/* ==========================================================================
   DONA BROWS — main.css
   Tokens und Regeln stammen aus DESIGN.md. Farben sind aus der bestehenden
   Jimdo-Site gemessen, nicht erfunden.
   ========================================================================== */

/* --- Schrift: selbst gehostet, kein Google-Fonts-Request zur Laufzeit ----- */

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 200 500;
  font-display: swap;
  src: url('../fonts/jost-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 200 500;
  font-display: swap;
  src: url('../fonts/jost-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Tokens -------------------------------------------------------------- */

:root {
  /* Hell — Salbei als Flaeche, Bordeaux als Schrift. Beide aus der
     Farbpalette des Studios, siehe DESIGN.md. */
  --canvas: #cecdbe;  /* Salbei */
  --surface: #dcdbd2; /* Salbei aufgehellt */
  --sand: #d4cdc1;    /* Greige hell und neutral, CTA-Band */
  --sand-soft: #ddd8ce; /* Greige noch heller, Footer und Baender */
  --ink: #2f0209;     /* Bordeaux, 11.56:1 auf Salbei */
  --clay: #5a4136;    /* Taupe abgedunkelt, 5.84:1 */
  --taupe: #775748;   /* nur Grosstext und Dekor, 4.04:1 */
  --mocha: #523509;   /* Ocker abgedunkelt, alles Interaktive, 7:1 */
  --mocha-hover: #3e2806;
  --on-accent: #ffffff;
  --line: rgba(119, 87, 72, 0.25);
  --line-strong: rgba(119, 87, 72, 0.42);
  --scrim: rgba(47, 2, 9, 0.55);
  /* Sekundaertext auf der Sandflaeche. --clay ergaebe dort nur 4.22:1. */
  --on-sand-muted: #4a3a2c;

  /* Eine Rundung für alles */
  --radius: 2px;

  /* Rhythmus */
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --section: clamp(4rem, 10vw, 8rem);
  --measure: 62ch;
  --max: 1240px;
  --nav-h: 68px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur: 320ms;

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Dunkel bleibt warmes Braun. Bordeaux als Vollflaeche wurde probiert
       und verworfen, es wirkt schwer und dunkel. */
    --canvas: #171310;
    --surface: #201a16;
    --sand: #3a2e26;
    --sand-soft: #2a221c;
    --ink: #f2ebe2;
    --clay: #b3a498;
    --taupe: #c4a98f;
    --mocha: #d9bfa4;
    --mocha-hover: #e8d3bd;
    --on-accent: #1b130f;
    --line: rgba(196, 169, 143, 0.2);
    --line-strong: rgba(196, 169, 143, 0.36);
    --scrim: rgba(10, 7, 5, 0.6);
    --on-sand-muted: #b3a498;
  }
}

/* --- Reset --------------------------------------------------------------- */

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

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: 'Jost', 'Century Gothic', 'Questrial', 'Avenir Next', sans-serif;
  font-weight: 400;
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p, figure, blockquote { margin: 0; }
/* ol mit abdecken: sonst stehen bei eigenen Zaehlern die Browserziffern daneben. */
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: var(--mocha); text-underline-offset: 0.25em; }

:where(a, button, summary, input, [tabindex]):focus-visible {
  outline: 2px solid var(--mocha);
  outline-offset: 3px;
}

::selection { background: var(--sand); color: var(--ink); }

/* --- Typo-Klassen -------------------------------------------------------- */

.wordmark {
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.3rem);
  font-weight: 300;
  letter-spacing: 0.28em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

.display {
  font-size: clamp(2.5rem, 1.6rem + 4.2vw, 4.5rem);
  font-weight: 200;
  letter-spacing: 0.01em;
  line-height: 1.06;
  text-wrap: balance;
}

.h2 {
  font-size: clamp(1.75rem, 1.3rem + 2vw, 2.5rem);
  font-weight: 300;
  letter-spacing: 0.03em;
  line-height: 1.18;
  color: var(--taupe);
  text-wrap: balance;
}

.h3 {
  font-size: clamp(1.15rem, 1.05rem + 0.5vw, 1.4rem);
  font-weight: 400;
  letter-spacing: 0.05em;
  line-height: 1.35;
}

/* --taupe waere hier nur 3.87:1. Kleintext bekommt daher immer --mocha. */
.eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--mocha);
  line-height: 1.4;
}

.lede {
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  font-weight: 300;
  line-height: 1.65;
  color: var(--clay);
  max-width: 44ch;
}

.body { max-width: var(--measure); color: var(--ink); }
.body + .body { margin-top: 1.1em; }

.muted { color: var(--clay); }

.num { font-variant-numeric: tabular-nums; }

/* --- Layout -------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section); }

/* Nicht per left:-9999px auslagern, das erzeugt horizontales Overflow. */
.skip {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--ink);
  color: var(--canvas);
  padding: 0.75rem 1.25rem;
  z-index: 100;
}

.skip:focus {
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
  left: 0;
  top: 0;
}

/* --- Navigation ---------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  background: color-mix(in srgb, var(--canvas) 88%, transparent);
  backdrop-filter: saturate(150%) blur(12px);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--line);
}

.nav__inner {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.5vw, 2.25rem);
}

.nav__links a {
  font-size: 0.8125rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--clay);
  text-decoration: none;
  padding-block: 0.35rem;
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.nav__links a:hover { color: var(--ink); }
.nav__links a[aria-current='page'] {
  color: var(--ink);
  border-bottom-color: var(--taupe);
}

.nav__cta { display: inline-flex; }

.nav__toggle {
  display: none;
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 0.8125rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
}

/* Spezifitaet mit .nav davor: sonst gewinnt spaeter im File .btn mit
   display:inline-flex und der CTA bleibt auf Mobile stehen. */
@media (max-width: 900px) {
  .nav .nav__links,
  .nav .nav__cta { display: none; }
  .nav .nav__toggle { display: inline-flex; }
}

.nav__inner > * { min-width: 0; }
.nav__toggle { flex: 0 0 auto; }

/* Der Schliessen-Button liegt im Overlay, nicht in .nav, und ist immer sichtbar. */
.menu .nav__toggle { display: inline-flex; }

/* Mobile-Overlay */
.menu {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--canvas);
  padding: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 2rem;
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
    visibility 0s linear var(--dur);
}

.menu[data-open='true'] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

.menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--nav-h);
}

.menu__links { display: grid; gap: 0.25rem; margin-top: 1rem; }

.menu__links a {
  display: block;
  padding-block: 0.6rem;
  font-size: clamp(1.5rem, 6vw, 2rem);
  font-weight: 200;
  letter-spacing: 0.04em;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
}

.menu__foot { margin-top: auto; }

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0.9rem 2.25rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    transform 120ms var(--ease);
}

.btn--primary {
  background: var(--mocha);
  color: var(--on-accent);
}
.btn--primary:hover { background: var(--mocha-hover); }

.btn--ghost {
  background: transparent;
  color: var(--mocha);
  border-color: var(--line-strong);
}
.btn--ghost:hover { border-color: var(--mocha); }

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

.btn--sm { padding: 0.6rem 1.4rem; min-height: 40px; font-size: 0.75rem; }

/* Textlink mit Pfeil */
.arrow {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mocha);
  text-decoration: none;
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 0.35rem;
  transition: border-color var(--dur) var(--ease);
}
.arrow:hover { border-bottom-color: var(--mocha); }
.arrow span { transition: transform var(--dur) var(--ease); }
.arrow:hover span { transform: translateX(4px); }

/* --- Hero: asymmetrischer Split ------------------------------------------ */

/* Auf Mobile keine erzwungene Viewporthoehe: der Textblock ist kurz und es
   entstuende ein grosses leeres Sandfeld unter den Buttons. */
.hero {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .hero {
    grid-template-columns: 54fr 46fr;
    align-items: stretch;
    min-height: calc(100dvh - var(--nav-h));
  }
}

.hero__media {
  position: relative;
  overflow: hidden;
  background: var(--sand-soft);
  /* Mobile: das Video fuellt den Bildschirm unter der Navigation. */
  /* Fallback fuer Browser ohne lvh, also vor Safari 15.4 und Chrome 108. */
  min-height: calc(100vh - var(--nav-h));
  /* lvh statt dvh, aus zwei Gruenden. Erstens liefert Safari seit iOS 26 bei
     dvh zu wenig Hoehe und laesst unten eine Luecke, waehrend Chrome korrekt
     rechnet. lvh ist die Hoehe ohne Browserleisten und kann darum nie zu
     klein sein. Zweitens ist lvh statisch: das Layout rueckt nicht nach,
     wenn die Adressleiste beim Scrollen ein- und ausfaehrt.
     Der Preis ist ein Beschnitt unten, und bei einem Video mit object-fit
     cover fallen ohnehin Bildteile weg. */
  /* Auf dem iPhone gemessen: der Hero endete bei 794px, der Bildschirm ist
     874px hoch. Die fehlenden 80px sind genau die schwebende Suchleiste.
     Safari meldet lvh um diesen Betrag zu klein, obwohl der Inhalt darunter
     durchlaeuft, und env(safe-area-inset-bottom) ist dort null.

     max() nimmt den groesseren der beiden Werte, weil je nach Browser mal
     der eine und mal der andere zu klein ist. Der Zuschlag deckt die
     Leiste ab. Lieber zu hoch als zu kurz: zu hoch heisst etwas mehr
     Beschnitt bei einem Video, das ohnehin beschnitten wird, zu kurz
     heisst eine sichtbare Luecke.

     --hero-h wird auch fuer die Wortmarke gebraucht, damit beide
     denselben Wert verwenden. */
  --hero-h: calc(max(100vh, 100lvh) + 5rem);
  min-height: calc(var(--hero-h) - var(--nav-h));
  display: grid;
  place-items: center;
}

@media (min-width: 900px) {
  /* Desktop: die Hoehe kommt aus dem Grid, nicht aus dem Viewport. */
  .hero__media { min-height: 52dvh; }
}

/* Absolut positioniert, damit die Eigenhoehe des Mediums nicht die Zeilenhoehe
   des Grids diktiert. Sonst waechst der Hero ueber den Viewport hinaus. */
.hero__media img,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 28%;
}

/* Das Videomaterial ist in kaltem Studiograu aufgenommen, die Seite ist warm.
   sepia zieht den Hintergrund in die Sandpalette, saturate holt die Hauttoene
   zurueck, die sepia sonst flach zieht. Zum Abschalten: Zeile entfernen. */
.hero__video {
  filter: sepia(0.24) saturate(1.32) contrast(1.02);
}

/* Scrim fuer die Wortmarke: zurueckhaltend, damit das Video kraeftig bleibt.
   Die Abdunkelung liegt als weiche Ellipse hinter der Schrift und laeuft
   nach aussen vollstaendig aus, das Bild bleibt an den Kanten unberuehrt.
   Ab 900px faellt Wortmarke und Scrim weg. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: radial-gradient(
    ellipse 78% 30% at 50% 50%,
    rgba(27, 19, 15, 0.42) 0%,
    rgba(27, 19, 15, 0.26) 58%,
    rgba(27, 19, 15, 0) 100%
  );
  pointer-events: none;
}

.hero__wordmark {
  position: relative;
  z-index: 3;
  margin: 0;
  padding-inline: var(--gutter);
  text-align: center;
  color: #FFFFFF;
  /* Versalien mit weitem Gang, wie die Wortmarke in der Navigation. Der
     Gang wird rechts als Einzug ausgeglichen, sonst sitzt die Zeile
     optisch links von der Mitte. */
  text-transform: uppercase;
  font-size: clamp(1.875rem, 9.5vw, 3.25rem);
  font-weight: 300;
  line-height: 1.18;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  /* Der Scrim ist bewusst schwach. Der Schatten haelt die Schrift auch
     dort lesbar, wo eine helle Wange direkt hinter ihr liegt. */
  text-shadow: 0 0 3px rgba(27, 19, 15, 0.72),
               0 0 12px rgba(27, 19, 15, 0.55),
               0 1px 32px rgba(27, 19, 15, 0.5);
}

/* Der Hero ist absichtlich hoeher als der sichtbare Bereich. Ohne Korrektur
   sitzt die Wortmarke darum unter der Mitte dessen, was man wirklich sieht.
   Der halbe Unterschied zwischen sichtbarer Hoehe und --hero-h hebt sie
   exakt dorthin zurueck, unabhaengig davon, wie gross der Zuschlag ist.
   svh meldet Safari korrekt, auf dem Geraet nachgemessen: 9px Abweichung. */
@supports (height: 100svh) and (height: 100lvh) {
  .hero__wordmark,
  /* Die Ellipse muss denselben Weg gehen, sonst steht die Schrift an ihrem
     oberen Rand statt in ihrer Mitte. Der Gradient laeuft nach aussen
     transparent aus, der frei werdende Streifen oben faellt nicht auf. */
  .hero__media::after {
    transform: translateY(calc((100svh - var(--hero-h)) / 2));
  }
}

@media (min-width: 900px) {
  /* Desktop hat die Wortmarke schon in der Navigation. */
  .hero__wordmark { display: none; }
  .hero__media::after { display: none; }
}

.hero__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1.75rem;
  padding: clamp(2.5rem, 6vw, 5rem) var(--gutter);
  background: var(--canvas);
}

@media (min-width: 900px) {
  .hero__body {
    padding-right: max(var(--gutter), calc((100vw - var(--max)) / 2 + var(--gutter)));
    padding-left: clamp(2rem, 4vw, 3.5rem);
    border-left: 1px solid var(--line);
  }
}

/* Der Hero hat nur knapp die halbe Breite. Die Display-Groesse wird hier
   gedeckelt, sonst laeuft die Zeile auf vier Zeilen aus. */
.hero__body .display {
  font-size: clamp(2.25rem, 1.4rem + 2.6vw, 3.5rem);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
  align-items: center;
}

/* Der Bogen: einmal auf der Seite, als Übergang aus dem Hero */
.arc {
  display: block;
  width: min(280px, 46vw);
  height: auto;
  color: var(--taupe);
  opacity: 0.55;
}

/* --- Leistungen: asymmetrisches 2x2 -------------------------------------- */

.services {
  display: grid;
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}

@media (min-width: 760px) {
  .services { grid-template-columns: 1fr 1fr; }
  /* ungleiche Zeilenhöhen brechen das Raster auf */
  .services > :nth-child(1) { grid-row: span 2; }
}

.service {
  background: var(--canvas);
  padding: clamp(1.75rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.service--feature { justify-content: space-between; }

/* Ueberschrift ueber dem Kachelraster: gleicher Einzug wie der Text in den
   Kacheln, damit sie bei breitem Bildschirm nicht in die Mitte rutscht. */
.services-head { padding-inline: clamp(1.75rem, 4vw, 3rem); }

.service__media {
  margin-block: 0.5rem 0.25rem;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--sand-soft);
}

.service__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 1200ms var(--ease);
}

/* Augenbrauen liegen quer, darum das Feature-Bild im Breitformat */
.service--feature .service__media img { aspect-ratio: 17 / 10; }
.service:hover .service__media img { transform: scale(1.03); }

/* Titel, Text und Preiszeile stehen als Block ueber dem Bild */
.service__head {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.service__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  color: var(--clay);
}

.service p { color: var(--clay); max-width: 42ch; }

/* --- Diptychon Vorher / Nachher ------------------------------------------ */

.diptych {
  display: grid;
  gap: 1px;
  background: var(--line-strong);
}

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

.diptych figure { background: var(--canvas); }

.diptych img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.diptych figcaption {
  padding: 1rem clamp(1rem, 3vw, 2rem) 1.5rem;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  color: var(--clay);
}

/* --- Split (Bild + Text) ------------------------------------------------- */

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

@media (min-width: 900px) {
  .split { grid-template-columns: 5fr 6fr; }
  .split--reverse > :first-child { order: 2; }
}

.split__media {
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--sand-soft);
}

.split__media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

.split__body { display: grid; gap: 1.25rem; }

/* --- Bewertungen --------------------------------------------------------- */

.reviews {
  background: var(--sand-soft);
  border-block: 1px solid var(--line);
}

.rating {
  display: grid;
  gap: 0.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--line-strong);
  max-width: 32ch;
}

.rating__score {
  font-size: clamp(3.5rem, 8vw, 5.5rem);
  font-weight: 200;
  line-height: 0.9;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Das Laufband steht ausserhalb von .shell und laeuft bis an die
   Bildschirmkante. Ohne JS bleibt es eine scrollbare Reihe, damit alle
   fuenfzehn Zitate auch dann erreichbar sind. */
/* Der Rahmen traegt den Fokusring. Er liegt ausserhalb der Maske, sonst
   verschwaende der Ring in der transparenten Randzone des Laufbands. */
.marquee-frame {
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.marquee {
  /* Breite der weichen Ausblendkante. Auf kleinen Viewports schmal, damit im
     Ruhezustand kein Zitattext in der Ausblendzone beginnt: dort faellt die
     Deckkraft und mit ihr der Kontrast unter die geforderten 4.5:1. Bei 390px
     beginnt die zweite, angeschnittene Karte bei x=369, also 21px vor der
     Kante; 20px Ausblendung bleiben knapp darunter. Ab 768px ist genug Platz.
     Das gilt fuer die ruhende Reihe, also ohne JS und bei reduzierter
     Bewegung, wo das padding-inline der Spur die Zone abdeckt. Im laufenden
     Band wandert dagegen jeder Zitattext durch die Kante, bei 19% Deckkraft
     rechnerisch rund 1.3:1. Das ist fuer ein Laufband gewollt: der Text ist
     dort in Bewegung und wird eine Kartenbreite spaeter voll lesbar. */
  --fade: 1.25rem;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade), #000 calc(100% - var(--fade)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade), #000 calc(100% - var(--fade)), transparent 100%);
}

@media (min-width: 768px) {
  .marquee { --fade: 5rem; }
}

.marquee::-webkit-scrollbar { display: none; }

/* Ring am Rahmen, nicht am maskierten Band. Die Regel an .marquee selbst
   bleibt als Rueckfall fuer Browser ohne :has() stehen. */
.marquee:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}

.marquee-frame:has(> .marquee:focus-visible) {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}

.marquee-frame:has(> .marquee:focus-visible) > .marquee { outline: none; }

.marquee__track {
  display: flex;
  align-items: stretch;
  width: max-content;
  /* Mindestens so breit wie die Ausblendkante: so beginnt der Zitattext der
     ersten Karte immer bei voller Deckkraft. */
  padding-inline: max(var(--gutter), var(--fade));
}

.marquee__track > .quote {
  flex: 0 0 auto;
  width: min(30rem, 78vw);
  padding-inline: clamp(1.5rem, 4vw, 3rem);
  border-left: 1px solid var(--line);
  display: grid;
  align-content: start;
}

.quote p {
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
  font-weight: 300;
  line-height: 1.6;
  color: var(--ink);
}

/* --clay ergaebe auf --sand-soft nur 3.21:1, siehe Kommentar bei den Tokens. */
.quote footer {
  margin-top: 0.75rem;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  color: var(--on-sand-muted);
}

/* Die Animation laeuft nur, wenn main.js die Karten verdoppelt und das Band
   freigeschaltet hat. Geschoben wird um --strecke, die Summe der Breiten der
   fuenfzehn Originalkarten. Nicht um -50% der Spur: die Spur traegt zusaetzlich
   padding-inline (je nach Breite 20 bis 80px pro Seite), das in scrollWidth
   eingeht. Die halbe Spurbreite waere also groesser als der Kartenblock, und
   pro Umlauf risse eine Luecke von bis zu 160px auf. Genau um --strecke
   verschoben steht die Kopie exakt dort, wo das Original stand: keine Naht. */
.js .marquee[data-laufband="an"] { overflow-x: hidden; }

/* Bei Fokus wird das Band wieder zum Scrollcontainer. Mit overflow-x: hidden
   greifen die Pfeiltasten nicht, scrollLeft bleibt gemessen bei 0, und wer
   hertabbt kommt ueber die drei sichtbaren Zitate nicht hinaus. Ein Sprung
   entsteht dabei nicht: die Leiste ist ueber scrollbar-width und
   ::-webkit-scrollbar ausgeblendet, es aendert sich also keine Groesse. */
.js .marquee[data-laufband="an"]:focus-within { overflow-x: auto; }

.js .marquee[data-laufband="an"] .marquee__track {
  animation: laufband var(--laufzeit, 60s) linear infinite;
}

/* data-ruht setzt main.js, solange die Section nicht im Bild ist. */
.js .marquee[data-laufband="an"]:hover .marquee__track,
.js .marquee[data-laufband="an"]:focus-within .marquee__track,
.js .marquee[data-laufband="an"][data-ruht] .marquee__track {
  animation-play-state: paused;
}

@keyframes laufband {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-1 * var(--strecke, 0px))); }
}

/* --- Band (CTA) ---------------------------------------------------------- */

.band {
  background: var(--sand);
  color: var(--ink);
  text-align: center;
}

@media (prefers-color-scheme: dark) {
  .band { background: var(--sand-soft); }
}

.band__inner {
  display: grid;
  gap: 1.5rem;
  justify-items: center;
  max-width: 48ch;
  margin-inline: auto;
}

.band .h2 { color: var(--ink); }
.band .muted { color: var(--on-sand-muted); }

/* --- Galerie ------------------------------------------------------------- */

.gallery {
  display: grid;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 900px) {
  .gallery { grid-template-columns: repeat(6, 1fr); }
  .gallery__item--wide { grid-column: span 4; }
  .gallery__item--tall { grid-column: span 2; grid-row: span 2; }
  .gallery__item--std { grid-column: span 2; }
}

.gallery__item {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--sand-soft);
}

.gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 4 / 5;
  transition: transform 1200ms var(--ease);
}

.gallery__item--wide img { aspect-ratio: 16 / 10; }
.gallery__item--tall img { aspect-ratio: 4 / 5; }
.gallery__item:hover img { transform: scale(1.03); }

/* --- Buchung ------------------------------------------------------------- */

.booking {
  max-width: 760px;
  margin-inline: auto;
}

.booking__mount { margin-top: clamp(2rem, 5vw, 3rem); min-height: 320px; }

.consent {
  display: grid;
  gap: 1.25rem;
  justify-items: start;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--sand-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.consent p { color: var(--clay); max-width: 52ch; }

.skeleton {
  display: grid;
  gap: 0.75rem;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.skeleton span {
  display: block;
  height: 1rem;
  border-radius: var(--radius);
  background: linear-gradient(
    90deg,
    var(--sand-soft) 0%,
    color-mix(in srgb, var(--sand) 60%, var(--sand-soft)) 50%,
    var(--sand-soft) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1600ms linear infinite;
}

.skeleton span:nth-child(1) { width: 45%; }
.skeleton span:nth-child(2) { width: 100%; height: 3rem; }
.skeleton span:nth-child(3) { width: 78%; height: 3rem; }
.skeleton span:nth-child(4) { width: 60%; }

@keyframes shimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

.notice {
  padding: 1rem 1.25rem;
  border-left: 2px solid var(--taupe);
  background: var(--sand-soft);
  color: var(--clay);
  font-size: 0.9375rem;
}

/* --- Preise: drei Gruppen, sparsame Linien ------------------------------- */

.pricing {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}

@media (min-width: 900px) {
  .pricing { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.pricing__group > h3 {
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--line-strong);
  color: var(--mocha);
}

.pricing__group ul { margin-top: 1.25rem; display: grid; gap: 1rem; }

.pricing__group li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.15rem 1rem;
  align-items: baseline;
}

.pricing__group li > :first-child { grid-column: 1; }

.pricing__group li > .num:first-of-type {
  grid-column: 1;
  grid-row: 2;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  color: var(--clay);
}

.pricing__group li > .num:last-child {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  color: var(--ink);
  white-space: nowrap;
}

/* --- Info-Zeilen (Adresse, Zeiten) --------------------------------------- */

.facts {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
}

@media (min-width: 760px) {
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.fact { display: grid; gap: 0.5rem; align-content: start; }
.fact dt {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mocha);
}
.fact dd { margin: 0; color: var(--ink); }

/* --- Footer -------------------------------------------------------------- */

.footer {
  background: var(--sand);
  color: var(--ink);
  padding-block: clamp(3rem, 7vw, 5rem);
}

@media (prefers-color-scheme: dark) {
  .footer { background: var(--sand-soft); }
}

.footer__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
}

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

.footer .muted { color: var(--on-sand-muted); }
.footer a { color: var(--ink); text-decoration: none; }
.footer a:hover { text-decoration: underline; }

/* Gestapelte Footer-Links brauchen eine greifbare Trefferflaeche. */
.footer__grid p > a:only-child {
  display: inline-block;
  padding-block: 0.45rem;
}

.footer__label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mocha);
  margin-bottom: 0.75rem;
}

@media (prefers-color-scheme: dark) {
  .footer__label { color: var(--taupe); }
}

.footer__bottom {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-strong);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.75rem;
  font-size: 0.875rem;
  color: var(--on-sand-muted);
}

/* --- Rechtstexte: Impressum und Datenschutz ------------------------------ */

/* Reine Fliesstextseiten. Zeilenlaenge auf --measure, damit die Absaetze
   lesbar bleiben, und Aufzaehlungen bekommen ihre Punkte zurueck, die der
   Reset global entfernt. */
.legal {
  max-width: var(--measure);
}

.legal > .lede {
  max-width: none;
  margin-top: 1rem;
}

.legal h2 {
  margin-top: clamp(2.25rem, 5vw, 3.25rem);
  margin-bottom: 0.75rem;
}

.legal p {
  line-height: 1.7;
  color: var(--ink);
}

.legal p + p,
.legal address + p,
.legal ul + p {
  margin-top: 1.1em;
}

.legal p.muted {
  color: var(--clay);
}

.legal address {
  font-style: normal;
  line-height: 1.7;
  margin-top: 0.25rem;
}

.legal ul {
  margin-top: 1.1em;
  padding-left: 1.35rem;
  list-style: disc;
}

.legal li {
  line-height: 1.7;
  color: var(--ink);
}

.legal li + li {
  margin-top: 0.6em;
}

.legal strong {
  font-weight: 500;
}

.legal .todo {
  margin-block: 0.15em;
}

/* --- Platzhalter-Markierung (nur MVP) ------------------------------------ */

.todo {
  display: inline-block;
  padding: 0.1em 0.5em;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  /* --clay ergab auf --sand-soft nur 4.38:1, unter dem Grenzwert fuer
     Kleintext. --mocha misst 4.98:1. */
  color: var(--mocha);
  background: var(--sand-soft);
}

/* --- Scroll-Reveal ------------------------------------------------------- */

/* Nur verstecken, wenn JS wirklich laeuft. Ohne JS bleibt die Seite lesbar. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 640ms var(--ease), transform 640ms var(--ease);
}

.js .reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none !important; transform: none !important; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Schulung: Ablauf des Tages ------------------------------------------
   Sechs Bausteine als vertikale Folge. Bewusst kein Kartenraster: der Tag
   hat eine Reihenfolge, und die soll man sehen. Die Linie laeuft durch die
   Ziffern und endet mit dem letzten Schritt. */

/* Titel links, Folge rechts: der Abschnitt nutzt die Breite, ohne dass die
   Lesespalte breiter wird als bequem lesbar ist. */
.curriculum-wrap {
  display: grid;
  gap: clamp(2rem, 5vw, 3rem);
}

@media (min-width: 1000px) {
  .curriculum-wrap {
    grid-template-columns: 28fr 72fr;
    gap: clamp(2rem, 6vw, 5rem);
    align-items: start;
  }
}

.curriculum {
  counter-reset: step;
  max-width: 60ch;
}

/* Die Linie laeuft als Rahmen durch die Schritte und endet mit dem letzten.
   Keine Kreise: DESIGN.md kennt genau eine Rundung, und die ist 2px. */
.curriculum > li {
  counter-increment: step;
  position: relative;
  padding-left: clamp(2.5rem, 4vw, 3.5rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  border-left: 1px solid var(--line);
}

.curriculum > li:last-child {
  padding-bottom: 0;
  border-left-color: transparent;
}

.curriculum > li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.3em;
  padding-left: 0.9rem;
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  color: var(--mocha);
  font-variant-numeric: tabular-nums;
}

.curriculum h3 { margin-bottom: 0.5rem; }
.curriculum p { color: var(--ink); }
.curriculum p + p { margin-top: 0.75rem; }

/* Die Theorieinhalte innerhalb von Schritt eins. Zweispaltig, damit die
   Liste den Schritt nicht optisch erdrueckt. */
.curriculum__topics {
  margin-top: 0.875rem;
  display: grid;
  gap: 0.5rem 1.5rem;
  font-size: 0.9375rem;
  color: var(--clay);
}

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

.curriculum__topics li {
  padding-left: 1rem;
  position: relative;
}

.curriculum__topics li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 5px;
  height: 1px;
  background: var(--taupe);
}

/* --- Schulung: Kursdetails ----------------------------------------------
   Drei Werte, gross gesetzt. Der Preis ist das Argument, nicht eine Zeile
   in einer Tabelle. */

.kursdetails {
  display: grid;
  gap: clamp(1.75rem, 4vw, 2.5rem);
  border-block: 1px solid var(--line-strong);
  padding-block: clamp(2rem, 5vw, 3rem);
}

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

.kursdetails > div { display: grid; gap: 0.5rem; align-content: start; }

.kursdetails dt {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mocha);
}

.kursdetails dd {
  margin: 0;
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.125rem);
  font-weight: 300;
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.kursdetails dd small {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  letter-spacing: 0;
  color: var(--clay);
}

/* --- Safe Areas -----------------------------------------------------------
   Mit viewport-fit=cover reicht das Layout bis an die physischen Kanten.
   Im Querformat liegt dort die Notch, unten der Home-Indicator. Ohne diese
   Zuschlaege klebt Text an der Kante oder verschwindet darunter.
   Auf Geraeten ohne Aussparungen ist env() null, es aendert sich nichts. */

.shell,
.nav__inner {
  padding-inline:
    max(var(--gutter), env(safe-area-inset-left, 0px))
    max(var(--gutter), env(safe-area-inset-right, 0px));
}

.footer {
  padding-bottom: calc(var(--section) / 2 + env(safe-area-inset-bottom, 0px));
}

/* Das Overlay deckt den ganzen Bildschirm ab und braucht die Zuschlaege
   an allen vier Kanten selbst. */
.menu {
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* --- Zone hinter der Statusleiste ----------------------------------------
   Zweite Absicherung neben theme-color. Reicht die Seite dank
   viewport-fit=cover bis unter die Statusleiste, deckt dieser Streifen sie
   in der Seitenfarbe ab. Meldet das Geraet keine Aussparung, ist er null
   hoch und damit wirkungslos. Liegt ueber der Navigation, deren Hintergrund
   halbtransparent ist und die Zone sonst durchscheinen liesse. */
body::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: env(safe-area-inset-top, 0px);
  background: var(--canvas);
  z-index: 60;
  pointer-events: none;
}
