/*
  JUWELIER GRIO — design system (v4, "Grün löst sich in Weiß auf")
  -------------------------------------------------------------------
  Redesign, not refinement: the v3 dark-green-everywhere system is fully
  replaced. Only the HERO carries deep Kieferngrün (RAL 6028, #2C5545,
  deepening toward #16302A) — it dissolves into white via a soft vertical
  gradient at the hero's own base. From there on, WHITE/off-white is the
  page's dominant ground; green and gold return only as accents (heading
  color touches, hairlines, small icon fills, the footer bookend).
  Tenor Sans (display) + Jost (body) — exactly two typefaces. Motion is a
  first-class material now: staggered scroll-reveal, a jewel-case opening
  animation on the homepage catalog, a slow continuously-rotating gem/ring
  line object in the hero, a quiet gold shine sweep on primary buttons —
  all transform/opacity only, IntersectionObserver-driven, fully inert
  under prefers-reduced-motion. Headings stay left-aligned with an image to
  their right, never centered — the one layout rule carried through every
  redesign of this project.
*/

/* ── Fonts ──────────────────────────────────────────────────────────── */
/* Self-hosted (keine Anfragen an fonts.googleapis.com / fonts.gstatic.com).
   Nur Latin-Subset (deckt deutsche Umlaute/ß über Latin-1 ab). Exakt zwei
   Schriftfamilien.
   Display = Tenor Sans (self-hosted von github.com/google/fonts, OFL) —
   abgelöst: Fraunces war dem vorherigen Feedback nach gelöst, jetzt ein
   klarer Schnitt-Wechsel zu einem eleganten geometrischen Sans-Serif.
   ANDERS als jede Displayschrift zuvor auf dieser Seite: Tenor Sans ist
   KEIN Variable Font und hat nur genau einen Schnitt (Regular/400) — es
   gibt keine Achsen zu tunen und keinen Bold-Schnitt zu wählen. Auf
   ausdrücklichen Wunsch bewusst unangetastet eingebunden: keine künstliche
   Verzerrung, kein fake-bold, keine ungewöhnlichen Einstellungen. Jedes
   font-weight im Type-Scale unten ist deshalb exakt 400 — alles andere
   würde der Browser mangels echtem Bold-Schnitt synthetisch (verzerrt)
   nachbilden, genau das soll vermieden werden. Fließtext = Jost. */
@font-face {
  font-family: "Tenor Sans";
  src: url("/assets/fonts/tenorsans.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("/assets/fonts/jost-variable.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* ── Tokens ─────────────────────────────────────────────────────────── */
:root {
  /* Pine green — hero + footer bookend ONLY, never a full content section.
     Deepened toward a Rolex-green register (v4.1): the two client-cited
     anchors #1E3D30 / #16302A now sit mid-scale (pine-800/pine-900) rather
     than at the top, so the whole hero gradient reads darker and richer —
     the old top-of-gradient highlight (pine-700, #3a6b57) is retired. */
  --pine-950: #0f231c;
  --pine-900: #16302a;
  --pine-800: #1e3d30;
  --pine-700: #2a4a3b;

  /* Paper — the page's dominant ground from just below the hero onward */
  --paper: #ffffff;
  --paper-dim: #fbfaf7;
  --paper-wash: #f2f5f2;

  /* Accent — warm gold, sparingly: hairlines, buttons, icons, hover.
     v4.2: deepened/enriched (was #c6a664/#ddc48f/#9c7f45) — the old set
     read as pale brass at a glance; this set keeps the same hue family
     but pulls saturation and depth up so it reads as genuine gold. A
     3-stop --gold-gradient token rides on top for buttons/gold text —
     a metallic sheen instead of a flat fill. */
  --gold: #b68d40;
  --gold-light: #e3c16f;
  --gold-dark: #8c6a2c;
  --gold-wash: rgba(182, 141, 64, 0.09);
  --gold-gradient: linear-gradient(150deg, var(--gold-light) 0%, var(--gold) 42%, var(--gold-dark) 75%, var(--gold) 100%);

  /* Text on pine (hero, footer, mobile drawer) — warm white, never gray */
  --on-pine: #ffffff;
  --on-pine-muted: rgba(255, 255, 255, 0.8);
  --on-pine-faint: rgba(255, 255, 255, 0.56);

  /* Text on paper (almost everywhere else) */
  --on-paper: #17241c;
  --on-paper-muted: #55625a;
  --on-paper-faint: #838f86;

  /* Borders */
  --line-on-paper: rgba(23, 36, 28, 0.12);
  --line-on-paper-strong: rgba(23, 36, 28, 0.22);
  --line-on-pine: rgba(255, 255, 255, 0.2);
  --line-on-pine-strong: rgba(255, 255, 255, 0.36);
  --line-gold: rgba(182, 141, 64, 0.42);
  --line-gold-strong: rgba(182, 141, 64, 0.62);

  /* Type */
  --font-display: "Tenor Sans", "Century Gothic", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Layout */
  --max-w: 1280px;
  --content-w: 66ch;
  --header-h: 108px;
  --header-h-mobile: 84px;

  /* Motion */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-md: 480ms;
  --dur-sm: 220ms;
}

/* ── Reset ──────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: hidden;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.7;
  color: var(--on-paper);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* overflow-x lives on <html> only (above) — setting it here too forces
     the browser to also resolve body's overflow-y to "auto", turning body
     into its own independent scroll container instead of the normal
     document/viewport scroll. That silently breaks position:sticky on
     .site-header (confirmed: header scrolled away instead of pinning). */
}

img,
picture,
svg {
  display: block;
  max-width: 100%;
}

/* <picture> is only a source-selection wrapper — it must not introduce its
   own box, so every existing `.parent img` layout rule keeps applying to
   the chosen <img> exactly as before it was wrapped. */
picture {
  display: contents;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

input,
textarea {
  font: inherit;
  color: inherit;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

/* ── Browser surfaces — themed, not left to defaults ──────────────────── */
::selection {
  background: var(--gold);
  color: var(--pine-950);
}

:focus-visible {
  outline: 2px solid var(--gold-dark);
  outline-offset: 3px;
}

/* Keyboard focus on the two pine-green surfaces (hero, footer, mobile
   drawer): the darker gold-dark ring is hard to see on deep green, so lift
   it to the lighter gold there. Pointer users are unaffected. */
.hero :focus-visible,
.page-hero :focus-visible,
.site-footer :focus-visible,
.mobile-nav :focus-visible {
  outline-color: var(--gold-light);
}

/* Anchor targets clear the sticky header instead of hiding beneath it.
   Mirrors the header-height breakpoint in .site-header below. */
:target {
  scroll-margin-top: calc(var(--header-h-mobile) + 20px);
}

@media (min-width: 860px) {
  :target {
    scroll-margin-top: calc(var(--header-h) + 20px);
  }
}

html {
  scrollbar-color: var(--gold-dark) var(--paper-wash);
  scrollbar-width: thin;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--paper-wash);
}

::-webkit-scrollbar-thumb {
  background: var(--gold-dark);
  border: 2px solid var(--paper-wash);
}

/* ── Type scale ─────────────────────────────────────────────────────── */
/* Fraunces is set with SOFT=100/WONK=0/opsz=24 baked into the subset (see
   the @font-face comment above) — round, calm, moderate stroke contrast,
   deliberately the "middle ground" between Jost and a dramatic display
   serif the client asked for. At those axis values Fraunces already reads
   solidly filled from ~500–560 up, same as it did with Playfair, so the
   weight scale carries over unchanged (560 base / 600 H1, never below
   500). What DOES change is size: Fraunces' rounded, SOFT-maxed forms sit
   Tenor Sans has exactly one weight (Regular/400 — see the @font-face
   comment above), so every rule below is pinned to font-weight:400; there
   is no "heavier for the hero" trick available anymore, and forcing a
   higher number would just make the browser fake-bold it (blurry,
   distorted strokes) instead of actually rendering bolder — precisely
   what was asked to avoid. Tenor Sans is also a notably WIDE, airy
   geometric sans — every clamp here is sized down again versus the
   Fraunces scale to keep headings from running too wide/wrapping
   awkwardly, and tracking is kept modest ("dezent, ruhig"): a font this
   open doesn't need much extra letter-spacing to breathe in caps. Line-
   height stays generous for multi-line titles — wide, thin caps read
   cramped without room between lines. */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.32;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--on-paper);
  /* A very long German compound on a narrow phone must break rather than
     run off the edge. Last-resort only (no hyphen char, no effect on
     desktop line-breaking). */
  overflow-wrap: break-word;
}

h1 {
  /* Mobile floor lowered again — Tenor Sans' wide letterforms need even
     more headroom than Fraunces did to keep long words from crowding a
     narrow phone screen. Desktop max also reduced (was 3.1rem). */
  font-size: clamp(1.5rem, 1.2rem + 1.35vw, 2.85rem);
  font-weight: 400;
  letter-spacing: 0.022em;
  line-height: 1.28;
}

h2 {
  font-size: clamp(1.22rem, 1.08rem + 0.72vw, 2rem);
  font-weight: 400;
  letter-spacing: 0.02em;
}

/* Only the smallest phones hyphenate — nicer than a mid-word chop for a
   compound like "Einzel­anfertigungen"; desktop never triggers this. H1 is
   deliberately excluded: combined with text-wrap:balance above, hyphens:
   auto on the biggest, most prominent heading on the page was splitting
   ordinary words ("Individu-ell") purely to even out line lengths, which
   reads far worse than an unbalanced but whole-word wrap. h2/h3 keep it
   for the genuine long-compound case. */
@media (max-width: 400px) {
  h2,
  h3 {
    hyphens: auto;
  }
}

h3 {
  font-size: clamp(0.98rem, 0.92rem + 0.32vw, 1.16rem);
  font-weight: 400;
  letter-spacing: 0.018em;
}

h4 {
  font-size: 0.98rem;
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: none;
  line-height: 1.3;
}

p {
  max-width: var(--content-w);
}

.lede {
  font-size: clamp(1.08rem, 1rem + 0.35vw, 1.28rem);
  line-height: 1.62;
  color: var(--on-paper-muted);
}

/* ── Layout helpers ─────────────────────────────────────────────────── */
.wrap {
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 56px);
}

/* Widescreen: --max-w (1280px) starts reading as a narrow island once the
   viewport clears ~1600px — huge equal margins either side, sections that
   never use the room they're given. Content itself doesn't need to grow
   (paragraphs stay capped at --content-w so lines don't over-run), but the
   container that positions images, cards and grids against does, so those
   elements get to sit further out and breathe instead of clustering in a
   1280px column on a 1920–2560px screen. Mobile/tablet (<1600px) untouched. */
@media (min-width: 1600px) {
  :root {
    --max-w: 1440px;
  }
}

.measure {
  max-width: var(--content-w);
}

section {
  position: relative;
  padding-block: clamp(60px, 9vw, 120px);
  background-color: var(--paper);
}

/* Subtle panel variant — a whisper off-white, still white, just enough to
   pace the scroll without ever reading as a color block. */
section[data-tone="dim"] {
  background-color: var(--paper-dim);
}

/* The one "accent band" left outside hero/footer — still on the paper
   family (never a green fill), distinguished by gold hairlines and a
   pine-colored heading rather than by a dark background. This is how
   trust/CTA moments keep a whisper of identity while green stays an
   accent, not a block. */
section[data-tone="ink"] {
  background-color: var(--paper-wash);
}

section[data-tone="ink"] h1,
section[data-tone="ink"] h2,
section[data-tone="ink"] h3 {
  color: var(--pine-800);
}

section[data-tone="ink"] p {
  color: var(--on-paper-muted);
}

.section-head {
  margin-bottom: clamp(32px, 5vw, 52px);
  max-width: 46rem;
}

/* ── Buttons ────────────────────────────────────────────────────────── */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 30px;
  font-family: var(--font-body);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid transparent;
  border-radius: 1px;
  white-space: nowrap;
  overflow: hidden;
  transition: background-color var(--dur-sm) ease, color var(--dur-sm) ease, border-color var(--dur-sm) ease,
    transform var(--dur-sm) ease;
}

.btn:active {
  transform: translateY(1px);
}

.btn-gold {
  background: var(--gold-gradient);
  color: var(--pine-950);
  /* thin bright top edge + soft dark underside — reads as a gently domed,
     polished metal surface instead of a flat color chip */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 rgba(0, 0, 0, 0.14);
}

.btn-gold:hover {
  background: linear-gradient(150deg, var(--gold-light) 0%, var(--gold-light) 32%, var(--gold) 68%, var(--gold-light) 100%);
}

/* Quiet, recurring shine sweep — a soft diagonal highlight drifting across
   gold buttons every few seconds. Never distracting: one thin band, long
   pause between passes. */
.btn-gold::after {
  content: "";
  position: absolute;
  inset: -40% -20%;
  background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.55) 50%, transparent 58%);
  transform: translateX(-140%);
  animation: btn-shine 5.5s ease-in-out infinite;
  pointer-events: none;
}

@keyframes btn-shine {
  0%,
  55% {
    transform: translateX(-140%);
  }
  75%,
  100% {
    transform: translateX(140%);
  }
}

.btn-outline-ink {
  border-color: var(--line-on-pine-strong);
  color: var(--on-pine);
}

.btn-outline-ink:hover {
  border-color: var(--gold);
  background: rgba(255, 255, 255, 0.08);
}

.btn-outline-paper {
  border-color: var(--line-on-paper-strong);
  color: var(--on-paper);
}

.btn-outline-paper:hover {
  border-color: var(--gold-dark);
  background: var(--gold-wash);
}

.btn svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* Inline text links within copy */
.text-link {
  position: relative;
  color: inherit;
  font-weight: 600;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-size: 100% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  padding-bottom: 1px;
  transition: background-size var(--dur-sm) var(--ease-out-expo);
}

.text-link:hover {
  background-size: 0% 1px;
  color: var(--gold-dark);
}

section[data-tone="ink"] .text-link:hover,
.hero .text-link:hover {
  color: var(--gold-light);
}

/* ── Header — white, sits above the green hero, gold hairline to ground it ── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-h-mobile);
  display: flex;
  align-items: center;
  background: var(--paper);
  border-bottom: 1px solid var(--line-gold);
  box-shadow: 0 1px 0 rgba(23, 36, 28, 0.04);
}

@media (min-width: 860px) {
  .site-header {
    height: var(--header-h);
  }
}

/* Mobile header (default, <1180px) — "Rubin"-style symmetric layout: two
   equal 40px icon tracks (menu, phone) bookend a flexible centered track
   that holds the logo. Because both side tracks and the gap either side of
   the middle track are equal, the logo lands on the wrap's true visual
   center via justify-self, not just the center of an arbitrary column.
   .main-nav has no area here — it's display:none below 1180px regardless
   (see below), so it never needs a reserved track on mobile. */
.site-header .wrap {
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  grid-template-areas: "menu logo actions";
  align-items: center;
  width: 100%;
  max-width: 1440px;
  padding-inline: clamp(24px, 6vw, 72px);
  gap: clamp(12px, 4vw, 24px);
}

.menu-toggle {
  grid-area: menu;
}

.brand {
  grid-area: logo;
  justify-self: center;
  display: flex;
  align-items: center;
  color: var(--on-paper);
  min-width: 0;
}

.main-nav {
  grid-area: nav;
}

.header-actions {
  grid-area: actions;
}

/* Desktop (≥1180px, the same breakpoint .main-nav already switches on) —
   the original three explicit tracks: logo | nav | actions, instead of
   flex space-between. With a 7-item nav and the larger v4 logo,
   space-between let the phone number get squeezed or overlap the nav on
   medium widths. auto/1fr/auto keeps logo and actions at their natural
   width and gives the nav a flexible, centered middle track that never
   steals their space. gap is a hard floor (not just a suggestion) between
   adjacent tracks — bumped to guarantee the nav→phone gap the client asked
   for (~2rem minimum) even at the narrower end of the desktop nav's range
   (1180–1300px), where 20px let "Termin anfragen" sit almost flush against
   the phone icon. */
@media (min-width: 1180px) {
  .site-header .wrap {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "logo nav actions";
    gap: clamp(32px, 4vw, 56px);
  }

  .brand {
    justify-self: start;
  }
}

/* Widescreen: keep the header band proportionally wider than the bumped
   --max-w below it (was already wider than .wrap at every size — same
   relationship carried up) instead of capping out at 1440px on a
   1920–2560px screen. */
@media (min-width: 1600px) {
  .site-header .wrap {
    max-width: 1600px;
  }
}

/* Logo, scaled up ~1.8x from the previous pass so it reads as present, not
   an afterthought in the corner. */
.brand__logo {
  display: block;
  height: 56px;
  width: auto;
}

@media (min-width: 860px) {
  .brand__logo {
    height: 76px;
  }
}

/* Desktop (from the same breakpoint the full nav switches on) — a
   noticeably bigger, more present logo. Header height stays fixed at
   --header-h (108px) at every size from 860px up, so 92/100px still sits
   with clean air above/below and never forces the header taller. Mobile
   (56px, above) is untouched. */
@media (min-width: 1180px) {
  .brand__logo {
    height: 92px;
  }
}

@media (min-width: 1600px) {
  .brand__logo {
    height: 100px;
  }
}

.brand__name {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 400;
  letter-spacing: 0.022em;
  text-transform: uppercase;
}

.brand__place {
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-dark);
  margin-top: 2px;
}

.main-nav {
  display: none;
}

/* Raised from 980px: with the bigger v4 logo and the phone number both
   needing their own room, seven nav items didn't fit cleanly until well
   past 980px — the drawer covers every width below this instead of
   letting the nav squeeze or wrap inside the sticky header. */
@media (min-width: 1180px) {
  .main-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(14px, 1.6vw, 28px);
    min-width: 0;
  }

  .main-nav a {
    position: relative;
    display: inline-block;
    white-space: nowrap;
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--on-paper-muted);
    padding-block: 6px;
    transition: color var(--dur-sm) ease;
  }

  .main-nav a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 100%;
    bottom: 0;
    height: 1px;
    background: var(--gold);
    transition: right var(--dur-sm) var(--ease-out-expo);
  }

  .main-nav a:hover {
    color: var(--pine-800);
  }

  .main-nav a:hover::after,
  .main-nav a[aria-current="page"]::after {
    right: 0;
  }

  .main-nav a[aria-current="page"] {
    color: var(--pine-800);
  }
}

.header-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  flex-shrink: 0;
}

.tel-link {
  display: none;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--on-paper);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.tel-link svg {
  width: 16px;
  height: 16px;
  color: var(--gold-dark);
  flex-shrink: 0;
}

/* Mobile-only call icon — the "Rubin"-style header's right-hand bookend.
   Same tel: link/target as .tel-link, just icon-only instead of icon+text,
   so it fits the 40px action track without crowding the centered logo.
   Swaps places with .tel-link exactly at the desktop breakpoint below. */
.tel-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--on-paper);
  flex-shrink: 0;
}

.tel-icon svg {
  width: 19px;
  height: 19px;
  color: var(--gold-dark);
}

@media (min-width: 1180px) {
  .tel-link {
    display: inline-flex;
  }

  .tel-icon {
    display: none;
  }
}

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--on-paper);
}

.menu-toggle svg {
  width: 22px;
  height: 22px;
}

.menu-toggle .icon-close {
  display: none;
}

.menu-toggle[aria-expanded="true"] .icon-open {
  display: none;
}

.menu-toggle[aria-expanded="true"] .icon-close {
  display: block;
}

@media (min-width: 1180px) {
  .menu-toggle {
    display: none;
  }
}

/* ── Mobile navigation — right-side drawer over a dimmed backdrop ─────────
   Replaces the old full-bleed dropdown. Backdrop fades in/out; the drawer
   itself slides in from the right edge. Both are inert (pointer-events:
   none, aria-hidden via JS) until opened, so they never block content or
   tab order when closed. ── */
.mobile-nav-backdrop {
  position: fixed;
  inset: 0;
  z-index: 95;
  background: rgba(22, 48, 42, 0.5);
  backdrop-filter: blur(2px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-md) ease;
}

html[data-nav-open="true"] .mobile-nav-backdrop {
  opacity: 1;
  pointer-events: auto;
}

.mobile-nav {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 96;
  width: 82%;
  max-width: 380px;
  background: var(--pine-950);
  padding: 24px 28px 32px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transform: translateX(100%);
  transition: transform var(--dur-md) var(--ease-out-expo);
  overflow-y: auto;
  box-shadow: -24px 0 64px -24px rgba(4, 16, 12, 0.5);
}

html[data-nav-open="true"] .mobile-nav {
  transform: translateX(0);
}

@media (min-width: 1180px) {
  .mobile-nav,
  .mobile-nav-backdrop {
    display: none;
  }
}

.mobile-nav__close {
  align-self: flex-end;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--on-pine);
  margin-bottom: 12px;
}

.mobile-nav__close svg {
  width: 22px;
  height: 22px;
}

.mobile-nav a {
  padding: 15px 0;
  border-bottom: 1px solid var(--line-on-pine);
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--on-pine);
}

.mobile-nav a[aria-current="page"] {
  color: var(--gold-light);
}

.mobile-nav .btn {
  margin-top: 24px;
  justify-content: center;
}

/* ── Hero — the ONLY full-green surface on the site ───────────────────── */
.hero {
  position: relative;
  background: radial-gradient(120% 100% at 15% 0%, var(--pine-700) 0%, var(--pine-800) 42%, var(--pine-900) 78%, var(--pine-950) 100%);
  color: var(--on-pine);
  overflow: hidden;
  /* Compact on purpose: H1 + lede + primary CTA must clear the fold on a
     375–414px phone without scrolling — no min-height:100vh trick, just a
     much smaller reserved top/bottom gap than the rest of the page. Extra
     bottom padding reserves room for the dissolve-to-white fade below. */
  padding-block: clamp(28px, 7vw, 72px) clamp(96px, 14vw, 168px);
}

/* Background photo slot — a real element (::before's background-image,
   not an <img>) since this is always above the fold on every page and
   must never be lazy-loaded or gate the H1's paint. Each page sets its
   own image via the --hero-bg-image custom property inline on the
   section tag; background-size:cover means one crop rule works for every
   photo regardless of its exact aspect. The radial-gradient on .hero
   itself stays as the base/fallback tone underneath. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-bg-image, none);
  background-size: cover;
  background-position: center;
  pointer-events: none;
}

/* Dark green wash over the photo — strong on purpose (78–88% opacity):
   the photo should read as schemenhaft, present but never competing with
   the headline or the pine palette. Sits above the photo, below the
   guilloché texture and the dissolve. */
.hero__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(165deg, rgba(15, 35, 28, 0.88) 0%, rgba(15, 35, 28, 0.78) 45%, rgba(15, 35, 28, 0.86) 100%);
  pointer-events: none;
}

/* Guilloché-inspired fine line texture — engine-turning arcs, gold on the
   green, kept far below decoration-becomes-noise: ~5% opacity, large tile,
   never competing with the text. Layered above the photo+overlay now, so
   it still reads as a texture over the image rather than being buried
   under it. */
.hero__texture {
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220' viewBox='0 0 220 220'%3E%3Cg fill='none' stroke='%23e3c16f' stroke-width='1'%3E%3Ccircle cx='110' cy='110' r='30' opacity='.5'/%3E%3Ccircle cx='110' cy='110' r='55' opacity='.4'/%3E%3Ccircle cx='110' cy='110' r='80' opacity='.3'/%3E%3Ccircle cx='0' cy='0' r='30' opacity='.5'/%3E%3Ccircle cx='0' cy='0' r='55' opacity='.4'/%3E%3Ccircle cx='220' cy='0' r='30' opacity='.5'/%3E%3Ccircle cx='220' cy='0' r='55' opacity='.4'/%3E%3Ccircle cx='0' cy='220' r='30' opacity='.5'/%3E%3Ccircle cx='0' cy='220' r='55' opacity='.4'/%3E%3Ccircle cx='220' cy='220' r='30' opacity='.5'/%3E%3Ccircle cx='220' cy='220' r='55' opacity='.4'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 220px 220px;
  opacity: 0.16;
  pointer-events: none;
}

/* Dissolve-to-white: a tall gradient sitting over the hero's own bottom
   edge so the green visibly softens into the page's white ground instead
   of cutting off hard. */
.hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(120px, 22vw, 260px);
  background: linear-gradient(180deg, rgba(22, 48, 42, 0) 0%, rgba(22, 48, 42, 0.7) 55%, var(--paper) 100%);
  pointer-events: none;
}

.hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: 28px;
  position: relative;
  z-index: 1;
}

.hero__inner {
  position: relative;
  z-index: 1;
  max-width: 100%;
}

@media (min-width: 900px) {
  .hero__inner {
    /* Was capped at 42rem (matched to the old 2-column split) — now that
       the gem sits behind the text instead of beside it, the headline
       gets to run wide, editorial-statement wide. */
    max-width: 46rem;
  }
}

@media (min-width: 1200px) {
  .hero__inner {
    max-width: 58rem;
  }
}

.hero h1 {
  color: var(--on-pine);
  /* Mobile gets a noticeably smaller display size than every other H1 on
     the site — this hero is the one place height is the constraint. Tenor
     Sans is wide and airy, so both ends of the clamp sit lower again than
     the Fraunces scale did to keep multi-word lines like "– Trauringe,"
     from crowding a narrow phone screen. */
  font-size: clamp(1.3rem, 1.02rem + 1.8vw, 2.85rem);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: 0.022em;
  text-shadow: 0 2px 28px rgba(0, 0, 0, 0.25);
}

/* Gold key words in the hero head — "Juwelier" and "Bad Homburg" carry the
   same gold-light tone + soft glow; everything else stays warm white. Where
   background-clip:text is supported, the flat tone is upgraded to the
   3-stop --gold-gradient so the words read as a soft metallic sheen rather
   than a flat highlight color; browsers without support keep the solid
   gold-light fallback above (no invisible text either way). */
.hero h1 em {
  font-style: normal;
  color: var(--gold-light);
  text-shadow: 0 0 18px rgba(227, 193, 111, 0.45), 0 2px 24px rgba(0, 0, 0, 0.2);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero h1 em {
    background: var(--gold-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.hero__lede {
  margin-top: 14px;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.2rem);
  color: var(--on-pine-muted);
  max-width: 38rem;
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 22px;
}

.hero__trust {
  margin-top: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 7px 20px;
}

.hero__trust-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.78rem;
  color: var(--on-pine-faint);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.hero__trust-item svg {
  width: 13px;
  height: 13px;
  color: var(--gold-light);
  flex-shrink: 0;
}

/* Fixed-width digits so the "35" count-up (main.js) doesn't nudge the
   surrounding trust-item text sideways as it ticks. */
.counter {
  font-variant-numeric: tabular-nums;
}

/* ── Luxury catalog grid (homepage) ────────────────────────────────────
   Near full-bleed 2×2: the grid breaks out of .wrap to run edge-to-edge of
   the viewport (standard 100vw/negative-margin breakout — safe because
   <html> already carries overflow-x:hidden, see above), then pulls back in
   by a slim clamped padding so the tiles keep a touch of air from the true
   screen edge instead of sitting flush against it. Tile height is capped
   independently of width from 560px up (see .catalog-tile media query)
   so stretching to full width on wide screens doesn't balloon height. ── */
.catalog-grid {
  display: grid;
  gap: clamp(14px, 2vw, 22px);
  grid-template-columns: 1fr;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  padding-inline: clamp(14px, 2vw, 22px);
}

@media (min-width: 560px) {
  .catalog-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* These four tiles are the most important photos on the homepage — always
   rendered fully visible in plain CSS, no class/JS/observer involved. A
   previous "bloom-in" animation (tiles starting at opacity:0 behind an
   IntersectionObserver + 2.5s safety-net timeout) has been removed: on a
   first load it could leave real product photos invisible for up to
   2.5 seconds, or hidden entirely if the observer never fired. Hover still
   gets a border/shadow lift. */
.catalog-tile {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--pine-900);
  border: 1px solid var(--line-on-paper);
  transition: border-color var(--dur-sm) ease, box-shadow var(--dur-sm) ease;
}

@media (min-width: 560px) {
  .catalog-tile {
    aspect-ratio: auto;
    height: clamp(280px, 30vw, 460px);
  }
}

.catalog-tile:hover {
  border-color: var(--gold);
  box-shadow: 0 18px 40px -20px rgba(23, 36, 28, 0.35);
}

.catalog-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--pine-900);
  color: var(--on-pine-faint);
  transition: transform 720ms var(--ease-out-expo);
}

.catalog-tile:hover img {
  transform: scale(1.045);
}

.catalog-tile__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(22, 48, 42, 0.18) 0%, rgba(22, 48, 42, 0.5) 60%, rgba(22, 48, 42, 0.86) 100%);
}

.catalog-tile__body {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  text-align: center;
  padding: 20px 16px clamp(22px, 4vw, 34px);
}

.catalog-tile__name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.1rem, 0.98rem + 0.6vw, 1.4rem);
  letter-spacing: 0.024em;
  text-transform: uppercase;
  color: var(--on-pine);
}

.catalog-tile__more {
  margin-top: 10px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-light);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--line-gold);
  transition: border-color var(--dur-sm) ease, color var(--dur-sm) ease;
}

.catalog-tile:hover .catalog-tile__more {
  color: var(--gold);
  border-color: var(--gold);
}

.catalog-tile__more svg {
  width: 13px;
  height: 13px;
  transition: transform var(--dur-sm) var(--ease-out-expo);
}

.catalog-tile:hover .catalog-tile__more svg {
  transform: translateX(3px);
}

/* Trauringkonfigurator badge — sits as a sibling of .catalog-tile (not a
   child) so it can be its own link without nesting an <a> inside the
   tile's own <a>. Positioned by the shared wrapper below. Small, dark-glass
   chip with a thin gold hairline so it reads as an accent label, not a
   second competing CTA. */
.catalog-tile-wrap {
  position: relative;
}

.catalog-tile__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: rgba(15, 35, 28, 0.55);
  backdrop-filter: blur(3px);
  border: 1px solid var(--line-gold-strong);
  color: var(--gold-light);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color var(--dur-sm) ease, border-color var(--dur-sm) ease, color var(--dur-sm) ease;
}

.catalog-tile__badge svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}

.catalog-tile__badge:hover {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--pine-950);
}

/* ── Trust / differentiators ───────────────────────────────────────── */
.trust-grid {
  display: grid;
  gap: clamp(28px, 4vw, 40px);
  grid-template-columns: 1fr;
  margin-top: 8px;
}

@media (min-width: 720px) {
  .trust-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.trust-item {
  padding-top: 22px;
  border-top: 1px solid var(--line-gold);
}

.trust-item svg {
  width: 26px;
  height: 26px;
  color: var(--gold-dark);
  margin-bottom: 18px;
}

.trust-item h3 {
  font-size: 1.1rem;
  margin-bottom: 10px;
}

.trust-item p {
  font-size: 0.95rem;
  color: var(--on-paper-muted);
}

/* Google-Bewertungen (Elfsight-Widget) — the widget script injects its
   own markup into this container, so we only own the outer box: centered,
   capped width so a wide desktop viewport doesn't stretch review cards
   edge-to-edge, and a min-height so the section doesn't collapse to ~0px
   and then jump once the external script has loaded (CLS). The min-height
   values are a reasonable estimate for the widget's typical rendered
   height, not an exact measurement — if the live widget renders shorter
   or taller, adjust these to match without touching anything else here. */
.reviews-widget {
  max-width: 900px;
  margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 32px);
  min-height: 340px;
}

@media (min-width: 700px) {
  .reviews-widget {
    min-height: 420px;
  }
}

/* Button unter dem Widget: auf Mobile sitzt er gut mit etwas Luft, auf
   Desktop wirkte der Abstand zu groß — dort deutlich enger an die
   Bewertungen heranrücken. Mobile-Wert bewusst unverändert. */
.reviews-cta {
  text-align: center;
  margin-top: 28px;
  margin-inline: auto;
}

@media (min-width: 860px) {
  .reviews-cta {
    margin-top: 4px;
  }
}

/* ── Find us / location ────────────────────────────────────────────── */
.location {
  display: grid;
  gap: clamp(36px, 5vw, 64px);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .location {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    align-items: start;
  }
}

.nap {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.nap__row {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.nap__row svg {
  width: 19px;
  height: 19px;
  color: var(--gold-dark);
  flex-shrink: 0;
  margin-top: 3px;
}

/* Field labels, not section headings — the NAP block sits directly under
   an h2 ("So finden Sie uns"), so these are deliberately a styled <p>
   rather than an h3/h4 that would misrepresent the outline. */
.nap__row .nap__label {
  margin-bottom: 4px;
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--on-paper);
}

.nap__row p,
.nap__row a {
  color: var(--on-paper-muted);
  font-size: 0.98rem;
}

.nap__row a:hover {
  color: var(--gold-dark);
}

.map-frame {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--paper-wash);
  border: 1px solid var(--line-on-paper-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

@media (min-width: 640px) {
  .map-frame {
    aspect-ratio: 16 / 10;
  }
}

.map-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  filter: grayscale(0.25) contrast(1.02);
}

/* The map's placeholder-before-consent styling (formerly .map-frame__cta)
   now lives in klaro-custom.css as .consent-placeholder, shared with the
   Elfsight placeholder — both are gated by the same Klaro consent
   mechanism, see index.html and main.js. */

/* ── Closing CTA band ──────────────────────────────────────────────────
   Heading stays left-aligned — never centered, per the fixed layout rule. */
.cta-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 8px;
}

/* ── Footer — the second (and last) green surface, bookending the hero ── */
.site-footer {
  background: var(--pine-950);
  color: var(--on-pine-faint);
  padding-block: 64px 32px;
  border-top: 1px solid var(--line-gold);
}

.footer-grid {
  display: grid;
  gap: 40px;
  grid-template-columns: 1fr;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--line-gold);
}

@media (min-width: 760px) {
  .footer-grid {
    grid-template-columns: 1.3fr 1fr 1fr 1fr;
  }
}

/* Real logo instead of a text lockup, so the footer carries the same mark
   as the header. This is a separate light-recolored export of the header
   PNG (logo-juwelier-grio-light-trimmed.png — "JUWELIER" turned white, the
   gold "GRIO" + swirl left untouched) rather than a CSS filter: an invert()
   would also flip the gold to an off color, and brightness()/contrast()
   can't lift true black off a dark background. The file is cropped tight
   to the mark's own ink (no more transparent canvas margin above/below),
   so the visible logo now starts flush with the column headings instead
   of floating ~30px below the shared top edge. Height only (width:auto)
   keeps the logo's own aspect ratio so nothing stretches; the three
   heights below are scaled down from the pre-crop values to land on the
   same rendered width as before (only the wasted vertical whitespace was
   removed, the mark itself isn't being resized). */
.footer-brand__logo {
  display: block;
  height: 32px;
  width: auto;
}

/* Mobile (einspaltiger Footer, viel Platz): Logo deutlich größer und
   präsenter. Ab 760px wird der Footer mehrspaltig und die Marken-Spalte
   schmaler — dort zurück auf die kompakte Größe. */
@media (max-width: 759px) {
  .footer-brand__logo {
    height: 44px;
  }
}

@media (min-width: 860px) {
  .footer-brand__logo {
    height: 40px;
  }
}

.footer-brand p {
  margin-top: 14px;
  font-size: 0.9rem;
  max-width: 32ch;
}

/* "Kontakt" is a <p class="footer-col__title">, not an <h4>: the footer's
   other column labels ("Sortiment", "Unternehmen") are <button> accordion
   toggles, not headings, so a lone <h4> here jumped the document's heading
   order (h2 → h4). Rendered identically — the extra font-weight/line-height
   below just restore what the global h4 rule used to supply. */
.footer-col h4,
.footer-col__title {
  color: var(--on-pine-muted);
  margin-bottom: 16px;
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  max-width: none;
}

.footer-col ul {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-col a,
.footer-col span {
  font-size: 0.92rem;
}

.footer-col a {
  position: relative;
  display: inline-block;
}

.footer-col a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -2px;
  height: 1px;
  background: var(--gold-light);
  transition: right var(--dur-sm) var(--ease-out-expo);
}

.footer-col a:hover {
  color: var(--gold-light);
}

.footer-col a:hover::after {
  right: 0;
}

/* ── Social / WhatsApp icon row — uniform 44×44 click target, icon exactly
   centered inside (see index.html: all three svgs now share one 18×18
   rounded-square frame at identical stroke-width, so they read as one set
   instead of three differently-weighted marks) ── */
.social-links {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
}

.social-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-on-pine-strong);
  color: var(--gold-light);
  transition: border-color var(--dur-sm) ease, color var(--dur-sm) ease;
}

.social-links a:hover {
  border-color: var(--gold);
  color: var(--gold);
}

.social-links svg {
  width: 20px;
  height: 20px;
  display: block;
}

.footer-bottom {
  padding-top: 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  justify-content: space-between;
  font-size: 0.8rem;
}

.footer-legal {
  display: flex;
  gap: 18px;
}

.footer-legal a,
.footer-legal button {
  position: relative;
}

.footer-legal a::after,
.footer-legal button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -2px;
  height: 1px;
  background: var(--gold-light);
  transition: right var(--dur-sm) var(--ease-out-expo);
}

.footer-legal a:hover::after,
.footer-legal button:hover::after {
  right: 0;
}

/* ── Footer accordion — mobile only ────────────────────────────────────
   Sortiment/Unternehmen and secondary contact details (email, fax,
   opening hours) collapse behind a toggle on small screens so the mobile
   footer doesn't run to several screens of scroll. NAP, the phone
   number, and the legal links (.footer-legal, above) are never inside a
   panel — they stay in normal flow on every breakpoint. From 760px up
   (same breakpoint as .footer-grid's column switch) the toggles become
   inert and every panel is forced open, so desktop is pixel-identical
   to a plain footer — no accordion behavior there at all. ── */
.footer-accordion-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  margin: 0 0 16px;
  padding: 0;
  color: var(--on-pine-muted);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.3;
  text-align: left;
}

.footer-accordion-toggle--sub {
  margin: 14px 0 0;
  color: var(--on-pine-faint);
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: none;
}

.footer-accordion-icon {
  flex: none;
  width: 11px;
  height: 7px;
  transition: transform var(--dur-sm) ease;
}

.footer-accordion-toggle[aria-expanded="true"] .footer-accordion-icon {
  transform: rotate(180deg);
}

.footer-accordion-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 360ms var(--ease-out-expo);
}

.footer-accordion-panel.is-open {
  max-height: 320px;
}

@media (min-width: 760px) {
  .footer-accordion-toggle {
    cursor: default;
    pointer-events: none;
  }

  .footer-accordion-icon {
    display: none;
  }

  .footer-accordion-panel,
  .footer-accordion-panel.is-open {
    max-height: none;
    overflow: visible;
  }

  .footer-accordion-toggle--sub {
    display: none;
  }

  .footer-accordion-item--sub .footer-accordion-panel {
    margin-top: 10px;
  }
}

/* ── Page hero (subpages: shorter, breadcrumb + H1) — same pine treatment
   as the homepage hero, without the rotating gem (kept as the homepage's
   own signature) but with the same guilloché texture + dissolve. ───── */
.page-hero {
  position: relative;
  background: radial-gradient(120% 140% at 15% 0%, var(--pine-700) 0%, var(--pine-800) 45%, var(--pine-900) 100%);
  color: var(--on-pine);
  overflow: hidden;
  padding-block: clamp(32px, 6.5vw, 72px) clamp(80px, 12vw, 140px);
}

/* Same photo/overlay/texture stack as .hero (shared .hero__overlay and
   .hero__texture classes below) — each subpage sets its own image via
   --hero-bg-image inline on the section tag. */
.page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-bg-image, none);
  background-size: cover;
  background-position: center;
  pointer-events: none;
}

/* Serve the hero photo as WebP where the browser can prove it supports
   image-set() with type() (Chrome/Edge 113+, Safari 17+, Firefox 113+ —
   the same generation that decodes WebP). Every page sets both custom
   properties inline; browsers that fail this @supports test keep the
   plain JPEG from the rules above. Deliberately placed after BOTH
   .hero::before and .page-hero::before (not right after .hero::before)
   so it wins the cascade for subpages too — an earlier placement here
   was silently overridden by .page-hero::before's own plain-JPEG rule,
   which sits later in the file, and every subpage hero loaded the JPEG
   even though its WebP was correctly preloaded and wastefully fetched
   alongside it. */
@supports (background-image: image-set(url("i.webp") type("image/webp"))) {
  .hero::before,
  .page-hero::before {
    background-image: var(--hero-bg-image-set, var(--hero-bg-image, none));
  }
}

.page-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(90px, 16vw, 180px);
  background: linear-gradient(180deg, rgba(22, 48, 42, 0) 0%, rgba(22, 48, 42, 0.65) 55%, var(--paper) 100%);
  pointer-events: none;
}

.page-hero .wrap {
  position: relative;
  z-index: 1;
}

.breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--on-pine-faint);
  margin-bottom: 14px;
}

.breadcrumbs a:hover {
  color: var(--gold-light);
}

.breadcrumbs li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.breadcrumbs li:not(:last-child)::after {
  content: "/";
  color: var(--on-pine-faint);
  opacity: 0.6;
}

.page-hero h1 {
  /* Full-width luxury statement; .wrap's own max-width is the only ceiling. */
  max-width: 100%;
  letter-spacing: 0.022em;
  color: var(--on-pine);
  text-shadow: 0 2px 28px rgba(0, 0, 0, 0.22);
}

@media (min-width: 700px) {
  .page-hero h1 {
    max-width: 44rem;
  }
}

@media (min-width: 1100px) {
  .page-hero h1 {
    max-width: 60rem;
  }
}

.page-hero .hero__lede {
  color: var(--on-pine-muted);
}

.page-hero .hero__ctas {
  margin-top: 18px;
}

/* ── Process steps (legitimate sequence — Goldankauf Ablauf, Trauring-Konfig) ──
   Gold hairline grid on white cards — the gold literally stitches each
   step to the next. One fine line icon per step in pine, above the gold
   counter number. ── */
.steps {
  counter-reset: step;
  display: grid;
  gap: 1px;
  background: var(--line-gold);
  border: 1px solid var(--line-gold);
  grid-template-columns: 1fr;
}

@media (min-width: 780px) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
  }
}

.step {
  counter-increment: step;
  background: var(--paper);
  padding: clamp(28px, 3.4vw, 40px);
}

.step__icon {
  width: 28px;
  height: 28px;
  color: var(--gold-dark);
  margin-bottom: 18px;
}

/* Line-draw: the icon's contour draws itself in as its .step scrolls into
   view, reusing the same data-reveal/.is-visible mechanism as the step's
   own fade+rise (no extra JS). 60 safely exceeds the real path length of
   these small 24×24 glyphs, so offset 60→0 always reads as a full draw. */
.step__icon path,
.step__icon circle {
  stroke-dasharray: 70;
  stroke-dashoffset: 70;
  transition: stroke-dashoffset 900ms var(--ease-out-expo) 180ms;
}

.step.is-visible .step__icon path,
.step.is-visible .step__icon circle {
  stroke-dashoffset: 0;
}

.step::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--gold-dark);
  letter-spacing: 0.1em;
  margin-bottom: 14px;
}

.step h3 {
  font-size: 1.05rem;
  margin-bottom: 10px;
  color: var(--on-paper);
}

.step p {
  font-size: 0.94rem;
  color: var(--on-paper-muted);
}

/* ── FAQ (details/summary — native, accessible, no JS) ────────────── */
.faq-list {
  border-top: 1px solid var(--line-gold);
}

.faq-item {
  border-bottom: 1px solid var(--line-gold);
}

.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 24px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--on-paper);
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary .plus {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  position: relative;
}

.faq-item summary .plus::before,
.faq-item summary .plus::after {
  content: "";
  position: absolute;
  background: var(--gold-dark);
  transition: transform var(--dur-sm) ease, opacity var(--dur-sm) ease;
}

.faq-item summary .plus::before {
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  transform: translateY(-50%);
}

.faq-item summary .plus::after {
  left: 50%;
  top: 0;
  width: 1px;
  height: 100%;
  transform: translateX(-50%);
}

.faq-item[open] summary .plus::after {
  opacity: 0;
}

.faq-item p {
  padding-bottom: 24px;
  color: var(--on-paper-muted);
  max-width: 60ch;
}

/* ── Trust bullet list (Goldankauf) ───────────────────────────────── */
.check-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.check-list li {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.check-list svg {
  width: 18px;
  height: 18px;
  color: var(--gold-dark);
  flex-shrink: 0;
  margin-top: 3px;
}

/* Editorial rhythm: the ratio varies deliberately per section instead of
   repeating the same split everywhere — .two-col (default, ~55/45),
   --wide (~60/40, more room for the image), --narrow (~52/48, near-even).
   --offset nudges the image column down/up for an asymmetric, non-grid
   feel. Content always comes first in the DOM (text left) regardless of
   ratio, per the fixed left/right rule. */
.two-col {
  display: grid;
  gap: clamp(36px, 5vw, 72px);
  grid-template-columns: 1fr;
}

@media (min-width: 860px) {
  .two-col {
    grid-template-columns: 1.1fr 0.9fr;
    align-items: start;
  }

  .two-col--wide {
    grid-template-columns: 1.5fr 1fr;
  }

  .two-col--narrow {
    grid-template-columns: 1.08fr 1fr;
  }

  .two-col--offset > *:last-child {
    margin-top: 56px;
  }
}

/* ── Full-bleed panel — the one rhythm-break per subpage where the photo
   runs to the viewport's own edge instead of stopping at .wrap's padding.
   Text keeps the normal wrap-measure via its own inline padding; the media
   column is a plain grid sibling outside any .wrap, so nothing constrains
   its right edge on desktop. Order in the DOM stays text-first (left) —
   the fixed rule — regardless of how the image renders. ── */
.bleed-section {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .bleed-section {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
  }
}

.bleed-section__text {
  padding: clamp(48px, 8vw, 96px) clamp(20px, 5vw, 56px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

@media (min-width: 900px) {
  .bleed-section__text {
    padding-right: clamp(32px, 5vw, 72px);
  }
}

/* Borderless on purpose: these photos have their own white studio
   background, so instead of cropping them edge-to-edge (object-fit:cover)
   behind a divider line, they sit centered and uncropped (contain) and
   melt straight into the page's own white — no box, no line between text
   and image. Placeholder tiles (still baked at their own exact target
   ratio) look identical either way, so this is a pure improvement for the
   real photos with no visible change for slots still waiting on one. */
.bleed-section__media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 320px;
  padding: clamp(24px, 4vw, 48px);
}

@media (min-width: 900px) {
  .bleed-section__media {
    min-height: 100%;
  }
}

.bleed-section__media img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 440px;
  object-fit: contain;
}

/* One bleed image asked to read larger/more present (Trauring-Konfigurator) —
   taller cap only, ratio untouched, still shrinks to fit narrow screens. */
.bleed-section__media--tall img {
  max-height: 600px;
}

/* ── Netlify Forms — appointment request ──────────────────────────────
   A quietly elevated card rather than a color inversion now that the
   whole page is already paper-toned: off-white fill, gold hairline,
   soft shadow give it just enough lift to read as "the important one". */
.form-panel {
  background: var(--paper-dim);
  color: var(--on-paper);
  padding: clamp(28px, 4vw, 44px);
  border: 1px solid var(--line-gold);
  box-shadow: 0 32px 64px -32px rgba(23, 36, 28, 0.22);
}

.field-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 20px;
}

.field-group label {
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  color: var(--on-paper-muted);
}

.field-group input,
.field-group select,
.field-group textarea {
  background: var(--paper);
  border: 1px solid var(--line-on-paper-strong);
  border-radius: 1px;
  padding: 13px 14px;
  color: var(--on-paper);
  transition: border-color var(--dur-sm) ease;
}

.field-group input::placeholder,
.field-group textarea::placeholder {
  color: var(--on-paper-faint);
}

.field-group input:focus,
.field-group select:focus,
.field-group textarea:focus {
  border-color: var(--gold-dark);
}

.field-row {
  display: grid;
  gap: 20px;
  grid-template-columns: 1fr;
}

@media (min-width: 560px) {
  .field-row {
    grid-template-columns: 1fr 1fr;
  }
}

.consent-group {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 20px;
}

.consent-group input[type="checkbox"] {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-top: 3px;
  accent-color: var(--gold-dark);
}

.consent-group label {
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--on-paper-muted);
}

.consent-group a {
  color: var(--on-paper);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.consent-group a:hover {
  color: var(--gold-dark);
}

.form-note {
  font-size: 0.78rem;
  color: var(--on-paper-faint);
  margin-top: 16px;
}

.form-success {
  /* Sichtbarkeit steuert das [hidden]-Attribut (main.js setzt s.hidden) —
     Aussehen identisch wie zuvor, nur der Ein-/Ausblend-Mechanismus. */
  background: var(--paper-dim);
  color: var(--on-paper);
  padding: clamp(28px, 4vw, 44px);
  border: 1px solid var(--line-gold);
  box-shadow: 0 32px 64px -32px rgba(23, 36, 28, 0.22);
  text-align: center;
}

.form-success[hidden] {
  display: none;
}

.form-success svg {
  width: 32px;
  height: 32px;
  color: var(--gold-dark);
  margin-inline: auto;
  margin-bottom: 16px;
}

/* ── Reveal-on-scroll ──────────────────────────────────────────────────
   Decorative-only from here on — trust-grid items, step icons' line-draw,
   the gold hairline draw-in. Real content (photos above all) is NEVER
   gated behind this: images used to carry a clip-path "reveal" here too,
   but that meant a genuinely invisible image (clip-path: inset(0 100% 0 0))
   sitting on a JS class that could fail to arrive (stale cached script,
   a backgrounded tab, an IntersectionObserver that never fires) — a real,
   reported bug ("Bilder erscheinen teils gar nicht"). Images are now plain
   markup with no reveal mechanism at all; only non-content decoration still
   opts in via data-reveal. :not(section) is deliberate: the six
   data-tone="ink" sections also carry data-reveal (for their hairline
   draw-in below), but a whole section must never sit at opacity:0 waiting
   on JS — only decorative pseudo-elements are allowed to depend on the
   observer for those. Grouped elements (trust-grid items, check-list rows)
   get an incremental transition-delay assigned in JS (main.js) based on
   their position among reveal-siblings, so a row feels choreographed
   rather than firing all at once — no extra markup needed per group. */
[data-reveal]:not(section) {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 680ms var(--ease-out-expo), transform 680ms var(--ease-out-expo);
}

[data-reveal]:not(section).is-visible {
  opacity: 1;
  transform: none;
}

/* Gold hairline draw-in on the six data-tone="ink" accent sections — the
   plain top/bottom border they used to carry is replaced by an animated
   line so it draws in on scroll instead of just sitting there. Section
   content itself is never gated on this (see :not(section) above). */
section[data-tone="ink"]::before,
section[data-tone="ink"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line-gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--ease-out-expo);
}

section[data-tone="ink"]::before {
  top: 0;
}

section[data-tone="ink"]::after {
  bottom: 0;
  transform-origin: right;
}

section[data-tone="ink"].is-visible::before,
section[data-tone="ink"].is-visible::after {
  transform: scaleX(1);
}

/* ── Utility ────────────────────────────────────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: -100px;
  left: 12px;
  z-index: 1000;
  background: var(--gold);
  color: var(--pine-950);
  padding: 12px 18px;
  font-weight: 600;
  transition: top var(--dur-sm) ease;
}

.skip-link:focus {
  top: 12px;
}

/* ── Photo positions (added once the client's real photography exists —
   these are the exact slots and dimensions from BILDPLAN.md; every <img>
   below already has final filename, width/height, and alt text set) ── */

.lead-band {
  aspect-ratio: 1600 / 720;
  overflow: hidden;
  background: var(--pine-900);
  border-top: 1px solid var(--line-gold);
  border-bottom: 1px solid var(--line-gold);
}

.lead-band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Matches .lead-band's own background so a not-yet-delivered photo (see
     BILDPLAN.md) reserves its slot in the page's own tone instead of
     flashing browser-default white before the real file lands. */
  background: var(--pine-900);
  color: var(--on-pine-faint);
}

/* No frame, no border — the photo's own white studio background melts
   into the page rather than sitting in a boxed card. The image keeps its
   OWN aspect ratio: the box is sized from the <img> width/height
   attributes (→ no layout shift), so the figcaption sits flush directly
   under the actual photo instead of under a pillar-boxed frame. */
.photo-frame img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 720ms var(--ease-out-expo);
}

.photo-frame:hover img {
  transform: scale(1.03);
}

/* Owner portrait (Über uns) — used nowhere else on the site. Deliberately
   capped well below its grid column's own width and centered in the
   leftover space: a modest, restrained photo so the text carries the page,
   not a dominant hero-sized portrait. Same cap at every size, mobile
   included. */
.photo-frame--portrait {
  max-width: 240px;
  margin-inline: auto;
}

.photo-frame figcaption {
  padding: 14px 4px 0;
  font-size: 0.82rem;
  color: var(--on-paper-faint);
}

.example-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(2, 1fr);
  margin-top: 24px;
}

@media (min-width: 640px) {
  .example-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Third example tile (Trauringe page only) — desktop/tablet exclusive. Below
   640px the grid itself is only 2 columns wide, so this third figure is
   hidden rather than wrapping to its own row; from 640px up (the same
   breakpoint the grid already switches to 3 columns at) it reappears and
   fills the third track exactly. */
.example-grid__desktop-only {
  display: none;
}

@media (min-width: 640px) {
  .example-grid__desktop-only {
    display: block;
  }
}

.example-grid figure {
  border: 1px solid var(--line-on-paper-strong);
  background: var(--pine-900);
  transition: border-color var(--dur-sm) ease;
  /* Without this, a grid item's default min-width:auto lets a broken/
     not-yet-loaded <img> (see BILDPLAN.md) report an oversized intrinsic
     size and blow the 1fr tracks out to equal *fixed* widths instead of
     splitting the row evenly — a well-known CSS Grid sizing gotcha. */
  min-width: 0;
}

.example-grid figure:hover {
  border-color: var(--gold);
}

.example-grid img {
  width: 100%;
  /* height must be explicit "auto" — aspect-ratio only fills in a
     dimension left as auto; the img's own HTML height="…" attribute
     (kept for layout-shift prevention) would otherwise win and ignore
     aspect-ratio entirely. */
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  background: var(--pine-900);
  color: var(--on-pine-faint);
  transition: transform 720ms var(--ease-out-expo);
}

.example-grid figure:hover img {
  transform: scale(1.045);
}

.example-grid figcaption {
  padding: 10px 12px;
  font-size: 0.78rem;
  color: var(--on-paper-faint);
  border-top: 1px solid var(--line-on-paper);
}

/* Quiet line beneath a set of example product photos — the muted paper-faint
   tone (never gold), small, sits like a fine caption under the row and reads
   as a footnote, not a call-out. */
.example-grid__note {
  margin-top: 12px;
  font-size: 0.76rem;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--on-paper-faint);
  max-width: 46rem;
}

/* Netlify-Vorschau-Badge ausblenden */
#netlify-badge,
.netlify-badge,
[id*="netlify" i],
[class*="netlify" i],
a[href*="netlify.com"],
a[href*="netlify.app"][target="_blank"] {
  display: none !important;
}
