/*
  Primitive und Muster, siehe Vellox-OS/07_ENGINEERING/03-komponentenarchitektur.md.
  Komponenten tragen eine Aufgabe per Attribut (intent, status), keine
  mehrdeutigen Modifier-Namen.
*/

/* ---------- Primitive ---------- */

.container {
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-inline: var(--space-3);
}

.stack > * + * {
  margin-top: var(--space-3);
}

.stack--tight > * + * {
  margin-top: var(--space-1);
}

.stack--loose > * + * {
  margin-top: var(--space-5);
}

.surface {
  background-color: var(--color-surface-elevated);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

.button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 600;
  padding: 0.85em 1.5em;
  border-radius: var(--radius-button);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  line-height: 1.2;
  /*
    Zwei Rhythmusfamilien in einem Button, siehe animation-plan.md:
    Farbwechsel bleiben kurz und direkt (--duration-state), damit der Button
    sofort auf den Hover antwortet, ohne träge zu wirken. Bewegung und
    Schatten laufen dagegen über --duration-spatial mit der weich
    auslaufenden --easing-emphasis, damit der Lift ruhig ausgleitet statt
    hart einzurasten. Dieselbe Kurve, die der Pfeil (.button__icon) bereits
    nutzt und die auch der große Hero-CTA seit Runde 14 trägt, jetzt einheitlich
    für alle Größen (siehe Runde 20).
  */
  transition: background-color var(--duration-state) var(--easing-standard),
    color var(--duration-state) var(--easing-standard),
    border-color var(--duration-state) var(--easing-standard),
    transform var(--duration-spatial) var(--easing-emphasis),
    box-shadow var(--duration-spatial) var(--easing-emphasis);
}

/*
  Touch-Feedback, siehe Runde 26. Ein Touchscreen kennt keinen Hover: Die
  gesamte Hover-Arbeit aus Runde 14, 15 und 20 ist auf dem Handy unsichtbar,
  und ein Antippen blieb bisher völlig ohne Rückmeldung, bis die nächste
  Seite geladen hatte. Der kurze Druckeindruck schließt genau diese Lücke.
  Er läuft bewusst über die kurze --duration-state statt über die weiche
  spatial-Familie, weil eine Bestätigung sofort kommen muss, nicht ausgleiten
  darf. transform und opacity laufen beide über den Compositor, siehe die
  Begründung zum Schatten in Runde 15.
*/
.button:active {
  transform: translateY(0) scale(0.97);
  transition: transform var(--duration-state) var(--easing-standard);
}

/*
  Die graue Standard-Aufblendung von iOS und Android passt nicht zur Palette
  und wirkt auf den warmen Flächen schmutzig. Ersetzt durch einen sehr
  leichten Salbeiton, der die Markenfarbe aufnimmt.
*/
a,
button,
summary,
[role="button"] {
  -webkit-tap-highlight-color: rgba(139, 138, 118, 0.18);
}

/*
  Primärfarbe Waldgrün statt Terrakotta, siehe design-direction.md, Runde 8.
  Gilt für jeden data-intent="primary"-Button im System, einschließlich des
  Formular-Absende-Buttons. Ausnahme: Auf einem bereits waldgrünen
  Forest-Band würde derselbe Ton unsichtbar verschmelzen, siehe die
  section--band-forest-Override weiter unten.
*/
.button[data-intent="primary"] {
  background-color: var(--color-surface-forest);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-sm);
}

.button[data-intent="primary"]:hover {
  background-color: var(--color-accent-text-hover);
  color: var(--color-on-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-button-hover);
}

.button[data-intent="secondary"] {
  background-color: transparent;
  color: var(--color-text);
  border-color: var(--color-text);
}

.button[data-intent="secondary"]:hover {
  background-color: var(--color-surface-inverse);
  color: var(--color-text-on-inverse);
  border-color: var(--color-surface-inverse);
  transform: translateY(-2px);
}

.button[data-intent="tertiary"] {
  background-color: transparent;
  color: var(--color-accent-text);
  padding-inline: 0;
  border: none;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.button[data-intent="tertiary"]:hover {
  color: var(--color-accent-text-hover);
  text-decoration-thickness: 2px;
}

.button[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/*
  Größenvariante für alleinstehende Handlungsflächen, aktuell nur der
  Hero-CTA. Größer, mit eigenem, weicherem Radius und einem sehr weichen,
  breit gestreuten Ruhe-Shadow, der die Fläche trägt statt sie leuchten zu
  lassen. Systementscheidung, siehe design-direction.md, Runde 6.
*/
.button[data-size="lg"] {
  position: relative;
  isolation: isolate;
  font-size: var(--text-body-lg);
  padding: 1.15em 2.3em;
  gap: var(--space-2);
  border-radius: var(--radius-button-lg);
  box-shadow: 0 10px 30px -8px rgba(30, 38, 23, 0.34);
  /*
    Eigene, langsamere Rhythmusfamilie für Lift und Fläche dieser
    Größenvariante: Der allgemeine Button-Hover ist bewusst kurz und direkt
    (--duration-state, siehe animation-plan.md), was bei einer so großen,
    alleinstehenden Fläche wie dem Hero-CTA aber hektisch statt hochwertig
    wirkt. transform läuft deshalb über --duration-spatial mit der weich
    auslaufenden --easing-emphasis, derselben Kurve, die der Pfeil
    (.button__icon) beim Hover schon nutzt, damit Fläche und Pfeil sich als
    eine einzige, zusammenhängende Bewegung lesen statt als zwei
    unterschiedlich schnelle.
  */
  transition: background-color var(--duration-state) var(--easing-standard),
    color var(--duration-state) var(--easing-standard),
    border-color var(--duration-state) var(--easing-standard),
    transform var(--duration-spatial) var(--easing-emphasis);
}

/*
  Der Hover-Schatten wird bewusst nicht über box-shadow selbst animiert:
  box-shadow läuft nicht über den Compositor, jede Zwischenstufe braucht ein
  neues Repaint, was auf schwächeren Geräten genau das stockende Ruckeln
  erzeugt, das der Auftraggeber zurückgemeldet hat. Stattdessen trägt ein
  eigenes ::after-Element bereits den fertigen, größeren Hover-Schatten und
  blendet nur seine Deckkraft ein, opacity und transform sind die einzigen
  Eigenschaften, die jeder Browser direkt auf der GPU animiert.
*/
.button[data-size="lg"]::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 22px 46px -10px rgba(30, 38, 23, 0.42);
  opacity: 0;
  transition: opacity var(--duration-spatial) var(--easing-emphasis);
}

.button[data-size="lg"][data-intent="primary"]:hover {
  transform: translateY(-4px);
  /*
    Setzt exakt den Ruhe-Wert erneut, um die weiter oben stehende, für
    kleine Buttons gedachte Regel `.button[data-intent="primary"]:hover`
    zu neutralisieren, die sonst hier ihren viel engeren
    --shadow-button-hover einsetzen und den Ruhe-Schatten dieser
    Größenvariante hart wechseln würde, gleichzeitig zur weichen
    ::after-Überblendung darunter. Der spürbare Zuwachs kommt allein aus
    dem ::after, die eigentliche box-shadow bleibt hier unverändert.
  */
  box-shadow: 0 10px 30px -8px rgba(30, 38, 23, 0.34);
}

.button[data-size="lg"][data-intent="primary"]:hover::after {
  opacity: 1;
}

.button__icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  transition: transform var(--duration-spatial) var(--easing-emphasis);
}

.button:hover .button__icon {
  transform: translateX(4px);
}

/*
  Sektionen mit dunklem Waldgrün-Band brauchen zwei Anpassungen. Der
  sekundäre Rahmen-Button braucht helle statt dunkle Ränder. Der primäre
  Button ist seit Runde 8 selbst waldgrün und würde auf gleichfarbigem Grund
  unsichtbar verschmelzen; er kehrt sich hier deshalb um: helle Fläche,
  dunkler Waldgrün-Text, dasselbe Prinzip wie beim Rahmen-Button.
*/
.section--band-forest .button[data-intent="secondary"] {
  color: var(--color-text-on-inverse);
  border-color: var(--color-text-on-inverse);
}

.section--band-forest .button[data-intent="secondary"]:hover {
  background-color: var(--color-text-on-inverse);
  color: var(--color-surface-forest);
  border-color: var(--color-text-on-inverse);
}

.section--band-forest .button[data-intent="primary"] {
  background-color: var(--color-text-on-inverse);
  color: var(--color-surface-forest);
}

.section--band-forest .button[data-intent="primary"]:hover {
  background-color: var(--color-surface-elevated);
  color: var(--color-surface-forest);
}

.field {
  display: block;
  margin-bottom: var(--space-3);
  max-width: var(--text-max-width);
}

/*
  Honeypot-Feld gegen einfache Formular-Bots, siehe api/contact.js. Für
  Menschen unsichtbar und über die Tab-Reihenfolge nicht erreichbar
  (tabindex="-1"), aber absichtlich nicht display:none, weil manche Bots
  genau danach filtern. Wird ausschließlich per Position aus dem
  sichtbaren Bereich verschoben, bleibt für Screenreader per aria-hidden
  auf dem Feld selbst ausgeblendet.
*/
.field--honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  margin: 0;
}

.field label {
  display: block;
  font-size: var(--text-label);
  font-weight: 600;
  margin-bottom: 0.4em;
}

.field .hint {
  display: block;
  font-size: var(--text-meta);
  color: var(--color-text-muted);
  margin-top: 0.3em;
}

.field input,
.field textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--text-body);
  padding: 0.7em 0.9em;
  border: 1px solid var(--color-text-muted);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface-elevated);
  color: var(--color-text);
}

.field textarea {
  min-height: 7rem;
  resize: vertical;
}

.field[data-status="error"] input,
.field[data-status="error"] textarea {
  border-color: var(--color-error);
}

.field-error {
  display: none;
  color: var(--color-error);
  font-size: var(--text-meta);
  margin-top: 0.35em;
}

.field[data-status="error"] .field-error {
  display: block;
}

/* ---------- Muster ---------- */

/*
  Sticky-Header ohne dauerhaften Border: die Trennkante erscheint erst, wenn
  der Nutzer gescrollt hat und der Header tatsächlich über Inhalt liegt.
  data-scrolled setzt assets/js/main.js, siehe initHeaderScroll(). Ohne
  JavaScript bleibt der Header voll bedienbar, nur ohne Blur-Zustand — die
  volle Grundfläche greift dann als Fallback, damit Text darüber nicht
  transparent auf Bild fällt.
*/
.site-header {
  background-color: var(--color-surface);
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid transparent;
  transition: background-color var(--duration-state) var(--easing-standard),
    border-color var(--duration-state) var(--easing-standard),
    backdrop-filter var(--duration-state) var(--easing-standard);
}

@supports ((-webkit-backdrop-filter: blur(12px)) or (backdrop-filter: blur(12px))) {
  .site-header[data-scrolled="true"] {
    background-color: rgba(231, 227, 220, 0.82);
    -webkit-backdrop-filter: saturate(140%) blur(12px);
    backdrop-filter: saturate(140%) blur(12px);
    border-bottom-color: rgba(36, 23, 16, 0.08);
  }
}

@supports not ((-webkit-backdrop-filter: blur(12px)) or (backdrop-filter: blur(12px))) {
  .site-header[data-scrolled="true"] {
    background-color: var(--color-surface);
    border-bottom-color: rgba(36, 23, 16, 0.08);
  }
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-3);
}

/*
  Geteilte Navigation mit dem Namen in der Mitte, siehe Runde 31. Zwei
  Rasterspalten zu je 1fr links und rechts, dazwischen eine auto-Spalte für
  den Namen: Weil beide Außenspalten per Definition gleich breit sind, sitzt
  der Name exakt mittig, unabhängig davon, wie unterschiedlich lang die
  Beschriftungen links und rechts sind. Eine absolut positionierte Mitte
  hätte dasselbe optische Ergebnis, könnte aber bei schmalerem Desktop mit
  der langen Beschriftung „Ablauf & Vitalstoff-Analyse" überlappen; das
  Raster reserviert den Platz stattdessen verlässlich.

  `display: contents` löst die Box des nav-Elements auf, damit seine beiden
  Listen direkt zu Rasterzellen der Kopfzeile werden und der Name zwischen
  ihnen stehen kann, ohne aus dem nav heraus verschoben zu werden. Die
  Landmarke bleibt dabei erhalten. Der Name muss außerhalb des nav bleiben,
  weil er auf dem Handy sichtbar sein soll, während das nav eingeklappt ist.

  Gilt bewusst erst oberhalb der Mobil-Schwelle: Auf dem Handy bleibt es bei
  Name links, Menü-Schaltfläche rechts und aufklappender Liste.
*/
/*
  Die Schwelle lag bis Runde 34 bei 43.8125rem (701px) und war geschätzt, nicht
  gemessen. Eine Messung an den realen Menüpunkten zeigt: Die Leiste braucht
  805px, damit „Ablauf & Vitalstoff-Analyse" und „Über mich" nicht umbrechen.
  Zwischen 701 und 805 Pixeln stand die Navigation deshalb zweizeilig da, die
  Kopfzeile wuchs von 80 auf 102 Pixel, und der Name in der Mitte saß neben
  gebrochenen Linkspalten. Die Schwelle liegt jetzt bei 51.3125rem (821px), mit
  einem kleinen Sicherheitsabstand für abweichende Schriftmetriken. Bis dahin
  bleibt die aufklappende Menü-Schaltfläche zuständig, die auf dieser Breite
  ohnehin gut bedienbar ist. Wenn ein Menüpunkt umbenannt wird, muss diese Zahl
  neu gemessen werden.

  Genau das ist in Runde 41 eingetreten. Mit der Verkürzung von
  „Ablauf & Vitalstoff-Analyse" auf „Ablauf & Analyse" braucht die Leiste nur
  noch 660 statt 805 Pixel: 208 Pixel linke Linkspalte, 179 Pixel rechte,
  132 Pixel Name, 64 Pixel Lücken, 48 Pixel Innenabstand. Die Schwelle lag
  damit 160 Pixel zu hoch, und zwischen 736 und 821 Pixeln erschien ohne Grund
  die Menü-Schaltfläche, obwohl die ausgeschriebene Leiste bequem gepasst
  hätte. Neu 46rem (736 Pixel), rund elf Prozent Luft über der gemessenen
  Mindestbreite; Systemschriften unterscheiden sich zwischen den
  Betriebssystemen in der Breite, dafür ist der Abstand da.
*/
@media (min-width: 46rem) {
  .site-header__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    column-gap: var(--space-4);
  }

  .site-nav {
    display: contents;
  }

  /*
    Alle drei Zellen ausdrücklich in Zeile 1. Ohne `grid-row` landet der Name
    in Zeile 1 Spalte 2, und die automatische Platzierung springt für die
    danach folgende linke Liste nicht mehr in Spalte 1 zurück, sondern legt
    eine zweite Zeile an. Der Name stand dadurch über statt neben den Links.
  */
  .site-nav__list--start {
    grid-column: 1;
    grid-row: 1;
    justify-content: flex-start;
  }

  .site-header__brand {
    grid-column: 2;
    grid-row: 1;
    justify-self: center;
  }

  .site-nav__list--end {
    grid-column: 3;
    grid-row: 1;
    justify-content: flex-end;
  }
}

.site-header__brand {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
  letter-spacing: -0.005em;
}

/*
  min-height/min-width 44px: Empfehlung von Apple und Google für sicher
  treffbare Bedienelemente. Der Menü-Button ist auf dem Handy die einzige
  Navigation und war vorher nur 32px hoch, siehe Runde 26.
*/
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--color-text);
  border-radius: var(--radius-sm);
  padding: 0.5em 0.8em;
  min-height: 44px;
  min-width: 44px;
  font-size: var(--text-label);
  cursor: pointer;
}

.site-nav__list {
  display: flex;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav__list a {
  position: relative;
  color: var(--color-text);
  text-decoration: none;
  font-size: var(--text-label);
  font-weight: 600;
  padding-bottom: 0.3em;
}

/*
  Ein Unterstrich, der beim Hover aus der Fläche wächst, statt sofort zu
  erscheinen. Dieselbe Bewegungsaufgabe wie der wachsende Akzent-Unterstrich
  unter Abschnittsüberschriften (siehe .section__heading::after), hier auf
  die Navigation übertragen, damit ein Muster das System trägt statt zwei
  unabhängiger Hover-Ideen.
*/
.site-nav__list a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background-color: var(--color-accent-text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--duration-state) var(--easing-standard);
}

.site-nav__list a:hover::after,
.site-nav__list a:focus-visible::after,
.site-nav__list a:active::after {
  transform: scaleX(1);
}

.site-nav__list a[aria-current="page"] {
  color: var(--color-accent-text);
}

.site-nav__list a[aria-current="page"]::after {
  transform: scaleX(1);
}

@media (max-width: 45.9375rem) {
  .nav-toggle {
    display: inline-block;
  }

  /*
    Orientierende Bewegung, siehe animation-plan.md: die Höhe erklärt, dass
    das Menü aus der Navigationsleiste heraus erscheint, nicht dass es
    plötzlich da ist. Position absolute statt normaler Flex-Fluss, weil das
    Nav-Element sonst als drittes Flex-Kind neben Marke und Menü-Button
    Breite beansprucht (auch mit `grid-template-rows: 0fr` bleibt die
    Spaltenbreite erhalten) und `justify-content: space-between` den
    Menü-Button dadurch in die Mitte statt an den rechten Rand schiebt.
  */
  .site-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    padding-inline: var(--space-3);
    background-color: var(--color-surface);
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    overflow: hidden;
    /*
      visibility: hidden nimmt die eingeklappten Links aus der Tab-Reihenfolge,
      damit eine Tastaturnutzerin nicht in ein optisch verborgenes Menü tabbt.
      Die Umschaltung ist verzögert (0s nach der Ausklapp-Dauer), damit die
      Schließ-Animation noch sichtbar abläuft, bevor das Menü fokusfrei wird.
    */
    visibility: hidden;
    transition: grid-template-rows var(--duration-spatial) var(--easing-standard),
      opacity var(--duration-spatial) var(--easing-standard),
      visibility 0s linear var(--duration-spatial);
  }

  .site-nav > * {
    min-height: 0;
  }

  .site-nav[data-open="true"] {
    grid-template-rows: 1fr;
    opacity: 1;
    visibility: visible;
    border-top: 1px solid rgba(36, 23, 16, 0.08);
    transition: grid-template-rows var(--duration-spatial) var(--easing-standard),
      opacity var(--duration-spatial) var(--easing-standard),
      visibility 0s linear 0s;
  }

  /*
    Der Abstand zwischen den Menüeinträgen kommt jetzt aus dem Innenabstand
    der Links statt aus einem Gap. Optisch bleibt der Rhythmus ähnlich, aber
    die Fläche zwischen den Einträgen ist nicht länger tot: Vorher war nur
    der Text selbst treffbar (20px hoch), wer knapp daneben tippte, traf
    nichts. Siehe Runde 26.
  */
  .site-nav__list {
    flex-direction: column;
    gap: 0;
    padding-block: var(--space-1);
  }

  /*
    Die Navigation besteht seit Runde 31 aus zwei Listen, damit der Name auf
    dem Desktop dazwischen stehen kann. Auf dem Handy sollen sie als eine
    durchgehende Liste gelesen werden, deshalb entfällt der Innenabstand
    zwischen ihnen; sonst entstünde in der Mitte eine unerklärliche Lücke.
  */
  .site-nav__list--start {
    padding-bottom: 0;
  }

  .site-nav__list--end {
    padding-top: 0;
  }

  .site-nav__list a {
    display: block;
    padding-block: 0.75rem;
  }

  .site-nav__list a::after {
    bottom: 0.6rem;
  }

  .site-header__brand {
    padding-block: 0.4rem;
  }
}

.hero {
  padding-block: var(--space-5) var(--space-6);
}

.hero__grid {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}

.hero__portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 56rem) {
  .hero__grid {
    grid-template-columns: 3fr 2fr;
  }

  .hero__portrait {
    max-height: 26rem;
  }
}

.hero__portrait {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

/*
  Page-Hero: einheitlicher Auftakt für alle Sub-Seiten (Über mich, Ablauf,
  Häufige Fragen, Kontakt), eingeführt in Runde 9. Ersetzt die bisherigen,
  visuell schwachen reinen Text-Heros durch dieselbe Editorial-Signatur wie
  der Startseiten-Hero: kleine, ruhige Uppercase-Eyebrow, große Serifen-
  Headline, ergänzender Lead. Optional mit Portrait auf Über mich. Kein
  90vh-Bühnen-Zwang wie auf der Startseite; die Sub-Seiten sind Kapitel,
  keine Bühnen, und dürfen sofort in ihren Inhalt übergehen.
*/
.page-hero {
  padding-block: var(--space-6) var(--space-5);
}

.page-hero__inner {
  max-width: 42rem;
}

.page-hero__eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin: 0 0 var(--space-3);
}

.page-hero h1 {
  margin-top: 0;
  margin-bottom: var(--space-3);
  letter-spacing: -0.015em;
}

.page-hero__lead {
  font-size: var(--text-body-lg);
  color: var(--color-text-muted);
  max-width: 36rem;
  margin: 0;
}

/*
  Handlung im Kopf der Unterseiten, siehe Runde 36. Der Abstand entspricht dem
  Verhältnis im Hero der Startseite, damit beide Einstiege denselben Rhythmus
  haben. Auf schmalen Geräten läuft die Schaltfläche über die volle Breite wie
  der Hero-CTA der Startseite, aus demselben Grund: Eine halbbreite Fläche
  neben Leerraum wirkt auf einem Telefon wie ein Rest, nicht wie ein Angebot.
*/
.page-hero__cta {
  margin-top: var(--space-4);
}

@media (max-width: 43.75rem) {
  .page-hero__cta {
    display: flex;
    width: 100%;
    justify-content: center;
  }
}

@media (min-width: 56rem) {
  .page-hero {
    padding-block: var(--space-7) var(--space-6);
  }

  .page-hero--with-portrait {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    column-gap: var(--space-6);
    align-items: center;
  }
}

.page-hero__portrait {
  display: block;
  margin: var(--space-4) 0 0;
  max-width: 22rem;
}

.page-hero__portrait img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center 20%;
  border-radius: var(--radius-portrait);
  box-shadow: 0 24px 48px -28px rgba(36, 23, 16, 0.28);
}

@media (min-width: 56rem) {
  .page-hero__portrait {
    margin: 0;
    justify-self: end;
  }
}

/*
  Premium-Hero der Startseite, siehe 00_PLANUNG/design-direction.md, Runde 5.
  .hero/.hero__grid/.hero__portrait weiter oben bleiben für die anderen Seiten
  bestehen. Der Block trägt allein den ersten Bildschirm: Bühne (mindestens
  90vh ab dem 2-Spalten-Breakpoint), zwei ruhige Spalten mit deutlichem
  Abstand, ein einziger dominanter CTA. Farbige Grundfläche und Typo-Familien
  stammen unverändert aus den bestehenden Tokens; neu sind ausschließlich die
  benannten Rollen --text-hero, --radius-portrait, --radius-button-lg.

  Der Hintergrund kombiniert die Grundfläche mit drei sehr schwachen Ebenen,
  siehe design-direction.md, Runde 6: ein warmer radialer Schimmer oben links,
  ein hellerer Glow rechts hinter dem Portrait und ein kaum wahrnehmbarer
  vertikaler Verlauf, der die Fläche nach unten minimal absenkt. Alle liegen
  bei etwa 3 bis 5 % Wirkung und sind reine Atmosphäre; die Struktur der Seite
  muss ohne sie tragen (Graustufen-Test). Ziel ist Tiefe, die man eher fühlt
  als sieht.
*/
.hero-editorial {
  position: relative;
  padding-block: var(--space-5) var(--space-6);
  overflow-x: clip;
  background:
    radial-gradient(58rem 44rem at 10% 4%, rgba(154, 95, 60, 0.055), transparent 58%),
    radial-gradient(52rem 46rem at 90% 46%, rgba(255, 250, 242, 0.9), transparent 62%),
    linear-gradient(180deg, rgba(255, 253, 250, 0.5) 0%, transparent 34%, rgba(36, 28, 20, 0.02) 100%);
}

/*
  Breite und Innenabstand bewusst identisch zu `.container`, siehe Runde 29.
  Vorher trug dieses Grid mit 82rem einen eigenen, fest eingetragenen Wert,
  während alle übrigen Abschnitte über den Token liefen. Auf schmalen
  Bildschirmen fiel das nicht auf, weil beide am Rand anstießen; ab etwa
  1300px lief die Fluchtlinie sichtbar auseinander, der Hero hing 92px weiter
  links als Kopfzeile, Abschnitte und Fußzeile. Der Verweis auf den Token
  statt auf eine zweite Zahl schließt diese Fehlerquelle dauerhaft.
*/
.hero-editorial__grid {
  display: grid;
  gap: var(--space-5);
  /*
    `width: 100%` ist hier nicht redundant, siehe Runde 35. Ab 56rem ist das
    umgebende `.hero-editorial` selbst ein Grid, und ein Grid-Kind mit
    `margin-inline: auto` streckt sich nicht: Die automatischen Ränder nehmen
    den freien Platz auf, das Element schrumpft auf seine Inhaltsbreite. Solange
    beide Hero-Spalten feste Obergrenzen hatten, ergab das zufällig genau die
    Containerbreite, und der Fehler blieb unsichtbar. Mit einer mitwachsenden
    Inhaltsbreite trat er als 120-Pixel-Versatz gegen Kopfzeile, Abschnitte und
    Fußzeile hervor. Die explizite Breite stellt das Strecken wieder her; die
    automatischen Ränder zentrieren weiterhin, sobald `max-width` greift.
  */
  width: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-inline: var(--space-3);
}

.hero-editorial__content {
  display: grid;
  gap: 0;
  justify-items: start;
  max-width: 32.5rem;
}


.hero-editorial__title {
  font-size: var(--text-hero);
  line-height: var(--line-height-hero);
  letter-spacing: var(--letter-spacing-hero);
  margin: 0;
  margin-top: var(--space-3);
  max-width: 32.5rem;
}

.hero-editorial__lead {
  font-size: var(--text-body-lg);
  color: var(--color-text-muted);
  max-width: 32.5rem;
  margin: 0;
  margin-top: var(--space-4);
}

.hero-editorial__cta {
  margin-top: var(--space-4);
}


/*
  Trust-Liste: gleichrangige Belege für dieselbe Frage („warum vertraue ich
  dieser Person?"), deshalb ausnahmsweise ein Dreier-Muster, siehe
  design-direction.md, Runde 5. Als leichte Textzeile mit Haken gestaltet,
  ausdrücklich NICHT als Card-Trio, damit sie das im Anti-Template-Standard
  benannte Muster „drei gleichartige Vorteilskarten" nicht bedient.
*/
.hero-editorial__trust {
  list-style: none;
  padding: 0;
  margin: 0;
  margin-top: var(--space-4);
  display: grid;
  gap: var(--space-2);
  font-size: var(--text-meta);
  color: var(--color-text-muted);
}

.hero-editorial__trust li {
  display: flex;
  align-items: center;
  gap: 0.6em;
}

/*
  Bewusst ein anderer Grünton als der Waldgrün-Button, siehe design-direction.md,
  Runde 8: das bereits vorhandene Marken-Olivgrün --color-accent-hover, damit
  die Haken nicht mit dem Button verschmelzen und trotzdem in derselben
  Grünfamilie bleiben, keine neue Farbe.
*/
.hero-editorial__trust svg {
  flex-shrink: 0;
  width: 1.05em;
  height: 1.05em;
  color: var(--color-accent-hover);
}

/*
  Portrait: weicher Radius, engerer Ausschnitt für mehr Präsenz, ein sehr
  weicher Glow als ::before dahinter. Das Bild bleibt ohne Karten-Schatten,
  der Glow übernimmt die Aufgabe „Tiefe" wesentlich leiser.
*/
.hero-editorial__figure {
  position: relative;
  isolation: isolate;
  margin: 0;
  align-self: center;
  justify-self: center;
  width: 100%;
  max-width: 37.5rem;
}

/*
  Sehr weicher, großzügig ausgedehnter Glow hinter dem Portrait, siehe
  Runde 6. isolation:isolate oben begrenzt den Stacking-Context, damit
  z-index:-1 den Glow nicht hinter das Section-Background schiebt (dort
  würde er von overflow-x:clip verschluckt). Der Glow reicht weiter über
  die Kanten hinaus und läuft früher aus, damit er als Atmosphäre wirkt,
  nicht als sichtbarer Ring.
*/
.hero-editorial__figure::before {
  content: "";
  position: absolute;
  inset: -16% -14% -12% -14%;
  background: radial-gradient(closest-side, rgba(255, 248, 236, 0.85), transparent 72%);
  z-index: -1;
  pointer-events: none;
}

/*
  Weicher, gerichteter Trag-Schatten statt eines Karten-Schattens: hohe
  Unschärfe, negativer Spread, tiefer Versatz nach unten. Er erdet das
  Portrait und gibt ihm Präsenz, ohne als Kante sichtbar zu werden.
*/
.hero-editorial__figure img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center 18%;
  border-radius: var(--radius-portrait);
  display: block;
  box-shadow: 0 34px 64px -34px rgba(36, 23, 16, 0.34);
}

@media (min-width: 56rem) {
  .hero-editorial {
    min-height: 90vh;
    min-height: 90svh;
    display: grid;
    align-content: center;
    padding-block: var(--space-6);
  }

  .hero-editorial__grid {
    grid-template-columns: minmax(0, 30rem) minmax(0, 32rem);
    column-gap: var(--space-7);
    row-gap: 0;
    align-items: center;
    justify-content: center;
  }

  /*
    Minimale editoriale Verschiebung aus der perfekten Symmetrie, siehe
    Runde 6: das Portrait sitzt einen kleinen Schritt tiefer als die
    optische Mitte des Textblocks. Bewusst subtil, damit die Komposition
    ruhig bleibt und nur der technisch-sterile Eindruck verschwindet.
  */
  .hero-editorial__figure {
    transform: translateY(1.5rem);
  }

  .hero-editorial__figure img {
    max-height: 62vh;
  }
}

/*
  Die zweite Spalte nimmt seit Runde 35 den Rest der Zeile statt eines festen
  Maximums. Grund ist die jetzt mitwachsende Inhaltsbreite: Solange beide
  Spalten feste Obergrenzen hatten, blieb das Hero-Raster ab etwa 2000px
  schmaler als der Container, und `justify-content: center` schob es mittig
  hinein. Der Hero-Text begann dadurch auf einem 2560px-Bildschirm 68 Pixel
  weiter rechts als Kopfzeile, Abschnitte und Fußzeile, also derselbe Fehler
  wie in Runde 29, nur an einer anderen Stelle ausgelöst.

  Die Textspalte behält ihre 31rem, damit sich an den Zeilenumbrüchen der
  Headline nichts ändert. Das Portrait behält seine Größe ebenfalls, weil
  `.hero-editorial__figure` bei 37.5rem gedeckelt ist und mittig in seiner
  Spalte sitzt; die überschüssige Breite landet als Luft neben dem Bild statt
  als Versatz unter der Fluchtlinie.
*/
@media (min-width: 78rem) {
  .hero-editorial__grid {
    grid-template-columns: minmax(0, 31rem) minmax(0, 1fr);
    column-gap: var(--space-8);
  }
}

@media (max-width: 55.9375rem) {
  /*
    Mobile-Reihenfolge: Headline → Portrait → Lead → CTA → Trust.
    Auf Mobile hebt display:contents den Content-Wrapper visuell auf, damit
    Grid-Kinder direkt geordnet werden können; die Figure rutscht per order
    zwischen H1 und Lead. Semantik und Screenreader-Reihenfolge bleiben
    unverändert (DOM: H1, Lead, CTA, Trust, Figure).
  */
  .hero-editorial__grid {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .hero-editorial__content {
    display: contents;
  }

  .hero-editorial__title { order: 2; }
  .hero-editorial__figure { order: 3; }
  .hero-editorial__lead { order: 4; }
  .hero-editorial__cta { order: 5; }
  .hero-editorial__trust { order: 6; }

  /*
    Der erste Bildschirm, siehe Runde 34. Gemessen auf einem 390 Pixel breiten
    Gerät bestand er vorher aus Kopfzeile (92px), Headline (132px) und Portrait
    (428px). Danach war der Bildschirm zu Ende. Der Satz, der erklärt, worum es
    geht, begann bei 805 Pixeln, der Handlungs-Button bei 895: Beide lagen
    unterhalb der Kante. Ein Erstbesucher sah also ein Foto und eine
    Überschrift, aber keinen Grund und keinen nächsten Schritt.

    Der Engpass war das Portrait im Hochformat 4:5, das mit 428 Pixeln mehr als
    die Hälfte des sichtbaren Bereichs belegte. Auf dem Handy trägt es jetzt
    einen eigenen Ausschnitt im Querformat 5:4 und wird von oben beschnitten:
    Kopf, Schultern und Brust bleiben, der untere Bildteil und ein Großteil der
    strukturierten Wand entfallen. Das ist kein Kompromiss, sondern ein
    Gewinn — der Ausschnitt zeigt mehr Gesicht auf weniger Fläche, und Gesicht
    ist hier das Vertrauensargument, nicht die Wand.

    Zusammen mit den enger gezogenen Abständen sinkt der Handlungs-Button von
    895 auf rund 650 Pixel und liegt damit auf jedem üblichen Gerät sichtbar
    über der Kante. Am Schreibtisch bleibt das Hochformat unverändert, dort
    steht das Portrait in einer eigenen Spalte und hat den Platz dafür.
  */
  .hero-editorial {
    padding-block: var(--space-3) var(--space-5);
  }

  .hero-editorial__figure {
    max-width: 26rem;
    align-self: center;
    margin-block: var(--space-3);
  }

  .hero-editorial__figure img {
    aspect-ratio: 3 / 2;
    object-position: center 4%;
  }

  .hero-editorial__title {
    margin-top: 0;
  }

  .hero-editorial__lead {
    margin-top: 0;
  }

  /*
    Der Button ist ein Flex-Kind der Hero-Spalte und wurde von
    `align-items: stretch` bisher auf die volle Zeilenbreite gezogen. Auf einem
    Telefon war das richtig und ausdrücklich gewollt (siehe die Regel unter
    43.75rem), auf einem Tablet ergab es eine über 700 Pixel breite grüne
    Fläche für zwei Wörter. Er sitzt jetzt auf seiner Inhaltsbreite und mittig;
    die schmalere Stufe überschreibt das weiterhin mit `width: 100%`.
  */
  .hero-editorial__cta {
    margin-top: var(--space-3);
    align-self: center;
  }

  /*
    Zentrierung nur auf Mobile, siehe Runde 33. Am Schreibtisch steht der
    Textblock in einer zweispaltigen Komposition neben dem Portrait; dort trägt
    die gemeinsame linke Kante die Ordnung, und eine Zentrierung würde jede
    Zeile an einer anderen Stelle beginnen lassen. Auf dem Handy gibt es diese
    zweite Spalte nicht mehr: Headline, Portrait, Lead, Button und Belege
    stehen untereinander auf einer schmalen Achse, und das Portrait ist bereits
    mittig gesetzt. Eine linksbündige Textspalte neben einem zentrierten Bild
    liest sich dort als Versatz, nicht als Kante. Die Zentrierung gilt deshalb
    ausschließlich für die kurzen Hero-Zeilen und ausdrücklich nicht für den
    Fließtext der übrigen Abschnitte, wo zentrierte Blocksätze das Lesen
    erschweren würden.
  */
  .hero-editorial__title,
  .hero-editorial__lead {
    text-align: center;
    margin-inline: auto;
  }

  /*
    Die Belegzeilen bleiben intern linksbündig (Haken, dann Text), aber die
    Zeile als Ganzes rückt in die Mitte. justify-items wirkt hier auf die
    Listeneinträge des Grids, jeder schrumpft dadurch auf seine Inhaltsbreite
    und wird zentriert; das Haken-Text-Paar bleibt als Einheit erhalten.
  */
  .hero-editorial__trust {
    justify-items: center;
  }

  /*
    Größenhierarchie für den ersten Bildschirm, siehe Runde 33. Zusammen mit
    der angehobenen Headline-Untergrenze in tokens.css ergibt sich auf 390px
    ein Verhältnis von 44 / 20 / 18 / 15 Pixeln über Headline, Lead, Button und
    Belege. Jede Stufe ist damit deutlich als eigene Ebene erkennbar, während
    vorher 38 / 18 / 18 / 13 galt: Lead und Button lagen exakt gleichauf, und
    die Belegzeile war so klein, dass sie eher wie eine Fußnote als wie ein
    Argument wirkte.
  */
  .hero-editorial__lead {
    font-size: 1.25rem;
    line-height: 1.45;
  }

  .hero-editorial__trust {
    font-size: 0.9375rem;
  }
}

@media (max-width: 43.75rem) {
  .hero-editorial__cta.button[data-size="lg"] {
    width: 100%;
    justify-content: center;
  }
}

.section {
  padding-block: var(--space-6);
  position: relative;
}

.section--muted {
  background-color: var(--color-surface-elevated);
}

.section--boundary {
  padding-block: var(--space-7);
  background-color: var(--color-surface-elevated);
  border-top: 1px solid rgba(36, 23, 16, 0.12);
  border-bottom: 1px solid rgba(36, 23, 16, 0.12);
}

/*
  Farbige Sektions-Bänder aus der Broschüren-Palette, siehe design-direction.md.
  Jedes Band trägt eine eigene, per Custom Property umgeschaltete Text- und
  Linkfarbe, damit bestehende Komponenten (p, a, .meta, .proof-list) ohne
  Zusatzregeln lesbar bleiben.
*/
.section--band-sage {
  background-color: var(--color-surface-sage-tint);
}

.section--band-forest {
  background-color: var(--color-surface-forest);
  color: var(--color-text-on-inverse);
}

.section--band-forest .meta {
  color: #aeb6a0; /* 5.2:1 auf Waldgrün */
}

.section--band-forest .proof-list li::before {
  background-color: var(--color-surface-sage-tint);
}

/*
  Organische Trennkante zwischen zwei Bändern, siehe design-direction.md:
  eine ruhige Schrägkante statt eines harten Farbschnitts, mit der einzigen
  Aufgabe, den Wechsel der Fläche anzukündigen. Reine Dekoration, deshalb
  aria-hidden über :not([aria-hidden]) nicht nötig, das Element trägt keinen
  Inhalt.
*/
.section--band-sage::before,
.section--band-forest::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3rem;
  background-color: inherit;
  clip-path: polygon(0 100%, 100% 40%, 100% 100%, 0 100%);
  transform: translateY(-99%);
  pointer-events: none;
}

@media (max-width: 40rem) {
  .section--band-sage::before,
  .section--band-forest::before {
    height: 1.75rem;
  }
}

.section__heading {
  max-width: var(--text-max-width);
  margin-bottom: var(--space-4);
}

/*
  Schritt-Liste für den Ablauf, überarbeitet in Runde 9 zu einer editorialen,
  Apple-nahen Form: statt kleiner farbiger Nummernkreise trägt jeder Schritt
  jetzt eine große, dünn geschriebene Serifen-Ziffer im Format 01–04, links
  neben dem Text, in derselben Serifen-Familie wie die Headline. Die Ziffer
  ist Beweis genug, dass die Reihenfolge zählt, ohne dass ein farbig gefüllter
  Kreis wie ein Icon wirkt. Farblich stimmt sie jetzt mit dem seit Runde 8
  auf Waldgrün umgestellten System zusammen, nicht mehr mit dem alten
  Terrakotta.

  Der Text kommt in zwei Ebenen: Schritt-Titel (fett) und ergänzende
  Beschreibung darunter. Auf kompakten Listen ohne Titel (Startseite) ist der
  Titel einfach der ganze Satz.
*/
.step-list {
  list-style: none;
  padding: 0;
  counter-reset: step;
  display: grid;
  gap: var(--space-5);
}

.step-list li {
  counter-increment: step;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--space-4);
  align-items: baseline;
  max-width: none;
}

.step-list li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.25rem, 1.5rem + 2vw, 3.25rem);
  line-height: 1;
  color: var(--color-surface-forest);
  letter-spacing: -0.02em;
  align-self: start;
  padding-top: 0.1em;
  min-width: 2.4em;
}

@media (min-width: 56rem) {
  .step-list {
    gap: var(--space-6);
    max-width: 52rem;
  }
}

.step-list__body {
  padding-top: 0.2em;
}

.step-list__body strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-subheading);
  line-height: var(--line-height-heading);
  margin-bottom: 0.4em;
}

.step-list__body p {
  margin: 0;
  color: var(--color-text-muted);
  max-width: 34rem;
}

@media (max-width: 43.75rem) {
  .step-list li {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-1);
  }

  .step-list li::before {
    min-width: 0;
  }
}

/*
  Abschluss-CTA-Sektion, siehe Runde 9. Ersetzt am Ende der Unterseiten die
  isoliert stehenden „Titel + Button"-Blöcke durch einen mittig gesetzten,
  ruhigen Abschluss: großzügiges Padding, zentrierte Überschrift, ein kurzer
  Kontext-Satz, dann der Button in seiner Premium-Größe. Damit bekommt der
  wichtigste Schritt am Ende einer Seite ein Bühnengefühl, ohne dass ein
  zweites Formular oder Feature nötig wird.
*/
.section--cta {
  padding-block: var(--space-7);
  text-align: center;
}

.section-cta {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  max-width: 40rem;
  margin-inline: auto;
}

.section-cta h2 {
  margin: 0;
  letter-spacing: -0.015em;
}

.section-cta p {
  margin: 0;
  color: #c8cfba; /* 6:1 auf Waldgrün, ruhiger Muted-Ton für invertierten Grund */
  max-width: 34rem;
}

.section-cta .button {
  margin-top: var(--space-2);
}

.card-grid {
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 40rem) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.card {
  background-color: var(--color-surface-elevated);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
}

.proof-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-2);
}

.proof-list li {
  padding-left: 1.6em;
  position: relative;
}

.proof-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 0.5em;
  height: 0.5em;
  background-color: var(--color-accent);
  border-radius: 50%;
}

/*
  FAQ-Gruppen, siehe Runde 9: die neun Fragen der FAQ-Seite werden in drei
  thematische Blöcke sortiert (Beratung, Vitalstoff-Messung, LR/Datenschutz).
  Der Gruppentitel steht als eigenständige, kleine Zwischenüberschrift über
  jedem Block, damit die Liste scan-bar wird, statt als endlose Reihe zu
  wirken. Der Titel nutzt die kleine Meta-Rolle, keine H2-Größe, damit die
  Fragen selbst weiter die visuelle Führung übernehmen.
*/
.faq-group {
  display: block;
}

.faq-group__heading {
  font-family: var(--font-body);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin: 0 0 var(--space-3);
}

.section--band-sage .faq-group__heading,
.section--band-forest .faq-group__heading {
  color: var(--color-accent-text);
}

.section--band-forest .faq-group__heading {
  color: var(--color-link-on-inverse);
}

.faq-item {
  border-bottom: 1px solid rgba(36, 23, 16, 0.12);
  padding-block: var(--space-2);
}

.faq-item summary {
  cursor: pointer;
  font-weight: 600;
  font-size: var(--text-subheading);
  font-family: var(--font-display);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  transition: color var(--duration-state) var(--easing-standard);
}

.faq-item summary:hover,
.faq-item summary:active {
  color: var(--color-accent-text);
}

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

.faq-item summary::after {
  content: "+";
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 1.5rem;
  color: var(--color-text-muted);
  flex-shrink: 0;
  display: inline-block;
  transition: transform var(--duration-spatial) var(--easing-emphasis),
    color var(--duration-state) var(--easing-standard);
}

.faq-item summary:hover::after {
  color: var(--color-accent-text);
}

.faq-item[open] summary::after {
  content: "+";
  transform: rotate(135deg);
}

.faq-item p {
  animation: faq-open var(--duration-spatial) var(--easing-emphasis);
}

@keyframes faq-open {
  from {
    opacity: 0;
    transform: translateY(-0.4rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.faq-item p {
  margin-top: var(--space-2);
}

.status-message {
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-body);
  margin-top: var(--space-3);
  display: none;
}

.status-message[data-status="success"] {
  background-color: rgba(75, 107, 78, 0.12);
  color: var(--color-success);
  display: block;
}

.status-message[data-status="error"] {
  background-color: rgba(166, 67, 46, 0.12);
  color: var(--color-error);
  display: block;
}

/*
  Zustimmungs-Checkbox, siehe Runde 26. Sie war zuvor über Inline-Styles im
  HTML gesetzt und dadurch nur 13x13 Pixel groß, also weit unter jeder
  Empfehlung für treffbare Bedienelemente, und das ausgerechnet an der
  Pflichtangabe, ohne die das Formular nicht abgeschickt werden kann. Die
  Fläche ist jetzt 1.5rem groß, das Label daneben bleibt ohnehin klickbar
  und vergrößert das Ziel zusätzlich.
*/
.field input[type="checkbox"] {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  margin: 0 0.6em 0 0;
  accent-color: var(--color-surface-forest);
  vertical-align: -0.35em;
}

.field label:has(input[type="checkbox"]) {
  display: flex;
  align-items: flex-start;
  gap: 0;
  line-height: 1.5;
}

/*
  Alleinstehende Links, die eine ganze Zeile für sich haben, verhalten sich
  wie eine eigene Handlung („Alle Fragen ansehen", „Ablauf im Detail") und
  brauchen deshalb dieselbe treffbare Fläche wie ein Button. Buttons selbst
  sind ausgenommen, sie bringen ihren Innenabstand mit.
*/
p > a:only-child:not(.button):not(.text-link) {
  display: inline-block;
  padding-block: 0.78rem;
}

.contact-methods {
  display: grid;
  gap: var(--space-2);
  margin-block: var(--space-4);
}

.contact-methods a {
  font-weight: 600;
}

.contact-methods__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}

/*
  Telefonnummer und E-Mail sind auf dem Handy die wichtigsten Handlungen der
  ganzen Seite und waren als reine Textzeilen nur 19px hoch. Der Innenabstand
  hebt die treffbare Fläche auf die empfohlenen 44px, ohne den optischen
  Rhythmus zu verändern, weil er den vorherigen Gap ersetzt. Siehe Runde 26.
*/
.contact-methods__list a {
  display: inline-block;
  padding-block: 0.78rem;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--duration-state) var(--easing-standard);
}

.contact-methods__list a:hover {
  border-bottom-color: currentColor;
}

/*
  Footer, überarbeitet in Runde 9. Ersetzt das frühere gleichgewichtete
  Drei-Spalten-Grid durch eine editorialere Aufteilung mit einem größeren
  Markenblock links (Serifen-Name, kurze Positionierungszeile, Adresse) und
  zwei schlanken Spalten rechts, die durch stille Überschriften (Kontakt,
  Rechtliches) sortiert sind. Eine dünne Trennlinie oberhalb des Copyright-
  Bereichs schließt die Seite optisch ab, kein zusätzliches Grafikelement.
*/
.site-footer {
  background-color: var(--color-surface-inverse);
  color: var(--color-text-on-inverse);
  padding-block: var(--space-6) var(--space-4);
}

.site-footer a {
  color: var(--color-link-on-inverse);
}

.site-footer a:hover {
  color: var(--color-link-on-inverse-hover);
}

.site-footer__grid {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 48rem) {
  .site-footer__grid {
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-6);
  }
}

.site-footer__brand-name {
  font-family: var(--font-display);
  font-size: var(--text-subheading);
  font-weight: 600;
  color: var(--color-text-on-inverse);
  display: block;
  margin-bottom: var(--space-1);
  letter-spacing: -0.01em;
}

.site-footer__tagline {
  color: #c8cfba;
  margin: 0 0 var(--space-3);
  max-width: 22rem;
}

.site-footer__address {
  font-size: var(--text-meta);
  color: #c8cfba;
  margin: 0;
  line-height: 1.6;
  font-style: normal;
}

.site-footer__heading {
  font-family: var(--font-body);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #c8cfba;
  margin: 0 0 var(--space-2);
}

.site-footer__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}

/* Treffbare Fläche wie bei .contact-methods__list, siehe Runde 26. */
.site-footer__list a {
  display: inline-block;
  padding-block: 0.65rem;
  text-decoration: none;
}

.site-footer__list a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.site-footer__baseline {
  border-top: 1px solid rgba(231, 227, 220, 0.14);
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--text-meta);
  /* Solides gedämpftes Salbei statt 70%-Alpha: die Alpha-Variante mischte
     sich Richtung Grund und lag beim Kontrast im Grenzbereich. #c8cfba ist
     der bereits an anderer Stelle genutzte, geprüfte Muted-Ton auf Waldgrün. */
  color: #c8cfba;
}

.site-footer__baseline p {
  margin: 0;
}

/* ------------------------------------------------------------------ *
   Fit-Finder: interaktiver Selbsttest "Passt ein Erstgespräch zu dir?"
   Siehe animation-plan.md (Aufgaben "Orientieren" und "Bestätigen") und
   index.html #fuer-wen. Nur mit JS sichtbar (Klasse js-fitcheck-ready am
   Wurzelelement blendet die statische .proof-list aus und den Test ein).
 * ------------------------------------------------------------------ */
/*
  Bis Runde 36 stand hier `display: none`, der Selbsttest verdrängte also die
  statische Liste vollständig. Eine Messung des gerenderten DOM ergab, dass
  damit 74 der 738 Wörter der Startseite verschwanden, und zwar ausgerechnet
  die vier konkretesten Sätze der ganzen Seite: „Du fühlst dich seit längerem
  erschöpft…", „…nach der Geburt eines Kindes oder in den Wechseljahren…" —
  also genau die Formulierungen, mit denen Suchende ihre eigene Lage
  beschreiben. Der Abschnitt trug für einen Crawler nach dem Rendern nur noch
  32 Wörter Einleitung zu einem Test, dessen Inhalt hinter vier Klicks lag.
  Mit ausgeblendet wurde außerdem der Hinweis auf den Hausarzt bei akuten
  Beschwerden.

  Der Test bleibt, die Liste bleibt jetzt aber darunter stehen. Sie beantwortet
  dieselbe Frage für jemanden, der nicht klicken will, und das ist nach jeder
  Messung an interaktiven Elementen die Mehrheit. Sie rückt dafür optisch eine
  Stufe zurück: kleinerer Text, gedämpfte Farbe, deutlicher Abstand, damit klar
  bleibt, was Angebot und was Ergänzung ist.
*/
.js-fitcheck-ready [data-fitcheck-fallback] {
  margin-top: var(--space-4);
  font-size: var(--text-meta);
  color: var(--color-text-muted);
}

.fitcheck {
  max-width: 46rem;
  background-color: var(--color-surface-elevated);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: clamp(1.5rem, 1rem + 2vw, 2.75rem);
}

/* Jeder Schritt (Intro, Frage, Ergebnis) läuft als eigenes Panel ein. Die
   Bewegung nutzt die räumliche Rhythmusfamilie und wird unter
   prefers-reduced-motion über das Token auf 1ms neutralisiert. */
.fitcheck__panel {
  animation: fitcheck-in var(--duration-spatial) var(--easing-emphasis);
}

@keyframes fitcheck-in {
  from { opacity: 0; transform: translateY(0.6rem); }
  to { opacity: 1; transform: none; }
}

.fitcheck__eyebrow {
  margin: 0 0 var(--space-1);
  font-size: var(--text-meta);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.fitcheck__lead {
  margin: 0 0 var(--space-3);
  color: var(--color-text);
  max-width: 34rem;
}

.fitcheck__progress {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.fitcheck__dots {
  display: flex;
  gap: 0.4rem;
}

.fitcheck__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background-color: rgba(51, 64, 44, 0.18);
  transition: background-color var(--duration-state) var(--easing-standard);
}

.fitcheck__dot[data-on="true"] {
  background-color: var(--color-surface-forest);
}

.fitcheck__progress-label {
  font-size: var(--text-meta);
  color: var(--color-text-muted);
}

.fitcheck__question,
.fitcheck__result-title {
  font-family: var(--font-display);
  line-height: var(--line-height-heading);
  color: var(--color-text);
  margin: 0 0 var(--space-3);
}

.fitcheck__question {
  font-size: var(--text-subheading);
}

.fitcheck__result-title {
  font-size: var(--text-heading);
  margin-bottom: var(--space-2);
}

.fitcheck__options {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.fitcheck__option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 500;
  line-height: 1.4;
  color: var(--color-text);
  background-color: var(--color-surface);
  border: 1px solid rgba(36, 23, 16, 0.14);
  border-radius: var(--radius-md);
  padding: 1rem 1.15rem;
  cursor: pointer;
  transition: border-color var(--duration-state) var(--easing-standard),
    background-color var(--duration-state) var(--easing-standard),
    transform var(--duration-spatial) var(--easing-emphasis);
}

.fitcheck__option:hover {
  border-color: var(--color-accent);
  background-color: #fff;
  transform: translateX(3px);
}

.fitcheck__option-arrow {
  flex: none;
  width: 1.1em;
  height: 1.1em;
  color: var(--color-accent-text);
  transition: transform var(--duration-spatial) var(--easing-emphasis);
}

.fitcheck__option:hover .fitcheck__option-arrow {
  transform: translateX(3px);
}

.fitcheck__result-body {
  margin: 0 0 var(--space-3);
  color: var(--color-text);
  max-width: var(--text-max-width);
}

/* Farbiger Akzentstrich am Ergebnis, je nach Ausgang: grün = passt,
   gedämpft für die beiden ehrlichen "eher nicht"-Ausgänge. */
.fitcheck__result {
  border-left: 3px solid var(--color-surface-forest);
  padding-left: var(--space-3);
}

.fitcheck__result[data-tone="medizin"] {
  border-left-color: var(--color-warning);
}

.fitcheck__result[data-tone="produkt"] {
  border-left-color: var(--color-accent);
}

.fitcheck__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.fitcheck__back,
.fitcheck__restart {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--text-label);
  color: var(--color-text-muted);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.fitcheck__back {
  margin-top: var(--space-3);
}

.fitcheck__back:hover,
.fitcheck__restart:hover {
  color: var(--color-text);
}

/* ------------------------------------------------------------------ *
   Intro-Split: editoriale Zwei-Spalten-Fassung der "Wer ich bin"-Sektion.
   Persönlicher Text links, scannbare Fakten-Karte rechts. Ersetzt die
   frühere einspaltige Textwand, siehe design-direction.md, Runde 17.
 * ------------------------------------------------------------------ */
.section__eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin: 0 0 var(--space-1);
}

.intro-split {
  display: grid;
  gap: var(--space-4);
  align-items: start;
}

@media (min-width: 56rem) {
  .intro-split {
    grid-template-columns: 1.6fr 1fr;
    gap: var(--space-6);
  }
}

.intro-split__facts {
  background-color: var(--color-surface-elevated);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4);
}

.intro-split__facts-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.facts {
  margin: 0;
}

.facts__row {
  padding: var(--space-2) 0;
  border-top: 1px solid rgba(36, 23, 16, 0.1);
}

.facts__row:first-of-type {
  border-top: none;
  padding-top: 0;
}

.facts__row:last-of-type {
  padding-bottom: 0;
}

.facts dt {
  font-size: var(--text-label);
  font-weight: 600;
  color: var(--color-text-muted);
  margin-bottom: 0.15rem;
}

.facts dd {
  margin: 0;
  color: var(--color-text);
  line-height: 1.45;
}

/* Inline-Textlink mit Pfeil, der beim Hover ruhig nach rechts wandert.
   Dieselbe Bewegungsaufgabe wie der Pfeil im Button (.button__icon). */
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--color-accent-text);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.text-link svg {
  width: 1em;
  height: 1em;
  transition: transform var(--duration-spatial) var(--easing-emphasis);
}

.text-link:hover {
  color: var(--color-accent-text-hover);
}

.text-link:hover svg {
  transform: translateX(4px);
}

/* ------------------------------------------------------------------ *
   Boundary-Split: das "Das ist sie / Das ist sie nicht"-Gegenüber im
   Grenzabschnitt. Bewusst ruhig gehalten (kein Bandton, kein rotes X),
   weil dieser Abschnitt laut animation-plan.md der ruhigste Punkt der
   Seite bleibt. Die Gegenüberstellung schafft Klarheit, keine Show.
 * ------------------------------------------------------------------ */
.boundary-split {
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 48rem) {
  .boundary-split {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
  }
}

.boundary-col {
  background-color: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

.boundary-col__title {
  font-family: var(--font-display);
  font-size: var(--text-subheading);
  line-height: var(--line-height-heading);
  margin: 0 0 var(--space-3);
}

.boundary-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.boundary-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  line-height: 1.45;
}

.boundary-list svg {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.15em;
}

.boundary-list--is svg {
  color: var(--color-success);
}

.boundary-list--isnt svg {
  color: var(--color-text-muted);
}

.boundary-note {
  max-width: var(--text-max-width);
  color: var(--color-text-muted);
}

/* ------------------------------------------------------------------ *
   Skalen-Legende, siehe ablauf-und-vitalstoff-analyse.html #ampel.
   Zeigt die vier Bereiche, in denen das Messgerät jeden Wert einordnet
   (Normal, leicht, gemäßigt, stark abweichend). Bewusst als ruhige
   Textliste mit kleinen farbigen Punkten, nicht als plakative Ampel-
   Grafik, damit die Bedeutung, nicht die Signalfarbe im Vordergrund
   steht. Farbwerte des Berichts wurden auf gedämpfte Marken-Töne
   übersetzt, siehe design-direction.md, Runde 21.
 * ------------------------------------------------------------------ */
.scale-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  max-width: 46rem;
}

@media (min-width: 48rem) {
  .scale-legend {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2) var(--space-4);
  }
}

.scale-legend li {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  line-height: 1.45;
}

.scale-legend strong {
  display: block;
  font-weight: 600;
  margin-bottom: 0.15rem;
}

.scale-legend p {
  margin: 0;
  font-size: var(--text-body);
}

.section--band-forest .scale-legend p {
  color: #c8cfba;
}

.scale-legend__dot {
  flex: none;
  width: 0.85rem;
  height: 0.85rem;
  margin-top: 0.35rem;
  border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.08);
}

.scale-legend__dot[data-tone="normal"]   { background-color: #7fa17f; }
.scale-legend__dot[data-tone="leicht"]   { background-color: #6a9ab3; }
.scale-legend__dot[data-tone="mittel"]   { background-color: #d9c26b; }
.scale-legend__dot[data-tone="stark"]    { background-color: #c47a63; }
