/* ============================================================================
   COREFRAME · Landingpage
   Grammatik: filmic one-shot. Aesthetische Familie: modern, hell, grafisch.
   Tokens aus CoreFrame/BRAND.md. Die Engine wird nicht angefasst.
   ========================================================================== */

:root {
  /* Warme Welt, ganze Seite. Signal-Gruen faellt: es ist die eine Farbe, die
     sich mit "warm technology statt cyberpunk" nicht vertraegt. Der Akzent
     ist jetzt Terrakotta, das Ink ein warmes Espresso statt Blauschwarz. */
  --sc-canvas:     #F4EFE6;   /* Ivory   */
  --sc-surface:    #EAE1D2;   /* Sand    */
  --sc-ink:        #241D16;   /* Espresso */
  --sc-ink-soft:   #6E5F4C;   /* Warmes Taupe */
  --sc-accent:     #A8482A;   /* Terrakotta */
  --sc-accent-ink: #FFF8F0;

  /* Violett und Sky sind in BRAND.md Produkt- und Datenebene, keine UI-Farben.
     Sie leben hier ausschliesslich in der Bahn und in den Bauteilen. */
  --cf-violet: #6357F5;       /* nur noch in Altlasten, nicht mehr sichtbar */
  --cf-sky:    #78DFFF;
  --cf-deep:   #2B2119;       /* warmes Espresso statt Blauschwarz */
  --cf-paper:  #F4EFE6;

  /* Die warme 3D-Welt. Studio-Produktfotografie statt Neon-Tech. */
  --cf-ivory:     #F7F3EC;
  --cf-cream:     #EFE7DA;
  --cf-sand:      #E2D5C2;
  --cf-taupe:     #B9A894;
  --cf-champagne: #D8C09A;
  --cf-terra:     #C97B5A;

  --sc-font-display: "Helvetica Neue", "Neue Haas Grotesk Text Pro", Arial, sans-serif;
  --sc-font-text:    "Helvetica Neue", "Neue Haas Grotesk Text Pro", Arial, sans-serif;
  --sc-font-mono:    "SFMono-Regular", Consolas, "Liberation Mono", monospace;

  --sc-track-tight: -0.055em;
  --sc-track-snug:  -0.03em;

  --sc-r-sm: 6px; --sc-r-md: 12px; --sc-r-lg: 22px; --sc-r-pill: 999px;
  --sc-shadow-color: 220 8% 6%;

  /* Lusions Bewegungssprache, aus deren Stylesheets gelesen: EINE Kurve fuer
     praktisch jedes transform, 0,4 bis 0,6 Sekunden, kein Ueberschwingen.
     Was dort fluessig wirkt, kommt nicht aus verschiedenen Kurven, sondern
     aus derselben Kurve mit verschiedenen VERZOEGERUNGEN je Element. */
  --cf-ease: cubic-bezier(0.4, 0, 0.1, 1);
  --cf-dur: 480ms;

  --cf-bar-h: 76px;
  --cf-gut: clamp(16px, 3.4vw, 44px);
  --cf-line: color-mix(in oklab, var(--sc-ink) 15%, transparent);
}

/* Die Engine setzt scroll-behavior: smooth. Zusammen mit unserem eigenen
   Nachlauf faellt das native Smooth-Scrollen jeden Frame in sich zusammen,
   und Tastatur sowie Anker kommen nicht mehr ans Ziel. Wir glaetten selbst. */
html { scroll-behavior: auto; }
body { font-weight: 400; letter-spacing: var(--sc-track-snug); }

.cf-mono, .cf-over {
  font-family: var(--sc-font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--sc-ink-soft); margin: 0;
}
.cf-over--dark { color: #B3A392; }

.cf-skip {
  position: fixed; z-index: 200; top: 8px; left: 8px;
  padding: 8px 14px; background: var(--sc-accent); color: var(--sc-accent-ink);
  font-weight: 700; transform: translateY(-180%);
}
.cf-skip:focus { transform: none; }

/* Fokusring: Signal-Gruen misst auf Papier 1,1:1 und waere dort unsichtbar.
   Zwei Stops einer Familie, gekeyt auf den Grund. */
:focus-visible { outline-color: var(--sc-ink); }
.cf-stage--hero :focus-visible, .cf-stage--work :focus-visible,
.cf-window :focus-visible { outline-color: var(--sc-accent); }

/* ================================================================= BAR == */

.cf-bar {
  position: fixed; z-index: var(--sc-z-chrome); inset: 0 0 auto 0;
  height: var(--cf-bar-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--cf-gut);
  pointer-events: none;
}
.cf-bar > * { pointer-events: auto; }
.cf-bar.is-dark { color: var(--cf-paper); }
.cf-bar.is-dark .cf-pill { background: var(--cf-paper); color: var(--sc-ink); }
.cf-bar.is-dark .cf-pill::after { background: var(--sc-accent); }
.cf-bar, .cf-bar .cf-pill { transition: color 240ms var(--sc-ease-out),
  background-color 240ms var(--sc-ease-out); }
.cf-bar__right { display: flex; align-items: center; gap: 10px; }
.cf-bar__mark { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.cf-bar__mark img { width: 26px; height: 26px; border-radius: var(--sc-r-sm); }
.cf-bar__mark span { font-size: 14px; font-weight: 700; letter-spacing: 0.15em; }

.cf-pill {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 20px; border-radius: var(--sc-r-pill);
  background: var(--sc-ink); color: var(--cf-paper);
  font-size: 12.5px; font-weight: 550; letter-spacing: 0.01em;
  text-decoration: none;
  box-shadow: var(--sc-e1);
  transition: transform 150ms var(--sc-ease-out), box-shadow 150ms var(--sc-ease-out);
}
.cf-pill::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--sc-accent); flex: none;
}
@media (hover: hover) and (pointer: fine) { .cf-pill:hover { box-shadow: var(--sc-e2); } }
.cf-pill:active { transform: translateY(1px); }
.cf-pill--ink { background: var(--sc-accent); color: var(--sc-accent-ink); }
.cf-pill--ink::after { background: var(--sc-ink); }
.cf-pill--big { padding: 16px 28px; font-size: 15px; }

/* ============================================================== AKT 1 ==
   Nach dem Vorbild der Referenz: die Zeile steht OBEN, die Buehne darunter
   ueber die ganze Breite. Das gibt dem Haufen Raum und der Seite einen
   Auftakt statt einer Illustration neben Text. */

.cf-hero {
  min-height: 100vh; display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  align-content: center; gap: clamp(20px, 3.4vh, 40px);
  padding: calc(var(--cf-bar-h) + 18px) var(--cf-gut) var(--cf-gut);
  background: var(--cf-paper);
}
.cf-hero__head {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: clamp(20px, 5vw, 90px); align-items: end;
  width: 100%; max-width: 92rem; margin-inline: auto;
}
.cf-hero__title {
  margin: 0; font-family: var(--sc-font-display);
  font-size: clamp(2.1rem, 4.2vw, 3.9rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 0.98;
}
.cf-hero__note {
  margin: 0 0 0.5em; max-width: 40ch; font-size: 14.5px; line-height: 1.58;
  color: var(--sc-ink-soft); text-wrap: pretty;
}

/* Die Buehne: volle Breite, warmer Studioverlauf, weiche Kante. */
.cf-stagebox {
  position: relative; width: 100%; max-width: 92rem; margin-inline: auto;
  min-height: 0; height: 100%;
  border-radius: var(--sc-r-lg);
  background:
    radial-gradient(120% 130% at 52% 34%, var(--cf-ivory) 0%, var(--cf-cream) 48%, var(--cf-sand) 100%);
  overflow: hidden;
  touch-action: pan-y;
}
.cf-stagebox canvas, .cf-core canvas, .cf-exp__viz canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.cf-stagebox .cf-2d, .cf-core .cf-2d, .cf-exp__viz .cf-2d { z-index: 0; }
.cf-stagebox .cf-gl, .cf-core .cf-gl, .cf-exp__viz .cf-gl { z-index: 1; }

.cf-marks { display: flex; justify-content: space-between; padding: 0 2px;
            max-width: 92rem; margin-inline: auto; width: 100%; }
.cf-marks i { position: relative; width: 11px; height: 11px; opacity: 0.4; }
.cf-marks i::before, .cf-marks i::after { content: ""; position: absolute; background: var(--sc-ink); }
.cf-marks i::before { inset: 50% 0 auto 0; height: 1px; }
.cf-marks i::after  { inset: 0 50% 0 auto; width: 1px; }

/* Basisregel fuer jede gepinnte Buehne. Sie war bei einem frueheren
   Blockaustausch mit verlorengegangen, wodurch die Buehnen ohne Innenabstand
   und ohne Raster liefen. */
.cf-stage {
  display: grid;
  padding: calc(var(--cf-bar-h) + 10px) var(--cf-gut) var(--cf-gut);
  background: var(--cf-paper);
}

/* ======================================================= DIE HELLE STRECKE */

.cf-run { position: relative; background: var(--cf-paper); }
.cf-ribbon-wrap { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }
.cf-ribbon { position: absolute; inset: 0; width: 100%; height: 100%; }
.cf-run > section { position: relative; z-index: 1; }

.cf-wrap { width: 100%; max-width: 78rem; margin-inline: auto; padding-inline: var(--cf-gut); }

/* -------------------------------------------------------------- AKT 2 -- */

.cf-claim { padding-block: clamp(1rem, 2.5vh, 2.5rem) clamp(3.5rem, 9vh, 7rem); }
.cf-claim__t {
  margin: 0 0 clamp(28px, 5vh, 56px); max-width: 16ch;
  font-family: var(--sc-font-display);
  font-size: clamp(3rem, 9.4vw, 9rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 0.9;
  text-wrap: balance;
}
.cf-claim__body {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(20px, 4vw, 64px); margin-left: auto; max-width: 62rem;
  padding: clamp(20px, 3vw, 34px);
  background: var(--cf-paper);
  border-radius: var(--sc-r-md);
}
.cf-lede {
  margin: 0; font-size: clamp(1.05rem, 1.5vw, 1.3rem); line-height: 1.46;
  letter-spacing: var(--sc-track-snug); text-wrap: pretty;
}
.cf-small { margin: 0; font-size: 14px; line-height: 1.6; color: var(--sc-ink-soft); text-wrap: pretty; }

/* -------------------------------------------------------------- AKT 3 -- */

.cf-stage--rail { padding-block: var(--cf-gut); align-items: center; background: transparent; }
.cf-rail { gap: 16px; align-items: center; height: 100%; padding-right: var(--cf-gut); }

.cf-card {
  flex: none; width: clamp(17rem, 22vw, 22rem);
  display: flex; flex-direction: column; gap: 10px;
  padding: 22px;
  border-radius: var(--sc-r-md);
  background: var(--cf-paper);
  border: 1px solid var(--cf-line);
  --i: 0;
}
.cf-card__link { text-decoration: none; }
.cf-card__link::after { content: ""; position: absolute; inset: 0; }
.cf-card { position: relative; }
.cf-card h3 {
  margin: 2px 0 0; font-family: var(--sc-font-display);
  font-size: 1.7rem; font-weight: 500; letter-spacing: var(--sc-track-tight); line-height: 1;
}
.cf-card__p { margin: 0; min-height: 4.5em; font-size: 13.5px; line-height: 1.5; color: var(--sc-ink-soft); }
.cf-spec {
  display: grid; grid-template-columns: auto 1fr; gap: 2px 12px;
  margin: 4px 0 0; padding-top: 14px; border-top: 1px solid var(--cf-line);
  font-size: 13px;
}
.cf-spec dt { font-family: var(--sc-font-mono); font-size: 9.5px; letter-spacing: 0.1em;
              text-transform: uppercase; color: var(--sc-ink-soft); align-self: center; }
.cf-spec dd { margin: 0; font-weight: 550; font-variant-numeric: tabular-nums; }

.cf-card--lead, .cf-card--end {
  width: clamp(19rem, 26vw, 27rem);
  border: 0; background: transparent; justify-content: center; padding: 0 4px;
}
.cf-card__lead {
  margin: 6px 0 0; font-family: var(--sc-font-display);
  font-size: clamp(1.9rem, 3vw, 2.9rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 1.02;
}
.cf-card--end { gap: 16px; }
.cf-card--end .cf-pill { align-self: flex-start; }
.cf-card--lead .cf-small, .cf-card--end .cf-card__p { min-height: 0; }

/* ------------------------------------------------- AKT 4 · EXPLODED ---- */

.cf-stage--exploded { background: var(--cf-paper); }
.cf-exp {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(20px, 4vw, 56px); align-items: center; height: 100%; min-height: 0;
}
.cf-exp__side { display: grid; gap: 16px; align-content: center; }
.cf-exp__t {
  margin: 0; font-family: var(--sc-font-display);
  font-size: clamp(1.9rem, 3.6vw, 3.4rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 1;
}
.cf-exp__rail { position: relative; margin-top: 6px; padding-left: 16px; }
/* Dieselbe senkrechte Bahn wie in der Seitenspalte von Client und Admin:
   gleiche Farbe, gleiche runde Kappe, gleiche Bedeutung "hier entlang". */
.cf-exp__track {
  position: absolute; left: 4px; top: 4px; bottom: 4px; width: 3px;
  border-radius: 3px; background: color-mix(in oklab, var(--sc-ink) 11%, transparent);
}
/* Bewegt wird ueber transform, nicht ueber top: top und height sind Layout und
   ziehen bei jedem Schritt Layout, Paint und Composite nach sich. Die Hoehe
   bleibt eine echte Hoehe und wird NICHT animiert: alle Zeilen der Liste sind
   gleich hoch, sie aendert sich also ohnehin nicht. Ueber scaleY waere sie
   zwar auch GPU, aber die runde Kappe wuerde mitskalieren und aus dem Strich
   eine Spitze machen. */
.cf-exp__mark {
  position: absolute; left: 4px; top: 0; width: 3px;
  height: var(--cf-mark-h, 0px);
  border-radius: 3px; background: #C0603C;
  transform: translateY(var(--cf-mark-t, 0px));
  transition: transform 420ms var(--sc-ease-out);
}
.cf-exp__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.cf-exp__list li {
  display: grid; grid-template-columns: 30px minmax(0, 11rem) minmax(0, 1fr);
  gap: 10px; align-items: baseline; padding: 8px 10px;
  border-radius: var(--sc-r-sm);
  color: var(--sc-ink-soft);
  transition: color 320ms var(--sc-ease-out), background-color 320ms var(--sc-ease-out);
}
.cf-exp__list span { font-family: var(--sc-font-mono); font-size: 10px; letter-spacing: 0.08em; }
.cf-exp__list b { font-family: var(--sc-font-display); font-size: 1.05rem; font-weight: 500;
                  letter-spacing: var(--sc-track-snug); }
.cf-exp__list em { font-style: normal; font-size: 12.5px; }
.cf-exp__list li[aria-current="true"] {
  color: var(--sc-ink); background: color-mix(in oklab, var(--cf-sand) 62%, transparent);
}
.cf-exp__list li[aria-current="true"] span { color: var(--cf-terra); }
.cf-exp__p { margin: 6px 0 0; max-width: 42ch; font-size: 14px; line-height: 1.55; color: var(--sc-ink-soft); }

/* Die Tiefenanzeige. Die Liste links sagt WAS gerade vorn liegt, diese Zeile
   sagt WIE TIEF man schon ist. Sie steht bewusst NEBEN dem preserve-3d-Kasten:
   ein Kind darin liegt bei z=0 und wuerde von den ausfahrenden Blaettern
   (bis z=+360px) verdeckt. */
.cf-exp__depth {
  position: absolute; right: 0; top: clamp(8px, 3vh, 34px); z-index: 5; margin: 0;
  display: flex; align-items: baseline; gap: 10px;
  font-family: var(--sc-font-mono);
}
.cf-exp__depth b {
  font-family: var(--sc-font-display); font-weight: 500;
  font-size: clamp(1.9rem, 3.4vw, 3.1rem); line-height: 0.9;
  letter-spacing: var(--sc-track-tight); color: var(--sc-ink);
  font-variant-numeric: tabular-nums;
}
.cf-exp__depth span { font-size: 11px; letter-spacing: 0.1em; color: var(--sc-ink-soft); }
.cf-exp__depth em {
  font-style: normal; font-family: var(--sc-font-display); font-size: 13px;
  letter-spacing: var(--sc-track-snug); color: var(--sc-ink-soft);
  padding-left: 10px; border-left: 1px solid var(--cf-line);
}

/* Der Ebenenstapel: echte Aufnahmen und echtes Markup in CSS-3D. Als Textur
   auf einer WebGL-Flaeche waeren die Seiten an dieser Groesse nicht mehr
   lesbar gewesen, und lesbar war genau der Punkt. */
.cf-exp__viz {
  position: relative; height: 100%; min-height: 0;
  perspective: 1500px; perspective-origin: 44% 50%;
  transform-style: preserve-3d;
}
.cf-layer {
  position: absolute; left: 50%; top: 50%;
  width: min(100%, 54rem); aspect-ratio: 16 / 10;
  translate: -50% -50%;
  transform-origin: 50% 50%;
  border-radius: 10px; overflow: hidden;
  background: var(--cf-paper);
  box-shadow: 0 2px 6px rgba(43,33,25,.14), 0 34px 70px -30px rgba(43,33,25,.48);
  will-change: transform, opacity;
  /* KEINE Transition auf opacity. Der Wert wird in page.js jeden Frame gesetzt
     und ist dort ueber explodedP schon nachlaufend geglaettet. Eine Transition
     darueber wird jeden Frame neu angesetzt, kommt nie an und fuegt der
     Bewegung nur Verzoegerung hinzu. */
}
.cf-layer img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top left; }
/* Luftperspektive statt Deckkraft: ein wartendes Blatt bleibt deckend und
   wird nur Richtung Papierfarbe gewaschen. Sonst liest man durch den halben
   Stapel hindurch. */
.cf-layer::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--cf-paper); opacity: var(--cf-haze, 0);
}

/* Die vier technischen Ebenen sind kein Bild, sondern Markup. Sie standen
   vorher als fast leere, fast weisse Blaetter da: winziger Inhalt, mittig,
   Creme auf #FFFCF7. Jetzt fuellen sie ihr Blatt und tragen echten Kontrast,
   sonst liest der Stapel sich ab Ebene 04 als vier leere Zettel. */
.cf-layer--tech { background: var(--cf-ivory); border: 1px solid var(--cf-line); }
.cf-layer--tech::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 34px;
  background: var(--cf-sand); border-bottom: 1px solid var(--cf-line);
}
.lay-in {
  height: 100%; display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  gap: clamp(10px, 1.8vh, 20px);
  padding: clamp(48px, 6vh, 62px) clamp(22px, 3.2vw, 46px) clamp(20px, 3vh, 34px);
}
.lay-head { display: grid; gap: 3px; }
.lay-t { margin: 0; font-family: var(--sc-font-display); font-weight: 500;
         font-size: clamp(1.15rem, 2vw, 1.7rem); line-height: 1;
         letter-spacing: var(--sc-track-tight); color: var(--sc-ink); }
.lay-h { margin: 0; font-family: var(--sc-font-mono); font-size: 9.5px; letter-spacing: 0.12em;
         text-transform: uppercase; color: var(--sc-ink-soft); }

/* 03 · Frontend, und die Antwortseite von 04. Echter Code, in denselben
   warmen Werten gesetzt: Klammern und Tags gedaempft, Namen in Ink, Werte in
   Terrakotta. Kein Buntsatz, die Seite hat drei Farben. */
.lay-code {
  margin: 0; overflow: hidden;
  font-family: var(--sc-font-mono);
  font-size: clamp(9px, 0.86vw, 12px);
  line-height: 1.62;
  color: var(--sc-ink);
  white-space: pre;
  tab-size: 2;
}
/* Vier Werte, alle gemessen gegen den Grund des Blattes (#F7F3EC). --cf-taupe
   waere fuer Tags naheliegend gewesen und traegt dort 2,1:1: als Zierde
   vielleicht vertretbar, als Code nicht. --cf-terra fuer Zahlen lag bei
   2,9:1. Beide raus. */
.lay-code .c-t { color: #7d6b55; }                      /* Tags und Klammern */
.lay-code .c-a { color: var(--sc-ink-soft); }           /* Attribut, Schluessel */
.lay-code .c-v { color: var(--sc-accent); }             /* Zeichenkette */
.lay-code .c-n { color: var(--sc-ink); }                /* Zahl */
.lay-code .c-c { color: #7d6b55; font-style: italic; }  /* Kommentar */

/* Anfrage links, Antwort rechts. Das ist die Aussage der Ebene: eine
   Vertragsschicht hat zwei Seiten. */
.lay-split {
  display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
  gap: clamp(14px, 2.4vw, 34px); align-items: start; height: 100%;
}
.lay-code--json { font-size: clamp(9px, 0.8vw, 11.5px); }

/* 04 · API */
.lay-api { width: 100%; height: 100%; border-collapse: collapse; }
.lay-api td { padding: clamp(7px, 1.3vh, 13px) 0; border-bottom: 1px solid var(--cf-line);
              font-size: clamp(11px, 1.05vw, 14px); color: var(--sc-ink); vertical-align: baseline; }
.lay-api tr:last-child td { border-bottom: 0; }
.lay-api td:nth-child(1) { width: 4.6rem; }
.lay-api td:nth-child(3) { width: 3rem; text-align: right; font-family: var(--sc-font-mono);
                           font-size: 10px; color: var(--cf-terra); }
.lay-api td:nth-child(1) b {
  display: inline-block; font-family: var(--sc-font-mono); font-weight: 400;
  font-size: 9.5px; letter-spacing: 0.08em; padding: 3px 7px; border-radius: 4px;
  background: var(--cf-cream); border: 1px solid var(--cf-line); color: var(--sc-ink);
}
.lay-api td:nth-child(2) { font-family: var(--sc-font-mono); }

/* 05 · Backend */
.lay-grid { display: grid; height: 100%; grid-template-columns: repeat(2, minmax(0, 1fr));
            grid-auto-rows: minmax(0, 1fr); gap: clamp(7px, 1.3vh, 13px); }
.lay-grid span { display: grid; gap: 2px; padding: clamp(9px, 1.6vh, 15px) clamp(10px, 1.2vw, 16px);
                 border-radius: 8px; background: var(--cf-cream); border: 1px solid var(--cf-line); }
.lay-grid b { font-size: clamp(11px, 1vw, 13.5px); font-weight: 500; color: var(--sc-ink);
              letter-spacing: var(--sc-track-snug); }
.lay-grid em { font-style: normal; font-size: clamp(9.5px, 0.85vw, 11.5px); color: var(--sc-ink-soft); }

/* 06 · Database */
.lay-db { width: 100%; height: 100%; border-collapse: collapse; font-size: clamp(11px, 1.05vw, 14px); }
.lay-db td { padding: clamp(6px, 1.15vh, 12px) 0; border-bottom: 1px solid var(--cf-line);
             color: var(--sc-ink); }
.lay-db tr:last-child td { border-bottom: 0; }
.lay-db td:first-child { font-family: var(--sc-font-mono); width: 34%; }
.lay-db td:nth-child(2) { color: var(--sc-ink-soft); }
.lay-db td:last-child { text-align: right; font-family: var(--sc-font-mono);
                        font-variant-numeric: tabular-nums; }
.lay-note { margin: 0; font-size: 10.5px; color: var(--sc-ink-soft); }

/* 07 · Automation */
.lay-flow { list-style: none; margin: 0; padding: 0; height: 100%;
            display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
            gap: clamp(7px, 1vw, 14px); align-items: stretch; }
.lay-flow li { position: relative; display: grid; gap: 3px; align-content: start;
               padding: clamp(10px, 1.7vh, 17px) clamp(8px, 0.9vw, 13px);
               border-radius: 8px; background: var(--cf-cream); border: 1px solid var(--cf-line); }
.lay-flow b { font-size: clamp(10.5px, 0.95vw, 13px); font-weight: 500; color: var(--sc-ink);
              letter-spacing: var(--sc-track-snug); }
.lay-flow em { font-style: normal; font-size: clamp(9px, 0.8vw, 11px); color: var(--sc-ink-soft); }
/* Der Verbinder ist derselbe rundgekappte Terrakotta-Strich wie die Bahn. */
.lay-flow li + li::before {
  content: ""; position: absolute; top: 50%; left: calc(-1 * clamp(7px, 1vw, 14px) - 1px);
  width: clamp(7px, 1vw, 14px); height: 3px; border-radius: 3px; background: #C0603C;
}

/* ---------------------------------------------- AKT 5 · OBERFLAECHEN ---
   Hell wie die uebrige Seite. Der dunkle Block war der letzte Rest der
   alten, kuehlen Fassung und stand quer zur warmen Welt. */

.cf-stage--surfaces { background: var(--cf-paper); align-content: center;
                      gap: clamp(16px, 2.4vh, 30px); }
.cf-surf__head { display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr) minmax(0, 30rem);
                 align-items: end; column-gap: clamp(24px, 5vw, 80px); }
.cf-surf__t { margin: 0; grid-column: 1; font-family: var(--sc-font-display);
  font-size: clamp(1.8rem, 3.2vw, 3rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 1; }
.cf-surf__head .cf-over { grid-column: 1; }
.cf-surf__lede { grid-column: 2; grid-row: 1 / span 2; margin: 0; align-self: end;
  max-width: 42ch; font-size: 14px; line-height: 1.55; color: var(--sc-ink-soft); }

.cf-surf__grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 30px);
  padding-inline: clamp(14px, 2vw, 34px);
  min-height: 0; align-content: center; align-items: start;
}

.cf-surf {
  display: grid; gap: 12px; text-decoration: none; color: inherit;
  /* Hover-Antwort. 520ms lagen weit ueber dem Band fuer Dropdowns und Selects
     (150 bis 250ms) und lasen sich als traege. */
  transition: transform 200ms var(--sc-ease-out), opacity 200ms var(--sc-ease-out);
}
/* Echte Aufnahmen der echten Unterseiten. Beide Masse werden ueberschrieben,
   sonst loest das nicht gesetzte auf den Attributwert auf. */
.cf-surf__media {
  position: relative; display: block; aspect-ratio: 16 / 10;
  border-radius: var(--sc-r-lg); overflow: hidden;
  background: #fff;
  box-shadow: 0 1px 2px rgba(43,33,25,.10), 0 18px 40px -18px rgba(43,33,25,.34);
}
.cf-surf__media img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: top left;
  transform: scale(1.02);
  transition: transform 260ms var(--sc-ease-out), filter 260ms var(--sc-ease-out);
  filter: saturate(0.82) contrast(0.96);
}
.cf-surf[aria-current="true"] .cf-surf__media img { transform: scale(1.07); filter: none; }
.cf-surf__open {
  position: absolute; right: 10px; top: 10px; z-index: 2;
  font-family: var(--sc-font-mono); font-size: 9px; letter-spacing: 0.12em;
  text-transform: uppercase; padding: 5px 9px; border-radius: var(--sc-r-pill);
  background: var(--sc-ink); color: var(--cf-paper);
  opacity: 0; transform: translateY(-5px);
  transition: opacity 300ms var(--sc-ease-out), transform 300ms var(--sc-ease-out);
}
.cf-surf[aria-current="true"] .cf-surf__open { opacity: 1; transform: none; }

.cf-surf__meta { display: grid; grid-template-columns: 28px 1fr; gap: 1px 8px; align-items: baseline; }
.cf-surf__n { grid-row: span 2; font-family: var(--sc-font-mono); font-size: 10px;
              letter-spacing: 0.1em; color: var(--sc-ink-soft); padding-top: 5px; }
.cf-surf__name { font-family: var(--sc-font-display); font-size: clamp(1.05rem, 1.5vw, 1.45rem);
                 font-weight: 500; letter-spacing: var(--sc-track-tight); line-height: 1;
                 color: var(--sc-ink-soft); transition: color 380ms var(--sc-ease-out); }
.cf-surf__tags { font-family: var(--sc-font-mono); font-size: 9.5px; letter-spacing: 0.1em;
                 text-transform: uppercase; color: var(--sc-ink-soft); }
.cf-surf[aria-current="true"] .cf-surf__name { color: var(--sc-ink); }
.cf-surf[aria-current="true"] .cf-surf__n { color: var(--sc-accent); }

@media (hover: hover) and (pointer: fine) {
  .cf-surf[aria-current="true"] { transform: scale(1.05); z-index: 2; }
  .cf-surf:not([aria-current="true"]) { opacity: 0.62; transform: scale(0.95); }
}
.cf-surf:focus-visible { outline-offset: 6px; }

/* ------------------------------------------------- AKT 5 · DER UNTERBAU --
   Der Anschluss an Akt 4. Ohne ihn stehen sieben Ebenen und vier Oberflaechen
   als zwei Bilder nebeneinander und niemand sagt, wie sie zusammenhaengen. */
.cf-base {
  position: relative; display: grid; gap: 0;
  padding-inline: clamp(14px, 2vw, 34px);
}
.cf-base__wire { display: block; width: 100%; height: clamp(46px, 7vh, 88px); overflow: visible; }
.cf-base__layers {
  list-style: none; margin: 0; padding: clamp(10px, 1.6vh, 16px) clamp(12px, 1.6vw, 22px);
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: clamp(6px, 1vw, 16px);
  border-radius: var(--sc-r-md);
  background: color-mix(in oklab, var(--cf-sand) 52%, transparent);
}
.cf-base__layers li { display: grid; gap: 2px; min-width: 0; }
.cf-base__layers span { font-family: var(--sc-font-mono); font-size: 9px; letter-spacing: 0.1em;
                        color: var(--cf-terra); }
.cf-base__layers b { font-size: clamp(10px, 0.92vw, 12.5px); font-weight: 500; color: var(--sc-ink);
                     letter-spacing: var(--sc-track-snug); white-space: nowrap;
                     overflow: hidden; text-overflow: ellipsis; }

/* ============================================================== AKT 6 ==
   Kein Rendering mehr, sondern eine Sequenz: das Bild startet klein links
   und waechst beim Scrollen auf. Die Groesse kommt aus --sc-p, das die
   Engine auf dem Akt veroeffentlicht. */

.cf-stage--close { background: var(--cf-paper); align-content: center; }
.cf-close {
  display: grid; grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(24px, 4vw, 70px); align-items: center; height: 100%; min-height: 0;
}
.cf-close__copy { display: grid; gap: 18px; justify-items: start; align-content: center; }
.cf-close__t {
  margin: 0; font-family: var(--sc-font-display);
  font-size: clamp(2.2rem, 4.6vw, 4.4rem); font-weight: 500;
  letter-spacing: var(--sc-track-tight); line-height: 0.96; text-wrap: balance;
}
.cf-close__p { margin: 0; max-width: 40ch; font-size: 15px; line-height: 1.56; color: var(--sc-ink-soft); }

/* Die vier echten Schritte des Konfigurators laufen mit dem Scroll nacheinander
   voll. Aus dem blossen Groesserwerden wird dadurch eine Sequenz: das Bild
   kommt naeher, WAEHREND daneben etwas passiert. Der Fuellstand kommt aus
   --sc-p, das die Engine auf dem Akt veroeffentlicht. */
.cf-close__steps {
  list-style: none; margin: 0; padding: 0; width: 100%; max-width: 30rem;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px;
}
.cf-close__steps li { position: relative; display: grid; gap: 3px; padding-top: 10px; }
.cf-close__steps li::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; border-radius: 3px;
  background: color-mix(in oklab, var(--sc-ink) 11%, transparent);
}
/* scaleX statt width. Der Fuellstand haengt an --sc-p und wurde damit bei
   JEDEM Scrollframe auf vier Elementen neu berechnet: width ist Layout, also
   Layout, Paint und Composite pro Frame. Als transform bleibt es auf der GPU.
   Die Kappe verzieht sich dabei leicht, aber bei 3 Pixel Hoehe sieht das
   niemand. */
.cf-close__steps i {
  position: absolute; left: 0; top: 0; width: 100%; height: 3px;
  border-radius: 3px; background: #C0603C;
  transform-origin: 0 50%;
  transform: scaleX(clamp(0, calc(var(--sc-p, 0) * 4 - var(--i)), 1));
}
.cf-close__steps span { font-family: var(--sc-font-mono); font-size: 9px; letter-spacing: 0.1em;
                        color: var(--sc-ink-soft); }
.cf-close__steps b { font-size: 12.5px; font-weight: 500; color: var(--sc-ink);
                     letter-spacing: var(--sc-track-snug); }

/* Die Zeile rollt wortweise aus einer Maske herauf. Das ist Lusions
   Handschrift auf ihrer Featured-Work-Liste, und sie kommt mit denselben
   Mitteln wie alles andere hier: eine Kurve, eine Dauer, gestaffelte
   Verzoegerung. Die Woerter werden in page.js eingepackt, damit im Markup ein
   lesbarer Satz steht und keine Span-Suppe. */
.cf-roll { overflow: visible; }
.cf-roll__m { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 0.06em; }
.cf-roll__w {
  display: inline-block;
  transform: translateY(115%);
  transition: transform 700ms var(--cf-ease) calc(var(--i, 0) * 70ms);
}
.cf-roll.is-in .cf-roll__w { transform: none; }

.cf-close__shot {
  position: relative;
  display: block; justify-self: end; width: 100%;
  /* Waechst mit dem Scroll und richtet sich dabei auf: erst klein und schraeg
     im Raum, am Ende flach und gross. Nur transform, keine Layoutanimation. */
  /* --cf-g laeuft doppelt so schnell wie der Akt: die Aufnahme steht nach gut
     der halben Strecke fertig da, statt bis zum letzten Pixel zu wachsen. Der
     Rest des Akts gehoert dann der Zeile und dem Knopf. */
  --cf-g: clamp(0, calc(var(--sc-p, 0) * 2), 1);
  transform:
    perspective(1400px)
    translate3d(0, calc((1 - var(--cf-g)) * 3.5%), 0)
    rotateY(calc((1 - var(--cf-g)) * -13deg))
    rotateX(calc((1 - var(--cf-g)) * 4deg))
    scale(calc(0.58 + 0.42 * var(--cf-g)));
  transform-origin: 82% 50%;
}
/* Der Rahmen oeffnet sich waehrend des Wachsens aus einem Breitbild-Streifen
   auf sein volles Mass, und das Bild darin faehrt leicht gegen die Oeffnung.
   Dieses Gegenlaufen ist der Unterschied zwischen "ein Bild wird groesser"
   und "ein Bild geht auf": ohne es klebt der Inhalt am Rahmen und die Maske
   liest sich als Beschnitt. */
/* KEIN Vorhang mehr. Der Rahmen fuhr ueber scaleY senkrecht auf und das Bild
   skalierte dagegen. Rechnerisch stimmte das Bild, aber Rundung und Schatten
   wurden mitgestaucht, und man sah einen Letterbox-Ausschnitt statt der Seite:
   es sah gequetscht aus. Jetzt waechst die Aufnahme gleichmaessig und richtet
   sich dabei auf. Eine gleichmaessige Skalierung kann nicht quetschen. */
.cf-close__frame {
  display: block; position: relative; overflow: hidden;
  border-radius: var(--sc-r-lg); background: #fff;
  box-shadow: 0 2px 6px rgba(43,33,25,.12), 0 30px 64px -26px rgba(43,33,25,.42);
}
.cf-close__shot img {
  display: block; width: 100%; height: auto;
  transform: scale(var(--cf-zoom, 1));
  transition: transform var(--cf-dur) var(--cf-ease);
}
@media (hover: hover) and (pointer: fine) {
  .cf-close__shot:hover, .cf-close__shot:focus-visible { --cf-zoom: 1.04; }
}
/* Der Hinweis ist eine runde Marke in der Mitte, die auf Zeigergeraeten erst
   beim Ueberstreichen kommt. Eine Plakette unten links stand vorher genau auf
   dem "Weiter" der abgebildeten Seite, und eine dauerhafte Plakette auf einer
   Aufnahme ist ohnehin Beiwerk. Sie sitzt NEBEN dem Rahmen, nicht darin: im
   Rahmen braeuchte sie die Gegenskalierung des Vorhangs, und die Mitte ist
   ohnehin immer sichtbar, egal wie weit der Vorhang auf ist. */
.cf-close__hint {
  position: absolute; left: 50%; top: 50%; z-index: 2;
  /* Keine Gegenskalierung mehr noetig: es wird nichts mehr gestaucht. */
  display: grid; place-content: center; gap: 2px; text-align: center;
  width: 108px; height: 108px; border-radius: 50%;
  background: var(--sc-ink); color: var(--cf-paper);
  opacity: 0; transform: translate(-50%, -50%) scale(0.82);
  transition: opacity 420ms var(--cf-ease), transform 420ms var(--cf-ease),
              background-color 240ms var(--cf-ease);
}
.cf-close__hint b { font-family: var(--sc-font-display); font-size: 14px; font-weight: 500;
                    letter-spacing: var(--sc-track-snug); }
.cf-close__hint em { font-style: normal; font-family: var(--sc-font-mono); font-size: 8px;
                     letter-spacing: 0.12em; text-transform: uppercase; color: #C9BCAC; }

@media (hover: hover) and (pointer: fine) {
  .cf-close__shot:hover .cf-close__hint,
  .cf-close__shot:focus-visible .cf-close__hint {
    opacity: 1; transform: translate(-50%, -50%) scale(1);
  }
  .cf-close__shot:hover .cf-close__hint { background: var(--sc-accent); }
}
/* Ohne Zeiger gibt es kein Ueberstreichen. Dort steht sie einfach da, sobald
   das Bild weit genug offen ist. */
@media (hover: none) {
  .cf-close__hint { opacity: clamp(0, calc(var(--cf-g) * 2 - 0.9), 1);
                    transform: translate(-50%, -50%) scale(1); }
}

/* ================================================================ FOOT == */

.cf-foot {
  display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 28px clamp(24px, 6vw, 80px);
  padding: clamp(2.5rem, 6vh, 4.5rem) var(--cf-gut);
  background: var(--cf-deep); color: var(--cf-paper);
}
.cf-foot__brand img { width: 190px; height: auto; }
.cf-foot__brand p { margin: 14px 0 0; max-width: 44ch; font-size: 13.5px; line-height: 1.6; color: #B3A392; }
.cf-foot__nav { display: flex; flex-wrap: wrap; gap: 10px 26px; align-content: start; font-size: 13.5px; }
.cf-foot__nav a { text-decoration: underline; text-underline-offset: 0.24em;
                  text-decoration-color: color-mix(in oklab, #F4EFE6 40%, transparent); }
.cf-foot__meta {
  grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 8px 24px;
  margin: 0; padding-top: 22px;
  border-top: 1px solid color-mix(in oklab, #F4EFE6 16%, transparent);
  font-family: var(--sc-font-mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: #B3A392;
}

/* =============================================================== MOBIL == */

@media (max-width: 1000px) {
  .cf-hero__head { grid-template-columns: 1fr; gap: 12px; align-items: start; }
  .cf-hero__note { margin: 0; }
  .cf-claim__body { grid-template-columns: 1fr; }

  /* Ohne eigene Regeln stand die Textspalte ueber dem warmen Verlauf, und
     gedaempftes Grau auf Sand faellt unter 4,5:1. Beide Spalten trennen. */
  /* Drei Kinder, drei Zeilen: Text, Tiefenanzeige, Stapel. Mit nur zwei
     gesetzten Zeilen fiel der Stapel in eine implizite dritte, die Textspalte
     wurde geklemmt, und die Anzeige landete mitten auf den Blaettern. */
  .cf-exp { grid-template-columns: 1fr; grid-template-rows: auto auto minmax(0, 1fr); gap: 10px; }
  .cf-exp__side {
    background: var(--cf-paper); border-radius: var(--sc-r-md); padding: 12px 14px; gap: 8px;
  }
  .cf-exp__list li { grid-template-columns: 26px 1fr; gap: 2px 10px; padding: 5px 8px; }
  .cf-exp__list em { grid-column: 2; }
  .cf-exp__p { display: none; }

  .cf-exp__rail { padding-left: 13px; }
  .cf-exp__depth { position: static; margin: 0; gap: 8px; align-items: center; }
  .cf-exp__depth b { font-size: 1.1rem; }
  .cf-exp__depth em { font-size: 12px; padding-left: 8px; }

  .cf-surf__head { grid-template-columns: 1fr; gap: 8px; }
  .cf-surf__t, .cf-surf__head .cf-over, .cf-surf__lede { grid-column: 1; grid-row: auto; }
  .cf-surf__lede { max-width: none; font-size: 13px; }
  .cf-surf__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .cf-surf__media { aspect-ratio: 5 / 4; }

  /* Zwei Reihen Karten: eine Steigleitung pro Spalte statt pro Karte waere
     falsch beschriftet. Die Leitungen treten hier ganz zurueck, die
     Ebenenbank traegt den Anschluss allein. */
  .cf-base__wire { display: none; }
  .cf-base__layers { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px 12px;
                     margin-top: clamp(12px, 2vh, 20px); }

  .cf-close { grid-template-columns: 1fr; gap: 18px; align-content: center; }
  .cf-close__shot { transform: scale(calc(0.76 + 0.24 * var(--cf-g))); transform-origin: 50% 50%; }
  .cf-close__steps { max-width: none; }
}

@media (max-width: 860px) {
  :root { --cf-bar-h: 62px; }
  .cf-bar__mark span { display: none; }
  .cf-pill { padding: 9px 15px; font-size: 12px; }
  .cf-stage { padding: calc(var(--cf-bar-h) + 6px) var(--cf-gut) var(--cf-gut); }
  .cf-hero { padding-top: calc(var(--cf-bar-h) + 10px); }
  .cf-marks i:nth-child(2), .cf-marks i:nth-child(4) { display: none; }
  .cf-card { width: 78vw; }
  .cf-card--lead, .cf-card--end { width: 84vw; }
  /* Kein Klemmen mehr. Die Ueberschrift steht seit der Korrektur ueber den
     ganzen Akt, und ein max-height hat ihr die erste Zeile abgeschnitten,
     der Liste die letzten beiden. Stattdessen faellt die Beschreibung: der
     Name der Ebene traegt sie auf dieser Breite allein. */
  .cf-exp__side { max-height: none; overflow: visible; gap: 5px; }
  .cf-exp__t { font-size: clamp(1.4rem, 6.2vw, 1.9rem); }
  .cf-exp__list li { padding: 3px 8px; }
  .cf-exp__list em { display: none; }
  .cf-exp__list b { font-size: 0.94rem; }
  /* Flachere Perspektive: bei 1500px reicht ein Blatt auf dieser Hoehe ueber
     seinen Kasten hinaus und wird unten vom Bildschirmrand abgeschnitten. */
  .cf-exp__viz { perspective: 2400px; }

  /* Die vier technischen Blaetter sind fuer 780 Pixel Breite gesetzt und
     stehen hier auf 358. Sie tragen deshalb weniger, statt zu ueberlaufen. */
  .cf-layer--tech::before { height: 22px; }
  .lay-in { padding: 32px 14px 14px; gap: 7px; }
  .lay-t { font-size: 1rem; }
  .lay-h { font-size: 8px; }
  .lay-api td { padding: 4px 0; font-size: 10px; }
  .lay-api tr:nth-child(n+5) { display: none; }
  /* Auf 358 Pixel Blattbreite steht Code in zwei Spalten nicht mehr. Die
     Antwortseite faellt, die Anfrage traegt die Ebene allein. */
  .lay-split { grid-template-columns: 1fr; }
  .lay-code--json { display: none; }
  .lay-code { font-size: 8px; line-height: 1.5; }
  .lay-api td:nth-child(1) { width: 3.1rem; }
  .lay-api td:nth-child(1) b { font-size: 8px; padding: 2px 5px; }
  .lay-api td:nth-child(3) { width: 1.8rem; }
  .lay-grid { gap: 5px; }
  .lay-grid span { padding: 6px 8px; }
  .lay-grid b { font-size: 9.5px; }
  .lay-grid em { display: none; }
  .lay-db td { padding: 4px 0; font-size: 10px; }
  .lay-db td:nth-child(2) { display: none; }
  .lay-db tr:nth-child(n+5) { display: none; }
  .lay-flow { gap: 4px; }
  .lay-flow li { padding: 7px 4px; border-radius: 6px; }
  .lay-flow b { font-size: 8.5px; }
  .lay-flow em { display: none; }
  .lay-flow li + li::before { left: -5px; width: 5px; height: 2px; }
  .lay-note { font-size: 8.5px; }

  .cf-surf__tags { display: none; }
  .cf-surf__open { display: none; }
  .cf-base__layers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cf-close__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cf-foot { grid-template-columns: 1fr; }
  .cf-ribbon { opacity: 0.85; }
}

/* Gestaffeltes Setzen im Rail. Ohne das liest sich seitliche Fahrt als
   Diashow statt als Schublade. Die erste Karte ist ausgenommen, weil ein
   pan act seinen Einstieg schon zeigen muss. */
@media (prefers-reduced-motion: no-preference) {
  .cf-card:not(.cf-card--lead) {
    --t: clamp(0, (var(--sc-p, 0) - var(--i) * 0.05) * 7, 1);
    opacity: calc(0.55 + 0.45 * var(--t));
    transform: translate3d(0, calc((1 - var(--t)) * 24px), 0);
  }
}

/* ====================================================== REDUCED MOTION == */

@media (prefers-reduced-motion: reduce) {
  /* Der Hinweis lädt zu etwas ein, das hier abgeschaltet ist. */
  .cf-hint { display: none; }
  /* Das Schlussbild stand fertig da, drehte und wuchs aber weiter mit dem
     Scroll: genau die Bewegung, die hier abbestellt ist. Es steht jetzt
     einfach da, und die vier Schritte stehen voll. */
  .cf-close__shot { transform: none; }
  .cf-close__shot img { transform: none; }
  /* transform: none wuerde hier das Zentrieren mitnehmen: die Marke sitzt auf
     translate(-50%,-50%) und stuende sonst mit der linken oberen Ecke in der
     Mitte des Bildes. Nur die Skalierung faellt weg. */
  .cf-close__hint { transform: translate(-50%, -50%); opacity: 1; transition: none; }
  .cf-close__steps i { transform: scaleX(1); }
  .cf-roll__w { transform: none; transition: none; }
  .cf-window--work.is-lifted { transform: none; }
  .cf-projects button[aria-current="true"] .cf-proj__name { transform: none; }
}

.sc-grain { opacity: 0.03; }


/* ==================================================== DIE OBERFLAECHEN-KLAPPE ==
   Vier Oberflaechen hinter einem Knopf oben rechts, erreichbar von jeder
   Stelle der Seite. Ein volles Seitenmenue kam fuer diese Grammatik nicht in
   Frage: ein filmic one-shot hat einen Eingang und macht seine Reihenfolge
   nicht sichtbar. Vier Ziele hinter drei Punkten tun das nicht.
   Bewegung wie ueberall: Lusions Kurve, gestaffelte Verzoegerung je Zeile. */

.cf-menu { position: relative; }
.cf-menu__btn {
  display: grid; grid-auto-flow: column; align-items: center; gap: 4px;
  width: 44px; height: 44px; padding: 0; place-content: center;
  border-radius: 50%; border: 1px solid var(--cf-line);
  background: transparent; color: inherit; cursor: pointer;
  transition: background-color 240ms var(--cf-ease), border-color 240ms var(--cf-ease);
}
.cf-menu__btn i {
  display: block; width: 4px; height: 4px; border-radius: 50%;
  background: currentColor;
  transition: transform 400ms var(--cf-ease), background-color 240ms var(--cf-ease);
}
/* Aufgeklappt rueckt der mittlere Punkt heraus und wird Terrakotta: derselbe
   Punkt, den die Pille traegt, also dieselbe Sprache. */
.cf-menu__btn[aria-expanded="true"] i:nth-child(2) { background: var(--sc-accent); transform: scale(1.6); }
.cf-menu__btn[aria-expanded="true"] i:nth-child(1),
.cf-menu__btn[aria-expanded="true"] i:nth-child(3) { transform: scale(0.72); }
.cf-bar.is-dark .cf-menu__btn { border-color: rgba(244,239,230,.34); }
/* Ohne Gate bleibt der Hover-Zustand auf Beruehrgeraeten nach dem Tippen
   stehen, bis woanders hingetippt wird. */
@media (hover: hover) and (pointer: fine) {
  .cf-menu__btn:hover { background: color-mix(in oklab, var(--sc-ink) 7%, transparent); }
  .cf-bar.is-dark .cf-menu__btn:hover { background: rgba(244,239,230,.14); }
}

.cf-menu__panel {
  position: absolute; right: 0; top: calc(100% + 10px);
  width: min(86vw, 25rem);
  display: grid; gap: 4px;
  padding: 14px; border-radius: var(--sc-r-lg);
  background: var(--cf-ivory); border: 1px solid var(--cf-line);
  box-shadow: 0 2px 8px rgba(43,33,25,.14), 0 34px 70px -28px rgba(43,33,25,.52);
  color: var(--sc-ink);
}
.cf-menu__panel[hidden] { display: none; }
.cf-menu__panel .cf-over { padding: 2px 8px 6px; }

.cf-menu__row {
  --open-delay:  calc(50ms + var(--i, 0) * 40ms);
  --close-delay: 0ms;
  display: grid; grid-template-columns: 62px 26px minmax(0, 1fr);
  gap: 2px 10px; align-items: center;
  padding: 8px; border-radius: var(--sc-r-md);
  text-decoration: none; color: inherit;
  opacity: 0; transform: translateY(10px);
  transition: opacity 360ms var(--close-delay) var(--sc-ease-out),
              transform 360ms var(--close-delay) var(--sc-ease-out),
              background-color 200ms var(--sc-ease-out);
}
.cf-menu.is-open .cf-menu__row {
  opacity: 1; transform: none;
  transition: opacity 360ms var(--open-delay) var(--sc-ease-out),
              transform 360ms var(--open-delay) var(--sc-ease-out),
              background-color 200ms var(--sc-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .cf-menu__row:hover { background: color-mix(in oklab, var(--cf-sand) 52%, transparent); }
  .cf-menu__row:hover .cf-menu__n { color: var(--sc-accent); }
}
/* Das Vorschaubild ist nicht Zierde: es ist das Rechteck, aus dem die Ansicht
   aufwaechst. Ohne ein Rechteck im Format 16:10 muesste der FLIP in x und y
   verschieden skalieren und das Bild quetscht auf dem Weg. */
.cf-menu__thumb {
  grid-row: span 2; position: relative; display: block;
  aspect-ratio: 16 / 10; border-radius: var(--sc-r-sm); overflow: hidden;
  background: #fff; border: 1px solid var(--cf-line);
}
.cf-menu__thumb img { position: absolute; inset: 0; width: 100%; height: 100%;
                      object-fit: cover; object-position: top left; }
.cf-menu__n { font-family: var(--sc-font-mono); font-size: 9.5px; letter-spacing: 0.1em;
              color: var(--sc-ink-soft); align-self: end; }
.cf-menu__nm { font-family: var(--sc-font-display); font-size: 1.05rem; font-weight: 500;
               letter-spacing: var(--sc-track-tight); align-self: end; }
.cf-menu__tg { grid-column: 2 / -1; font-family: var(--sc-font-mono); font-size: 9px;
               letter-spacing: 0.1em; text-transform: uppercase; color: var(--sc-ink-soft); }

.cf-menu__foot {
  --open-delay: 260ms; --close-delay: 0ms;
  margin-top: 6px; padding: 11px 14px; border-radius: var(--sc-r-md);
  background: var(--sc-ink); color: var(--cf-paper);
  font-size: 12.5px; font-weight: 550; text-align: center; text-decoration: none;
  opacity: 0; transform: translateY(10px);
  transition: opacity 360ms var(--close-delay) var(--sc-ease-out),
              transform 360ms var(--close-delay) var(--sc-ease-out);
}
.cf-menu.is-open .cf-menu__foot {
  opacity: 1; transform: none;
  transition: opacity 360ms var(--open-delay) var(--sc-ease-out),
              transform 360ms var(--open-delay) var(--sc-ease-out);
}

@media (max-width: 560px) {
  .cf-menu__panel { width: min(92vw, 22rem); }
  .cf-menu__row { grid-template-columns: 50px 24px minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .cf-menu__row, .cf-menu.is-open .cf-menu__row,
  .cf-menu__foot, .cf-menu.is-open .cf-menu__foot { transition: none; transform: none; }
  .cf-menu__btn i { transition: none; }
}
