/* ============================================================
   agentella.de — Kreativagentur
   Editorial-Hell mit cinematischen Dunkel-Akten.
   Marken-DNA: warmes Creme + Mint-Splitter (Stracciatella),
   aber Ausführung type-first, awwwards-Niveau.
   ============================================================ */

:root {
  /* Helle Basis — helles Bone, damit Glas & Grün des Ella-Steins klar lesen */
  --bg: #f7f5f1;
  --bg-2: #efece5;          /* Bänder / leicht dunkler */
  --bg-raise: #fefdfb;      /* Panels */
  --text: #131d18;          /* dunkles Grün-Ink */
  --text-soft: #3a4941;
  --muted: #6b7a72;
  --line: rgba(5, 46, 33, .12);
  --hair: rgba(5, 46, 33, .18);

  /* Papierfaser als Grund aller hellen Flächen. Sie wird per `multiply` auf
     die jeweilige Grundfarbe gelegt statt sie zu ersetzen — nur so bleibt die
     Tonabstufung --bg / --bg-2 der Bänder erhalten. Die Kachel ist fast weiß,
     das Ergebnis ist deshalb bewusst kaum sichtbar: sie soll Oberfläche geben,
     nicht Muster. Fällt die Datei aus, bleibt die reine Grundfarbe stehen. */
  --papier: url(assets/mat-papier.webp);
  --papier-kachel: 420px;

  /* Mint — Gewürz, kein Anstrich */
  --accent: #3ec99b;
  --accent-2: #86efce;
  --accent-deep: #178a63;
  --accent-ink: #052e21;
  --accent-soft: rgba(62, 201, 155, .12);

  /* Dunkel-Akt */
  --d-bg: #080b0a;
  --d-bg-2: #101614;
  --d-text: #e9f2ee;
  --d-muted: #8a9a93;
  --d-accent: #86efce;
  --d-line: rgba(255, 255, 255, .10);

  --shadow-soft: 0 24px 60px -24px rgba(20, 30, 20, .30);
  --shadow-raise: 0 50px 110px -40px rgba(20, 30, 20, .45);

  --mono: "JetBrains Mono", ui-monospace, monospace;
  --sans: "Instrument Sans", system-ui, sans-serif;
  --display: "Sora", var(--sans);

  --ease: cubic-bezier(.25, 1, .5, 1);
  --ease-expo: cubic-bezier(.16, 1, .3, 1);

  --maxw: 1480px;
  --col: 1200px;
  --pad: clamp(22px, 7vw, 128px);
  --radius: 18px;
  color-scheme: light;
}

* { box-sizing: border-box; margin: 0; }
html { -webkit-text-size-adjust: 100%; }
html, body { overflow-x: clip; }

body {
  font-family: var(--sans);
  background-color: var(--bg);
  background-image: var(--papier);
  background-size: var(--papier-kachel);
  background-blend-mode: multiply;
  color: var(--text);
  font-size: clamp(16px, 1.1vw, 19px);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

::selection { background: var(--accent); color: var(--accent-ink); }
a { color: inherit; text-decoration: none; }
img, video, svg, picture, canvas { display: block; max-width: 100%; }

/* Ella-Stein — fixed WebGL-Layer, begleitet über die ganze Seite.
   Über dem Inhalt (Glas ist transparent), aber unter Topbar/Progress/Cursor;
   pointer-events aus, damit Klicks/Links darunter erreichbar bleiben. */
#stein-canvas {
  position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 100;
  pointer-events: none;
}
.orb-hit-target {
  position: fixed; z-index: 110; left: 0; top: 0; width: 120px; height: 120px;
  border-radius: 50%; background: transparent; touch-action: none;
  cursor: grab; pointer-events: auto; user-select: none; -webkit-user-select: none;
  will-change: transform;
}
.orb-hit-target.is-grabbed { cursor: grabbing; }
.orb-guide {
  position: absolute; z-index: 3; left: var(--pad); bottom: 28px;
  font: 500 .62rem/1.4 var(--mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
body.orb-understood .orb-guide { opacity: 0; transform: translateY(8px); }
@media (max-width: 760px) {
  .orb-guide { left: 22px; bottom: 22px; max-width: 22ch; }
}
@media (prefers-reduced-motion: reduce) {
  .orb-hit-target { display: none; }
  .orb-guide { display: none; }
}

/* Leichtes statisches Raster statt eines bei Scroll neu gerasterten
   SVG-Turbulence-Filters. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 90;
  pointer-events: none; opacity: .025;
  background-image: radial-gradient(rgba(5,46,33,.35) .45px, transparent .55px);
  background-size: 4px 4px;
}

/* ------------------------------------------------------------
   Tiefenebene — passives Material, das gegen den Inhalt läuft
   ------------------------------------------------------------
   Der ScrollSmoother versetzt sie über `data-speed`. Sie trägt NUR Material,
   nie Inhalt; deshalb darf sie über die Sektionskante hinausragen.

   Drei Entscheidungen hängen daran:
   • Reserve im `inset`: der Smoother verschiebt um bis zu
     (1−speed)·(Sektionshöhe+Viewport)/2 — bei speed 0.86 und einer 1500-px-
     Sektion sind das ~170 px. Ist die Reserve kleiner als der Versatz, zieht
     er die eigene Kante ins Bild. Die tragenden Sektionen clippen zusätzlich.
   • Transform (das macht der Smoother) statt `background-position`: der
     Versatz läuft im Compositor. Ein wandernder Hintergrund wäre ein
     Vollbild-Repaint pro Frame.
   • Ohne Smoother (kein JS, reduced-motion, ?static, Touch) bleibt sie
     unsichtbar. Eine stehende Zusatztextur wäre Rauschen ohne Zweck —
     deshalb `smooth-on` und nicht `gsap-ready`. */
.akt-grund {
  /* Reserve = fest + proportional. Der Versatz ist |1−speed|·(Höhe+Viewport)/2;
     bei der lauten Spreizung vom 2026-07-27 (0.64 bis 1.34 ⇒ |1−speed| ≤ 0.36)
     sind das bis zu 0.18·Höhe + 162 px. `-180px - 12%` reichte dafür nicht
     mehr (Akt V bräuchte 684 px und bekam 528). */
  position: absolute; inset: calc(-260px - 22%) 0; z-index: 0;
  pointer-events: none; opacity: 0;

  /* Ein GROSSFLÄCHIGES Lichtfeld statt einer Textur — das ist die Bedingung
     dafür, dass der Versatz überhaupt zu sehen ist. Eine gekachelte Struktur
     kann NICHT sichtbar driften: die 28-px-Kachel wandert um bis zu 340 px,
     ist also zwölf Perioden weiter und sieht exakt gleich aus. Nur eine nicht
     periodische Struktur trägt die Bewegung. (Erst mit Leinwandgewebe gebaut,
     gemessen, verworfen: die Kachel hat Mittelwert 104/255 und dunkelte die
     Tafel unter `multiply` um ~18 % ab — die Papierfaser tut das um 2,2 %.
     Die Tafel las sich als grauer Jutesack.)

     Stärke am 2026-07-27 auf Nutzer-Urteil („parallax sehe ich nicht")
     deutlich angehoben: Licht .34 → .78, Schatten .05 → .13. Die erste
     Fassung war so zurückhaltend, dass die Bewegung zwar messbar, aber
     nicht sichtbar war. */
  --ag-licht:
    radial-gradient(58% 44% at 28% 26%, rgba(255,255,255,.78), rgba(255,255,255,0) 72%),
    radial-gradient(52% 40% at 76% 74%, rgba(5,46,33,.13), rgba(5,46,33,0) 70%);
  background-image: var(--ag-licht);
}
body.smooth-on .akt-grund { opacity: var(--ag-op, 1); }
/* Akt V zusätzlich mit Autotypie-Raster: es gibt der längsten Lesestrecke
   Oberfläche. Die Bewegung trägt auch hier das Lichtfeld, nicht das Raster. */
.ag-raster {
  background-image:
    radial-gradient(rgba(5,46,33,.28) 1.1px, transparent 1.35px),
    var(--ag-licht);
  background-size: 28px 28px, auto, auto;
}

/* ============================================================
   Layout-Primitive
   ============================================================ */
.wrap { width: min(var(--maxw), 100%); margin-inline: auto; padding-inline: var(--pad); }
section { position: relative; padding-block: clamp(90px, 13vw, 210px); }

/* ---------- Eyebrow ---------- */
.eyebrow {
  font-family: var(--mono); font-weight: 500;
  font-size: .72rem; letter-spacing: .24em; text-transform: uppercase;
  color: var(--muted); display: inline-flex; align-items: center; gap: 12px;
}
.eyebrow::before { content: ""; width: 28px; height: 1px; background: var(--accent); }
.idx { font-family: var(--mono); font-weight: 500; font-size: .74rem;
  letter-spacing: .18em; color: var(--accent-deep); }

/* ---------- Typo ---------- */
h1, h2, h3, h4 { font-family: var(--display); font-weight: 700; letter-spacing: -.025em; line-height: 1.02; }
.display { font-weight: 800; letter-spacing: -.04em; line-height: .92;
  font-size: clamp(3.2rem, 9vw, 8.6rem); }
.h-sec { font-size: clamp(2.15rem, 5.2vw, 4.8rem); letter-spacing: -.03em; line-height: 1.0; }
.h-sub { font-size: clamp(1.4rem, 2.4vw, 2.15rem); font-weight: 700; letter-spacing: -.02em; }
.accent-word { color: var(--accent-deep); }
.lede { font-size: clamp(1.08rem, 1.35vw, 1.32rem); line-height: 1.5; color: var(--text-soft); max-width: 54ch; }
p.body { max-width: 60ch; color: var(--text-soft); }

.line { display: block; overflow: hidden; }
.line > * { display: block; }

/* ---------- Buttons ---------- */
.btn {
  --bpad: 15px 26px;
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--sans); font-weight: 600; font-size: .95rem;
  padding: var(--bpad); border-radius: 100px; border: 1px solid transparent;
  cursor: pointer; will-change: transform; position: relative; white-space: nowrap;
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.btn-primary { background: var(--accent-ink); color: #eafff5; }
.btn-primary:hover { background: var(--accent-deep); }
.btn-ghost { border-color: var(--hair); color: var(--text); }
.btn-ghost:hover { border-color: var(--accent-ink); }
.btn .arrow { transition: transform .3s var(--ease); }
.btn:hover .arrow { transform: translateX(4px); }


/* ---------- Scroll-Progress ---------- */
#progress { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 130; pointer-events: none; }
#progress span { display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-2)); transform-origin: left; }

/* ============================================================
   Preloader
   ============================================================ */
#preloader { display: none; }
html.preloading #preloader {
  position: fixed; inset: 0; z-index: 300; background: var(--bg);
  display: grid; place-content: center; gap: 30px;
}
.pl-inner { display: flex; align-items: baseline; gap: 14px; font-family: var(--display);
  font-weight: 800; letter-spacing: -.03em; font-size: clamp(1.6rem, 4vw, 2.8rem); }
.pl-mark { width: 44px; height: 44px; display: grid; place-items: center; align-self: center; }
.pl-mark svg { width: 100%; height: 100%; }
/* Zwei Klassen tief, damit die Wortmarken-Grundregel weiter unten die
   Preloader-Typografie nicht überschreibt. */
.pl-inner .pl-word { font-weight: 700; letter-spacing: -.045em; }
.pl-count { font-family: var(--mono); font-weight: 500; font-size: .9rem; color: var(--muted);
  letter-spacing: .1em; align-self: flex-end; }
.pl-bar { width: min(280px, 60vw); height: 1px; background: var(--hair); margin-inline: auto; overflow: hidden; }
.pl-bar span { display: block; height: 100%; width: 0%; background: var(--accent-ink); }

/* ============================================================
   Topbar
   ============================================================ */
#topbar {
  position: fixed; inset: 0 0 auto 0; z-index: 120;
  display: flex; align-items: center; gap: 28px;
  padding: 16px var(--pad);
  transition: background .4s var(--ease), backdrop-filter .4s var(--ease), padding .4s var(--ease), color .4s var(--ease);
}
#topbar.scrolled { background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(14px) saturate(1.2); padding-block: 11px; border-bottom: 1px solid var(--line); }
#topbar.on-dark { color: var(--d-text); }
#topbar.scrolled.on-dark {
  background: rgba(0, 8, 5, .78);
  border-bottom-color: rgba(134, 239, 206, .14);
}
#topbar.on-dark .brand-sub, #topbar.on-dark nav a { color: rgba(233,242,238,.66); }
#topbar.on-dark nav a:hover { color: #fff; }
#topbar .brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  width: 32px; height: 32px; display: grid; place-items: center; flex-shrink: 0;
}
.brand-mark svg { width: 100%; height: 100%; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-size: 15px; }
.brand-sub { font-family: var(--mono); font-size: 9px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }

/* ============================================================
   Marke — Signet + Wortmarke
   Signet: Ikosaeder als reine Kantenzeichnung in currentColor — keine
   Kachel, keine Füllfläche.
   Wortmarke: Sora 700, kleingeschrieben, Mint-Punkt am Ende.
   Verbindlich: docs/konzept/AGENTELLA-MARKE-PRODUKT-WEBSITE-2026.md §3.
   ============================================================ */
.signet-def { position: absolute; }
.wortmarke, .brand-name { font-family: var(--display); font-weight: 700; letter-spacing: -.01em; }
.wortmarke::after, .brand-name::after {
  content: ""; display: inline-block; vertical-align: baseline;
  width: max(3px, .25em); height: max(3px, .25em); margin-left: .1em;
  border-radius: 999px; background: var(--accent);
}
#topbar.on-dark .brand { --accent: var(--d-accent); }
#topbar nav { display: flex; gap: 4px; margin-left: auto; }
#topbar nav a {
  font-size: 14px; font-weight: 500; color: var(--muted); padding: 8px 12px; border-radius: 8px;
  transition: color .2s var(--ease);
}
#topbar nav a:hover { color: var(--text); }
#topbar .btn { padding: 9px 18px; font-size: 13px; }
@media (max-width: 860px) { #topbar nav { display: none; } }

/* Reveal-Grundzustände */
body.gsap-ready [data-reveal] { opacity: 0; }

/* ============================================================
   HERO
   ============================================================ */
.hero { position: relative; min-height: 100svh; display: flex; align-items: flex-end;
  padding-top: 128px; padding-bottom: clamp(48px, 8vh, 96px); overflow: hidden; }
#hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; }
.hero-veil { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(120% 90% at 70% 20%, transparent 40%, rgba(247,245,241,.5) 100%); }
.hero-type-field { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.hero-ghost {
  position: absolute; font-family: var(--display); font-weight: 800; line-height: .72;
  letter-spacing: -.085em; color: transparent; -webkit-text-stroke: 1px rgba(5,46,33,.11);
  font-size: clamp(18rem, 42vw, 44rem); white-space: nowrap;
}
.ghost-a { left: -6vw; top: 2vh; }
.ghost-b { left: 41vw; top: 36vh; color: rgba(134,239,206,.08); -webkit-text-stroke-color: rgba(23,138,99,.09); }
.hero-axis { position: absolute; background: rgba(5,46,33,.11); }
.axis-x { left: 0; right: 0; top: 47%; height: 1px; }
.axis-y { top: 0; bottom: 0; left: 71%; width: 1px; }
.hero-coordinate {
  position: absolute; right: var(--pad); top: 18%; writing-mode: vertical-rl;
  font: 500 .58rem/1 var(--mono); letter-spacing: .2em; color: rgba(5,46,33,.38);
}
.hero-inner { position: relative; z-index: 2; width: 100%; }
.hero-h1 { margin: 22px 0 clamp(30px, 5vw, 56px);
  font-size: clamp(3rem, 11vw, 10rem); font-weight: 800; letter-spacing: -.045em; line-height: 1; }
.hero-h1 em { font-style: italic; font-weight: 700; color: var(--accent-deep); }
.hero-foot { display: grid; gap: clamp(24px, 3vw, 40px); align-items: end;
  border-top: 1px solid var(--hair); padding-top: clamp(24px, 3vw, 38px); }
@media (min-width: 900px) { .hero-foot { grid-template-columns: 1.3fr 1fr; } }
.hero .lede { margin: 0; }
.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; align-content: end; }
@media (min-width: 900px) { .hero-cta { justify-content: flex-end; } }
.scroll-cue { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 3;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: 10px; letter-spacing: .24em; text-transform: uppercase; color: var(--muted); }
.scroll-cue .line { width: 1px; height: 40px; overflow: visible; background: linear-gradient(var(--accent), transparent); }

/* ============================================================
   AKT-MARKEN
   Der Seite fehlte eine Gliederung: elf Sektionen in Folge lesen
   sich als Liste, nicht als Film. Jeder Akt bekommt jetzt eine
   Nummer und einen Namen — dasselbe Mittel wie ein Kapitelinsert.
   Bewusst klein und mono: es gliedert, es schreit nicht.
   ============================================================ */
.akt-marke {
  display: flex; align-items: baseline; gap: 14px;
  font-family: var(--mono); font-size: .72rem; letter-spacing: .24em;
  text-transform: uppercase; margin-bottom: clamp(20px, 2.4vw, 34px);
}
.akt-nr {
  color: var(--accent-deep); font-weight: 600;
  padding-right: 14px; border-right: 1px solid var(--hair);
}
.akt-name { color: var(--muted); }
.akt-marke.on-dark .akt-nr { color: var(--d-accent); border-right-color: var(--d-line); }
.akt-marke.on-dark .akt-name { color: var(--d-muted); }

/* ============================================================
   LEISTUNGEN — sticky stack
   ============================================================ */
.services { position: relative; }
.services-intro { padding-block: clamp(40px, 7vw, 120px) clamp(18px, 4vw, 40px); }
.services-intro h2 { margin-top: 16px; max-width: 20ch; }
.services-lede { margin-top: clamp(20px, 2.4vw, 32px); }
.service { position: sticky; top: 0; min-height: 100svh; display: flex; align-items: center;
  background-color: var(--bg); background-image: var(--papier);
  background-size: var(--papier-kachel); background-blend-mode: multiply;
  border-top: 1px solid var(--hair);
  /* clippt die überstehende Reserve der `.akt-grund`-Ebene. Unbedenklich für
     das Sticky-Verhalten (nur overflow am VORFAHREN bricht sticky) — und in
     der Live-Fassung sind die Tafeln ohnehin `relative`, s. `orb-card-act`. */
  overflow: hidden; }
body.gsap-ready .service.orb-card-act { position: relative; top: auto; }
.service:nth-of-type(2n) { background-color: var(--bg-2); }
/* z-index explizit statt über Stacking-Context-Tricks: eine positionierte
   Ebene mit z-index 0 malt sonst ÜBER nicht positionierten Blockinhalt. */
.service-inner { display: grid; gap: clamp(28px, 4vw, 64px); align-items: center; width: 100%; padding-block: 64px;
  position: relative; z-index: 1; }
@media (min-width: 900px) {
  .service-inner { grid-template-columns: 1fr 1fr; }
  .service-inner.reverse .service-copy { order: 2; }
  .service-inner.reverse .service-media { order: 1; }
}
.service-copy .idx { display: block; margin-bottom: 18px; }
.service-copy h3 { margin-bottom: 18px; max-width: 17ch; }
.deliverables { list-style: none; display: grid; gap: 12px; margin-top: 26px; }
.deliverables li { position: relative; padding-left: 26px; color: var(--text-soft); font-size: .98rem; }
.deliverables li::before { content: ""; position: absolute; left: 0; top: .6em; width: 12px; height: 2px; background: var(--accent); }
.service-media { border-radius: 20px; overflow: hidden; box-shadow: var(--shadow-soft); position: relative; }

/* ============================================================
   KOMPOSITIONEN — eine je Leistung
   Vorher: sechsmal dasselbe Schema (Mono-Kicker + Riesenwort +
   Pill-Tags), nur mit anderem Wort und anderer Textur. Das las
   sich als Wireframe, nicht als Arbeitsprobe.
   Jetzt zeigt jede Fläche das Handwerk der jeweiligen Leistung:
   Fragmentsatz · Kanalraster · Nutzerweg · Druckbogen · Gewebe ·
   Ablauf mit Freigabepunkt. Weiter bildlos (Masterplan §1) —
   aber jede Fläche hat eine eigene Idee statt einer Variante.
   ============================================================ */
.komp {
  position: relative; isolation: isolate; height: 100%; min-height: 340px;
  padding: clamp(26px, 3vw, 46px);
  display: flex; flex-direction: column; gap: clamp(18px, 2.2vw, 30px);
  color: var(--accent-ink);
  background: var(--bg-raise);
  border: 1px solid rgba(5,46,33,.13);
  overflow: hidden;
}
.komp-label {
  font: 500 clamp(.58rem, .75vw, .7rem)/1.4 var(--mono);
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted);
}
.komp-fuss {
  margin-top: auto;
  font: 500 clamp(.58rem, .75vw, .7rem)/1.5 var(--mono);
  letter-spacing: .1em; color: var(--muted);
}

/* --- 01 Strategie: offene Fragen gerinnen zu einer Aussage --- */
.komp-strategie { background: color-mix(in srgb, var(--bg-raise) 88%, var(--accent-2)); }
.frag-feld { display: flex; flex-wrap: wrap; gap: 8px 10px; align-content: flex-start; }
.frag {
  font-family: var(--sans); font-size: clamp(.82rem, 1.05vw, .98rem);
  color: var(--text-soft); padding: 7px 14px; border-radius: 100px;
  border: 1px dashed rgba(5,46,33,.26); background: rgba(255,255,255,.5);
}
/* Bewusste Unruhe: die Fragen stehen noch nicht in Reih und Glied. */
.frag:nth-child(2) { transform: translateY(-3px) rotate(-1.2deg); }
.frag:nth-child(3) { transform: translateY(2px) rotate(.8deg); }
.frag:nth-child(5) { transform: translateY(-2px) rotate(1.4deg); }
.frag-loesung {
  margin-top: auto; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.5rem, 2.9vw, 2.5rem); line-height: 1.1; letter-spacing: -.03em;
  padding-top: clamp(18px, 2.2vw, 28px); border-top: 2px solid var(--accent);
}
.frag-loesung em { font-style: normal; color: var(--accent-deep); }

/* --- 02 Kampagne: derselbe Satz durch vier Kanäle --- */
.komp-kampagne { background: #f8f4eb; }
.kanal-raster { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; flex: 1; }
.kanal {
  display: flex; flex-direction: column; gap: 8px; padding: clamp(12px, 1.5vw, 18px);
  border: 1px solid rgba(5,46,33,.15); background: #fffdf8; overflow: hidden;
}
.kanal-typ {
  font: 500 .6rem/1 var(--mono); letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-deep);
}
.kanal p {
  font-family: var(--display); font-weight: 700; letter-spacing: -.025em;
  line-height: 1.05; color: var(--accent-ink); margin: 0;
}
/* Gleicher Satz, vier Zuschnitte — das ist die Aussage der Fläche. */
.kanal:nth-child(1) p { font-size: clamp(.95rem, 1.5vw, 1.3rem); }
.kanal:nth-child(2) p { font-size: clamp(1.25rem, 2.1vw, 1.85rem); }
.kanal:nth-child(3) p { font-size: clamp(.8rem, 1.2vw, 1.02rem); font-weight: 600; }
.kanal:nth-child(4) p { font-size: clamp(1.05rem, 1.7vw, 1.5rem); color: var(--accent-deep); }

/* --- 03 Digital: ein durchgehender Weg, keine Sackgasse --- */
.komp-digital { color: #eafff5; background: #07120e; border-color: rgba(134,239,206,.24); }
.komp-digital .komp-label, .komp-digital .komp-fuss { color: rgba(234,255,245,.62); }
.weg { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; flex: 1; align-content: center; }
.weg li {
  position: relative; display: flex; align-items: baseline; gap: 16px;
  padding: clamp(11px, 1.5vw, 17px) 0 clamp(11px, 1.5vw, 17px) 30px;
}
/* Die durchgehende Linie IST die Botschaft: ein Weg, nicht vier Kästen. */
.weg li::before {
  content: ""; position: absolute; left: 5px; top: 0; bottom: 0;
  width: 1px; background: rgba(134,239,206,.4);
}
.weg li:first-child::before { top: 50%; }
.weg li:last-child::before { bottom: 50%; }
.weg li::after {
  content: ""; position: absolute; left: 0; top: 50%; margin-top: -5.5px;
  width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid var(--d-accent); background: #07120e;
}
.weg li:last-child::after { background: var(--d-accent); box-shadow: 0 0 22px rgba(134,239,206,.5); }
.weg-nr { font: 500 .66rem/1 var(--mono); letter-spacing: .14em; color: rgba(234,255,245,.5); }
.weg-txt { font-family: var(--display); font-weight: 700; letter-spacing: -.03em;
  font-size: clamp(1.35rem, 2.6vw, 2.2rem); line-height: 1; }
.weg li:last-child .weg-txt { color: var(--d-accent); }

/* --- 04 Print: ein echter Druckbogen mit Schnittmarken und Falz --- */
.komp-print { background: #f8f4eb; }
.bogen {
  position: relative; flex: 1; margin: clamp(12px, 1.6vw, 20px);
  background: #fffdf8; border: 1px solid rgba(5,46,33,.14);
  box-shadow: 0 26px 46px -34px rgba(5,46,33,.5);
  display: grid; place-items: center;
}
/* Schnittmarken sitzen AUSSERHALB des Bogens — wie in echten Druckdaten. */
.schnitt { position: absolute; width: 15px; height: 15px; }
.schnitt::before, .schnitt::after {
  content: ""; position: absolute; background: rgba(5,46,33,.45);
}
.schnitt::before { width: 15px; height: 1px; top: 50%; }
.schnitt::after { width: 1px; height: 15px; left: 50%; }
.s-ol { top: -20px; left: -20px; } .s-or { top: -20px; right: -20px; }
.s-ul { bottom: -20px; left: -20px; } .s-ur { bottom: -20px; right: -20px; }
.falz {
  position: absolute; left: 50%; top: 0; bottom: 0; width: 1px;
  background: repeating-linear-gradient(180deg, rgba(5,46,33,.4) 0 5px, transparent 5px 11px);
}
/* Der angelegte Satzspiegel auf dem Bogen — rechts vom Falz, damit die
   Falzlinie sichtbar bleibt und der Bogen als gefalztes Format liest. */
.bogen-satz {
  position: absolute; right: 9%; top: 16%; bottom: 16%; width: 33%;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 7%;
}
.bs-feld { display: block; height: 42%; background: var(--accent); border-radius: 2px; opacity: .9; }
.bs-zeile { display: block; height: 7%; background: rgba(5,46,33,.78); border-radius: 1px; }
.bs-gross { height: 12%; }
.bs-kurz { width: 58%; opacity: .5; }

/* --- 05 Textil: Gewebe mit gesticktem Feld --- */
.komp-textil { color: #eafff5; background: #0c2d22; border-color: rgba(134,239,206,.22); }
.komp-textil .komp-label, .komp-textil .komp-fuss { color: rgba(234,255,245,.62); }
.gewebe {
  position: relative; flex: 1; overflow: hidden;
  /* Kett- und Schussfäden: echtes Gewebe-Raster statt Deko-Linien.
     Darunter liegt jetzt echtes Leinwandgewebe. Der dunkle Schleier dazwischen
     hält den Tonwert der Tafel (#0c2d22) — ohne ihn hellen die hellen
     Baumwollfäden des Fotos die dunkle Komposition sichtbar auf. Fällt die
     Datei aus, ist der Schleier die Fläche und die Tafel liest wie vorher. */
  background:
    repeating-linear-gradient(90deg, rgba(134,239,206,.22) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(0deg, rgba(134,239,206,.14) 0 1px, transparent 1px 7px),
    linear-gradient(rgba(12,45,34,.74), rgba(12,45,34,.74)),
    url(assets/mat-gewebe.webp) center / 260px repeat;
}
.stich {
  position: absolute; left: 12%; right: 12%; top: 50%; height: clamp(46px, 7vw, 76px);
  transform: translateY(-50%);
  /* Steppstich-Kante oben und unten */
  border-block: 2px dashed var(--d-accent);
  background: rgba(134,239,206,.1);
  box-shadow: 0 0 40px rgba(134,239,206,.16) inset;
}

/* --- 06 KI: Ablauf, der an einem Menschen anhält --- */
.komp-ki {
  color: #eafff5; border-color: rgba(134,239,206,.24);
  background:
    radial-gradient(circle at 22% 18%, rgba(134,239,206,.18), transparent 34%),
    #071b14;
}
.komp-ki .komp-label { color: rgba(234,255,245,.7); }
.ablauf { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; flex: 1; align-content: center; }
.ablauf li {
  display: flex; align-items: center; gap: 14px;
  padding: clamp(11px, 1.4vw, 16px) clamp(14px, 1.8vw, 20px);
  border: 1px solid rgba(134,239,206,.2); border-radius: 10px;
  font-size: clamp(.85rem, 1.1vw, 1rem); color: rgba(234,255,245,.78);
}
.ab-typ {
  flex: none; font: 500 .56rem/1 var(--mono); letter-spacing: .14em;
  text-transform: uppercase; color: rgba(234,255,245,.42);
  border-right: 1px solid rgba(134,239,206,.2); padding-right: 14px; min-width: 9ch;
}
/* Der Haltepunkt ist der Punkt der ganzen Leistung — er wird betont. */
.ablauf li.halt {
  color: #eafff5; font-weight: 600;
  border-color: var(--d-accent); background: rgba(134,239,206,.09);
  box-shadow: 0 0 34px -12px rgba(134,239,206,.5);
}
.ablauf li.halt .ab-typ { color: var(--d-accent); border-right-color: rgba(134,239,206,.45); }

@media (max-width: 620px) {
  .komp { min-height: 300px; }
  .kanal-raster { grid-template-columns: 1fr; }
  .kanal:nth-child(3), .kanal:nth-child(4) { display: none; }
  .ab-typ { display: none; }
}

/* Orb → Card: Der WebGL-Körper übernimmt Rahmen und Material. Der DOM-Inhalt
   bleibt semantisch vorhanden, wird aber erst sichtbar, wenn die Glasfläche
   stabil steht. Ohne Motion/JS ist die Card sofort normal lesbar. */
.orb-card-target {
  --orb-card-reveal: 1;
  --orb-card-clip: 0%;
  --orb-card-scale: 1;
  --orb-card-saturation: 1;
  --orb-card-frost: 0;
  --orb-card-blur: 0px;
  isolation: isolate;
  aspect-ratio: 16 / 9;
  background: rgba(247, 245, 241, .36);
}
.orb-card-content {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
}
.orb-card-content > .komp {
  width: 100%; height: 100%;
  border: 0; border-radius: inherit; box-shadow: none;
}
/* Die Kompositionen sind dichter als die alten Riesenwort-Flächen (Kanalraster,
   vierstufiger Weg, Ablaufliste). Im 16:9-Wrapper blieben davon 215 px Höhe —
   zu wenig. Die Leistungsflächen bekommen deshalb 4:3 plus Mindesthöhe. */
.service-media.orb-card-target { aspect-ratio: 4 / 3; }
/* Damit das Zurückweichen der Fläche (rotateX/z) überhaupt Tiefe hat. */
.service-inner { perspective: 1600px; }
@media (min-width: 900px) {
  .service-media.orb-card-target { min-height: 400px; }
}
.orb-card-content::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: rgb(239 255 249 / var(--orb-card-frost));
}
body.gsap-ready .orb-card-target {
  --orb-card-reveal: 0;
  --orb-card-clip: 48%;
  --orb-card-scale: .965;
  --orb-card-saturation: .72;
  --orb-card-contrast: 1;
  --orb-card-frost: 0;
  --orb-card-blur: 0px;
  box-shadow: none;
  background: transparent;
  overflow: visible;
}
body.gsap-ready .orb-card-target .orb-card-content {
  opacity: var(--orb-card-reveal);
  clip-path: inset(var(--orb-card-clip) round 18px);
  transform: scale(var(--orb-card-scale));
  filter: saturate(var(--orb-card-saturation)) contrast(var(--orb-card-contrast));
  will-change: opacity, transform, clip-path, filter;
}
body.gsap-ready .orb-card-target::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 20px;
  pointer-events: none;
  opacity: calc(var(--orb-card-reveal) * .2);
  box-shadow: inset 0 0 0 1px rgba(203, 255, 235, .44),
              0 24px 64px -38px rgba(17, 122, 83, .42);
}
/* Flow-Variante: Tafeln, die keine 16:9-Medienfläche sind (Tabellen, Karten-
   raster, Kontaktkarte). Der orb-card-target ist ein transparenter Wrapper um
   das bereits gestylte Panel; die Materialisierung (Clip/Frost/Scale-Reveal)
   greift, das Panel behält Hintergrund, Höhe und Eigenfarbe. */
.orb-card-target.orb-card-flow { aspect-ratio: auto; background: transparent; box-shadow: none; }
.orb-card-flow .orb-card-content { position: relative; inset: auto; overflow: visible; }

/* Live-Brand-Panel (ersetzt Fake-Text-Bild) */
.brand-panel { background: var(--bg-raise); border: 1px solid var(--line); aspect-ratio: 4/3;
  display: flex; flex-direction: column; justify-content: space-between; padding: clamp(24px, 3vw, 40px); box-shadow: var(--shadow-soft); }
.bp-top { display: flex; align-items: flex-start; justify-content: space-between; }
.bp-mono { font-family: var(--display); font-weight: 800; font-size: clamp(3rem, 8vw, 6rem);
  line-height: .8; letter-spacing: -.05em; color: var(--accent-ink); }
.bp-specimen { text-align: right; }
.bp-display { display: block; font-family: var(--display); font-weight: 800; font-size: clamp(1.4rem, 3vw, 2.2rem); color: var(--accent-deep); letter-spacing: -.03em; }
.bp-sub { font-family: var(--mono); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.bp-swatches { display: flex; gap: 0; border-radius: 10px; overflow: hidden; height: clamp(38px, 6vw, 56px); }
.bp-swatches span { flex: 1; background: var(--c); }
.bp-swatches span:last-child { box-shadow: inset 0 0 0 1px var(--line); }
.bp-grid { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bp-grid svg { width: 30px; height: 30px; color: var(--accent-ink);
  background: linear-gradient(135deg, var(--accent-2), var(--accent)); border-radius: 8px; padding: 6px; }
.bp-tag { font-family: var(--mono); font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--line); border-radius: 100px; padding: 5px 12px; }

/* ============================================================
   AKT I — DIE THESE (früher „Signatur-Akt", stand hinter den
   Leistungen). Der Kernsatz ist jetzt der zweite Bildschirm der
   Seite: erst die Behauptung, dann sechs Akte Beleg. Deshalb
   trägt der Akt jetzt auch den Manifest-Satz.
   ============================================================ */
.these { position: relative; min-height: 100svh; overflow: hidden; display: grid; align-items: center;
  padding-block: clamp(96px, 13vh, 156px) clamp(48px, 8vh, 96px); }
/* Zwei Zonen: links der Satz (immer lesbar, ab der ersten Etappe), rechts die
   Szene. Das IST die Text-Safe-Zone — kein Schleier, keine Ausblendung nötig. */
.these-grid { display: grid; gap: clamp(30px, 4.4vw, 66px); align-items: center; }
@media (min-width: 901px) { .these-grid { grid-template-columns: minmax(300px, .9fr) 1.1fr; } }
.these-copy { position: relative; z-index: 2; display: grid; gap: clamp(15px, 2vw, 24px); justify-items: start; }
.these-copy .akt-marke { margin-bottom: 0; }
.these-copy .display { font-size: clamp(2.1rem, 4.3vw, 4rem); }
/* Der frühere Manifest-Satz — jetzt der Nachsatz der These statt
   einer eigenen Sektion mit eigenem Anlauf. */
.these-satz {
  max-width: 42ch; font-size: clamp(1rem, 1.18vw, 1.18rem);
  line-height: 1.55; color: var(--text-soft);
}

/* ---------- Etappen-Register (echter Inhalt, nicht Dekoration) ---------- */
.zf-etappen { list-style: none; margin: clamp(4px, 1vw, 12px) 0 0; padding: 0;
  width: 100%; max-width: 46ch; border-top: 1px solid var(--line); }
.zf-etappen li { display: grid; grid-template-columns: 2.6rem 1fr; gap: 1px 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line); }
/* Nur solange das Rig läuft, ist das Register ein Fortschritt. Steht die
   Szene still (kein JS, schmal, reduced-motion), sind alle fünf gleich da. */
body.zf-live .zf-etappen li { opacity: .38; transition: opacity .4s var(--ease); }
body.zf-live .zf-etappen li.on { opacity: 1; }
.zf-nr { grid-row: span 2; font: 500 .62rem/1.9 var(--mono); letter-spacing: .16em; color: var(--accent-deep); }
.zf-name { font-weight: 600; font-size: .93rem; letter-spacing: -.01em; }
.zf-was { font-size: .8rem; line-height: 1.45; color: var(--muted); }
/* Die laufende Etappe bekommt einen Balken, der mit ihr durchläuft (--zf-line
   schreibt agentur.js). Damit ist das Register nicht nur an/aus, sondern zeigt,
   WIE WEIT die Etappe ist — dieselbe Information wie im Flug, nur lesbar. */
body.zf-live .zf-etappen li { position: relative; }
body.zf-live .zf-etappen li::after {
  content: ""; position: absolute; left: 0; bottom: -1px; height: 1px;
  width: calc(var(--zf-line, 0) * 100%); background: var(--accent-deep);
  transition: width .12s linear;
}
body.zf-live .zf-etappen li.on .zf-nr { color: var(--accent-ink); }

/* ============================================================
   DER ZOOMFLUG — Etappe wächst aus Etappe, ohne Schnitt
   ------------------------------------------------------------
   Bauprinzip: JEDE Ebene ist ein RAHMEN. Material sitzt im
   äußeren Band, die mittleren 50 % bleiben frei. Die nächste
   Ebene liegt bei Skalierung 0.5 exakt in diesem Loch. Eine
   Oktave weiter nimmt sie exakt den Platz der vorherigen ein —
   deshalb schneidet die Kamera nie.

   z-index MUSS absteigen (e1 oben, e5 unten): Ebene 0 hat immer
   die größte Skala, ist also immer die kameranächste.

   MATERIAL, NICHT DRAHTGITTER: keine Haarlinien, keine
   gestrichelten Rahmen, kein Kasten um die Bühne. Was hier liegt,
   hat Farbe, Gewicht und Schatten. Maße in `cqw` (Container-
   Query-Breite der Ebene), damit alles mit dem Zoom mitwächst
   statt in Pixeln stehen zu bleiben.

   Skala/Deckkraft/`--zf-local` schreibt agentur.js pro Frame.
   ============================================================ */
.zf-stage { display: grid; gap: clamp(14px, 2vw, 22px); width: 100%; justify-items: center; }
.zf-kamera { display: contents; }
.zf-ebene { --zf-local: 1; container-type: inline-size;
  position: relative; width: 100%; max-width: 460px; aspect-ratio: 1;
  background: #eafff8; border-radius: 14px; overflow: hidden; }
/* Ohne Rig liegen die drei Tiefenebenen einfach übereinander. */
.zf-tief { position: absolute; inset: 0; }

/* Das Rig läuft NUR, wenn agentur.js es wirklich treibt. Sonst bleiben oben
   fünf lesbare Blöcke stehen. Die Bühne blutet nach rechts aus dem Bild und
   hat KEINEN Rahmen — sie ist eine Szene, kein Bedienelement. Links löst sie
   sich weich auf; das ist zugleich die Text-Safe-Zone für die Copy-Spalte. */
body.zf-live .zf-stage {
  /* EIN Maß für Bühne und Ebene. Vorher war die Ebene (78vh) größer als die
     Bühne (46vw) — dadurch lagen die Bandelemente außerhalb des sichtbaren
     Felds und das große Wort wurde unten abgeschnitten. */
  --zf-side: min(78vh, 48vw);
  position: relative; display: block; overflow: visible; background: none;
  width: calc(100% + var(--pad)); height: var(--zf-side);
  margin-right: calc(var(--pad) * -1);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 13%),
                      linear-gradient(to bottom, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 13%),
                      linear-gradient(to bottom, transparent 0, #000 7%, #000 93%, transparent 100%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
/* Kamerakörper: trägt Roll und Drift des Flugs (agentur.js schreibt die
   Transform pro Frame). Die Maske bleibt auf der Bühne — würde sie
   mitrollen, wanderte die weiche Kante ins Bild. */
body.zf-live .zf-kamera {
  display: block; position: absolute; inset: 0;
  transform-origin: 50% 50%; will-change: transform;
}
body.zf-live .zf-ebene {
  position: absolute; left: 50%; top: 50%; width: var(--zf-side); aspect-ratio: 1;
  height: auto; max-width: none; background: none; border-radius: 0; overflow: visible;
  transform: translate(-50%, -50%); transform-origin: 50% 50%;
  visibility: hidden;
}
/* DIE TIEFE. Jede dieser drei Ebenen bekommt von agentur.js ihre EIGENE
   Skalierung 2.5^(x + data-z). Der Vordergrund (z > 0) eilt voraus und
   verlässt das Bild früher, der Grund (z < 0) bleibt lange stehen. Genau
   dieser Unterschied ist der Unterschied zwischen „Bild wird größer" und
   „ich fliege hindurch". */
body.zf-live .zf-tief {
  /* `inset: auto` MUSS vor left/top stehen — es setzt sonst beide zurück und
     die Ebene hängt an ihrer statischen Position statt in der Mitte. */
  position: absolute; inset: auto; left: 50%; top: 50%;
  width: 100%; aspect-ratio: 1; transform-origin: 50% 50%;
  transform: translate(-50%, -50%);
  /* KEIN `will-change: transform` — das war die Ursache des Schriftflackerns.
     Diese Ebenen skalieren durchgehend (2.5^(x+z), über den Flug von 0.13 auf
     3.4). Eine promotete Ebene rastert ihren Text EINMAL für eine bestimmte
     Skala und behält die Textur; weicht die Skala zu weit ab, rastert Chrome
     neu — bei fünfzehn gleichzeitig zoomenden Ebenen ergibt das ein
     dauerndes Nachschärfen, und genau das liest sich als Flackern.
     Ohne Promotion rastert der Browser pro Frame auf der aktuellen Skala:
     durchgehend scharf, keine Sprünge. Die Promotion bleibt auf `.zf-kamera`
     — die trägt nur Translation und Rotation, dort ist sie billig und
     verursacht kein Nachschärfen. */
}
body.zf-live .zf-e1 { z-index: 5; } body.zf-live .zf-e2 { z-index: 4; }
body.zf-live .zf-e3 { z-index: 3; } body.zf-live .zf-e4 { z-index: 2; }
body.zf-live .zf-e5 { z-index: 1; }

/* ---------- Grundflächen der Tiefenebene „Grund" (z < 0) ----------
   Rückwärtige Ebenen schrumpfen relativ zur Etappe. Ihr Material darf
   deshalb nicht als Kasten im Band liegen (es wanderte ins Loch), sondern
   ist eine VOLLE FLÄCHE MIT LOCHMASKE: `closest-side` heißt 100 % = halbe
   Breite, das Loch endet also bei 27.5 % — mal Faktor 0.76 (data-z −0.30)
   sind das 20.9 %, gerade außerhalb der 20 %, die die nächste Etappe
   einnimmt. Wird `data-z` verändert, muss dieser Wert nachgerechnet werden. */
.zf-grund {
  /* ÜBERGROSS (inset −18 %): die Fläche liegt hinten und schrumpft um Faktor
     0.76 — bei inset 0 ragte der Inhalt der Mittelebene über ihre Kante
     hinaus und die Etappe sah aus wie ein Fehler.
     Lochrechnung: Box = 136 % der Ebene ⇒ `closest-side` = 68 %. Loch bis
     43 % davon = 29.2 % der Ebene, mal 0.76 = 22.2 % der Etappe — außerhalb
     der 20 %, die die nächste Etappe einnimmt. Wird `data-z` geändert,
     müssen diese drei Zahlen neu gerechnet werden. */
  position: absolute; inset: -18%; border-radius: 2cqw;
  /* RECHTECKIGE ÖFFNUNG, keine weiche Kreisblende. Ein weicher Kreis las sich
     als Fleck in der Fläche; die scharfe Rechtecköffnung liest sich als
     Durchlass — und hat dieselbe Form wie die Etappe, die dahinter aufgeht.
     Lochrechnung: 29…71 % der Box = ±21 %, mal Boxgröße 1.36 = ±28.6 % der
     Ebene, mal Ebenenfaktor 0.76 = ±21.7 % der Etappe. Die nächste Etappe
     nimmt ±20 % ein — 1.7 % Luft. Bei geändertem `data-z` neu rechnen. */
  clip-path: polygon(evenodd,
    0% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%,
    29% 29%, 71% 29%, 71% 71%, 29% 71%, 29% 29%);
}

/* ---------- 01 · DER FUNKE — ein Blatt, eine Notiz, ein Licht ----------
   SCHICHTUNG ALLER FÜNF GRUNDFLÄCHEN (oben → unten):
   1. Tonanker — halbtransparenter Verlauf, hält die Palette und die
      Lichtrichtung der Seite über dem Foto.
   2. Das generierte Material (deckend, `cover`).
   3./4. Die alten CSS-Verläufe. Sie sind unter dem deckenden Foto unsichtbar
      und stehen NUR noch als Bildlos-Fallback da: fällt die WebP-Datei aus,
      sieht die Etappe exakt aus wie vor dem Einbau. Deshalb nicht löschen. */
.zf-blatt {
  background:
    linear-gradient(158deg, rgba(255,253,246,.34) 0%, rgba(228,217,194,.34) 100%),
    url(assets/zf-01-blatt.webp) center / cover no-repeat,
    repeating-linear-gradient(97deg, rgba(5,46,33,.055) 0 .16cqw, transparent .16cqw 1.1cqw),
    repeating-linear-gradient(6deg, rgba(5,46,33,.038) 0 .12cqw, transparent .12cqw 1.9cqw),
    linear-gradient(158deg, #fffdf6 0%, #f2ead9 58%, #e4d9c2 100%);
  box-shadow: 0 5cqw 11cqw -4cqw rgba(5,46,33,.34);
}
.zf-notiz { position: absolute; left: 5%; top: 6%; width: 47%; display: grid; gap: .9cqw; }
.zf-notiz b {
  font-family: var(--display); font-weight: 700; font-size: 5cqw; line-height: 1.02;
  letter-spacing: -.025em; color: var(--accent-ink);
  clip-path: inset(0 calc((1 - var(--zf-local)) * 100%) 0 0);
}
.zf-notiz i {
  font: 500 2.3cqw/1.3 var(--mono); font-style: normal; letter-spacing: .04em;
  color: var(--muted); text-decoration: line-through;
  text-decoration-color: rgba(5,46,33,.4); opacity: var(--zf-local);
}
/* Bleistiftbogen unten links — eine Geste, kein Symbol. */
.zf-krizel {
  position: absolute; left: 6%; bottom: 9%; width: 19%; height: 11%;
  border-left: .45cqw solid rgba(5,46,33,.45);
  border-bottom: .45cqw solid rgba(5,46,33,.45);
  border-bottom-left-radius: 4cqw; transform: rotate(-7deg);
  opacity: calc(var(--zf-local) * .9);
}
.zf-marginal {
  position: absolute; right: 5%; top: 7%;
  font: 500 2.1cqw/1 var(--mono); letter-spacing: .3em; color: rgba(5,46,33,.4);
}
/* Der Funke ist ein RING, kein Punkt: er umgibt die Öffnung, durch die
   geflogen wird, statt sie zuzudecken. Ein gefüllter Kern säße genau dort,
   wo Etappe 02 aufgehen muss. */
.zf-glut {
  position: absolute; inset: 28%; border-radius: 50%;
  background: radial-gradient(circle closest-side at 50% 50%,
    transparent 0 62%, rgba(62,201,155,.42) 78%, rgba(62,201,155,.12) 90%, transparent 99%);
  filter: blur(.14cqw); opacity: calc(.2 + var(--zf-local) * .45);
}
.zf-funke {
  position: absolute; width: 1.4cqw; aspect-ratio: 1; border-radius: 50%;
  background: var(--accent-deep); box-shadow: 0 0 3.4cqw .7cqw rgba(62,201,155,.66);
  opacity: var(--zf-local);
}
.zf-f1 { left: 24%; top: 21%; }
.zf-f2 { right: 25%; top: 26%; width: 1cqw; }
.zf-f3 { left: 29%; bottom: 23%; width: .8cqw; }

/* ---------- 02 · ES ORDNET SICH — Rastermappe mit echten Maßen ---------- */
.zf-blau {
  background:
    linear-gradient(150deg, rgba(230,238,234,.30), rgba(211,226,218,.30)),
    url(assets/zf-02-raster.webp) center / cover no-repeat,
    repeating-linear-gradient(0deg, rgba(5,46,33,.20) 0 .12cqw, transparent .12cqw 4cqw),
    repeating-linear-gradient(90deg, rgba(5,46,33,.20) 0 .12cqw, transparent .12cqw 4cqw),
    linear-gradient(150deg, #e6eeea, #d3e2da);
  box-shadow: inset 0 0 9cqw rgba(5,46,33,.12), 0 4cqw 9cqw -4cqw rgba(5,46,33,.3);
}
.zf-spalten {
  position: absolute; left: 5%; right: 5%; top: 5%; height: 17%;
  display: grid; grid-template-columns: repeat(12, 1fr); gap: 1cqw;
}
/* Die Spalten fahren nacheinander hoch — „es ordnet sich" ist ein Vorgang,
   kein Zustand. `--d` staffelt den Einsatz über den Etappen-Fortschritt. */
.zf-spalten i {
  background: linear-gradient(180deg, var(--accent-deep), var(--accent));
  border-radius: .35cqw; transform-origin: 50% 100%;
  transform: scaleY(clamp(0, calc((var(--zf-local) - var(--d, 0)) * 3), 1));
}
.zf-spalten i:nth-child(1){--d:0}.zf-spalten i:nth-child(2){--d:.03}
.zf-spalten i:nth-child(3){--d:.06}.zf-spalten i:nth-child(4){--d:.09}
.zf-spalten i:nth-child(5){--d:.12}.zf-spalten i:nth-child(6){--d:.15}
.zf-spalten i:nth-child(7){--d:.18}.zf-spalten i:nth-child(8){--d:.21}
.zf-spalten i:nth-child(9){--d:.24}.zf-spalten i:nth-child(10){--d:.27}
.zf-spalten i:nth-child(11){--d:.30}.zf-spalten i:nth-child(12){--d:.33}
.zf-mass {
  position: absolute; left: 5%; right: 5%; height: 0;
  border-top: .34cqw solid rgba(5,46,33,.72);
  clip-path: inset(0 calc((1 - var(--zf-local)) * 100%) 0 0);
}
.zf-mass::before, .zf-mass::after {
  content: ""; position: absolute; top: -1.5cqw; width: .34cqw; height: 3cqw;
  background: rgba(5,46,33,.72);
}
.zf-mass::before { left: 0; } .zf-mass::after { right: 0; }
.zf-mass-o { top: 26%; } .zf-mass-u { bottom: 23%; }
.zf-mass em {
  position: absolute; left: 50%; top: -1.7cqw; transform: translateX(-50%);
  font: 600 2.4cqw/1 var(--mono); font-style: normal; letter-spacing: .1em;
  color: var(--accent-ink); background: #e2ece7; padding: 0 1.4cqw; white-space: nowrap;
}
.zf-e2 .zf-balken {
  position: absolute; height: 2.1cqw; border-radius: 1.05cqw;
  background: var(--accent-ink); transform-origin: 50% 50%;
  transform: rotate(calc(var(--zf-wirr) * (1 - var(--zf-local)) * 1deg));
  opacity: calc(.55 + var(--zf-local) * .45);
}
.zf-e2 .zf-balken:nth-of-type(1) { left: 4%;  top: 9%;     width: 21%; --zf-wirr: -34; }
.zf-e2 .zf-balken:nth-of-type(2) { right: 4%; top: 13%;    width: 17%; --zf-wirr: 41; background: var(--accent); }
.zf-e2 .zf-balken:nth-of-type(3) { left: 4%;  bottom: 11%; width: 19%; --zf-wirr: 29; background: var(--accent); }
.zf-e2 .zf-balken:nth-of-type(4) { right: 4%; bottom: 15%; width: 23%; --zf-wirr: -37; }
.zf-e2 .zf-balken:nth-of-type(5) { left: 7%;  top: 19%;    width: 13%; --zf-wirr: 52; }
.zf-e2 .zf-balken:nth-of-type(6) { right: 7%; bottom: 24%; width: 11%; --zf-wirr: -19; }
/* Die zwei auf der Vordergrundebene liegen näher an der Achse — sonst wären
   sie aus dem Bild, bevor man sie gesehen hat. Was vorn liegt, ist immer
   größer als das, was es beschreibt. */
.zf-e2 [data-z="0.34"] .zf-balken:nth-of-type(1) { left: 22%;  top: 24%;    width: 15%; --zf-wirr: -22; }
.zf-e2 [data-z="0.34"] .zf-balken:nth-of-type(2) { right: 23%; bottom: 25%; width: 13%; --zf-wirr: 31; }

/* ---------- 03 · ES BEKOMMT FORM — Briefbogen, Karte, Fächer, Signet ---------- */
/* Tonanker hier deutlich kräftiger als bei den anderen vier Flächen: auf dem
   Tisch liegt mit dem Briefbogen ein FAST WEISSES DOM-Element, und der
   Lichtpool des Fotos sitzt genau darunter (oben links). Bei .30 verschwand
   der Bogen im Grund. Mit .64/.72 trägt wieder der ursprüngliche Verlauf die
   Tonarchitektur, das Foto liefert nur noch die Oberfläche. */
.zf-tisch {
  background:
    linear-gradient(146deg, rgba(250,247,241,.64), rgba(231,221,202,.72)),
    url(assets/zf-03-tisch.webp) center / cover no-repeat,
    repeating-linear-gradient(102deg, rgba(5,46,33,.04) 0 .2cqw, transparent .2cqw 2.4cqw),
    linear-gradient(146deg, #faf7f1, #e7ddca);
  box-shadow: inset 0 0 10cqw rgba(5,46,33,.08), 0 4cqw 9cqw -4cqw rgba(5,46,33,.3);
}
/* Der Briefbogen schiebt sich von oben ins Bild — gedruckt wird von oben. */
.zf-bogen-brief {
  position: absolute; left: 5%; top: 5%; width: 21%; height: 24%;
  background: #fffdf8; border-radius: .5cqw; overflow: hidden;
  box-shadow: 0 2.2cqw 4.6cqw -1.5cqw rgba(5,46,33,.42);
  display: grid; align-content: start; gap: 1.1cqw; padding: 2.2cqw 1.9cqw;
  clip-path: inset(calc((1 - var(--zf-local)) * 100%) 0 0 0);
}
.zf-wortmarke {
  font-family: var(--display); font-weight: 800; font-size: 3.3cqw;
  letter-spacing: -.035em; color: var(--accent-deep);
}
.zf-bogen-brief i { height: .45cqw; background: rgba(5,46,33,.15); border-radius: .3cqw; }
.zf-bogen-brief i:nth-of-type(2) { width: 76%; }
.zf-bogen-brief i:nth-of-type(3) { width: 52%; }
.zf-karte {
  position: absolute; right: 5%; bottom: 6%; width: 24%; height: 14%;
  background: var(--accent-deep); color: #eafff5; border-radius: .6cqw;
  display: grid; align-content: center; gap: .7cqw; padding: 0 2cqw;
  box-shadow: 0 2.6cqw 5.4cqw -1.7cqw rgba(5,46,33,.5);
  transform: rotate(calc((1 - var(--zf-local)) * -9deg))
             translateY(calc((1 - var(--zf-local)) * 26%));
  opacity: var(--zf-local);
}
.zf-karte b { font-family: var(--display); font-weight: 800; font-size: 2.9cqw; letter-spacing: -.035em; }
.zf-karte em { font: 500 1.5cqw/1.3 var(--mono); font-style: normal; letter-spacing: .1em; opacity: .72; }
.zf-faecher {
  position: absolute; left: 5%; bottom: 8%; width: 22%; height: 8.5%;
  display: grid; grid-template-columns: repeat(5, 1fr); gap: .7cqw;
}
.zf-faecher i {
  border-radius: .35cqw; box-shadow: 0 1cqw 2.2cqw -.9cqw rgba(5,46,33,.4);
  transform: translateY(calc((1 - var(--zf-local)) * 45%)); opacity: var(--zf-local);
}
.zf-faecher i:nth-child(1) { background: #f7f5f1; }
.zf-faecher i:nth-child(2) { background: #cdeee0; }
.zf-faecher i:nth-child(3) { background: var(--accent-2); }
.zf-faecher i:nth-child(4) { background: var(--accent); }
.zf-faecher i:nth-child(5) { background: var(--accent-deep); }
.zf-e3 .zf-signet {
  position: absolute; right: 5%; top: 6%; width: 16%; aspect-ratio: 1;
  border-radius: 50%; background: var(--accent-deep); overflow: hidden;
  clip-path: inset(0 0 calc((1 - var(--zf-local)) * 100%) 0);
}
.zf-e3 .zf-signet::after {
  content: ""; position: absolute; left: 0; right: 0; top: 54%; height: 12%;
  background: #f6f1e7;
}
.zf-wort {
  position: absolute; left: 4%; right: 4%; bottom: 3%; text-align: center;
  font-family: var(--display); font-weight: 800; font-size: 16cqw; line-height: .8;
  letter-spacing: -.06em; color: var(--accent-ink); white-space: nowrap;
  clip-path: inset(0 calc((1 - var(--zf-local)) * 100%) 0 0);
}

/* ---------- 04 · ES VERVIELFÄLTIGT SICH — vier Träger, EINE Form ----------
   Die Kästen bleiben knapp außerhalb des Lochs: 4 % Rand + 27 % Breite endet
   bei 31 %, aber nur auf Höhen bis 28 % — die Lochzeile beginnt erst bei 30 %. */
.zf-bank {
  background:
    linear-gradient(154deg, rgba(18,58,44,.34), rgba(10,37,28,.42)),
    url(assets/zf-04-bank.webp) center / cover no-repeat,
    repeating-linear-gradient(90deg, rgba(255,255,255,.03) 0 .3cqw, transparent .3cqw 3.2cqw),
    linear-gradient(154deg, #123a2c, #0a251c);
  box-shadow: inset 0 0 12cqw rgba(0,0,0,.45), 0 4cqw 10cqw -4cqw rgba(5,46,33,.5);
}
.zf-e4 .zf-traeger {
  /* Maße nachgemessen, nicht geschätzt: 3.5 % Rand + 24 % Breite endet bei
     27.5 %, und der Anflug schiebt höchstens 2.5 % nach — beides bleibt vor
     der Lochkante bei 30 %. Mit 4 % + 27 % + 18 % Anflug stieß die Ecke
     messbar in die Fläche, in der Etappe 05 aufgeht. */
  position: absolute; width: 24%; height: 21%; overflow: hidden;
  display: grid; align-content: center; justify-items: center; gap: .8cqw;
  border-radius: 1cqw; opacity: var(--t);
  transform: translateY(calc((1 - var(--t)) * 12%)) scale(calc(.82 + var(--t) * .18));
}
.zf-e4 .zf-traeger b {
  font-family: var(--display); font-weight: 800; font-size: 4.2cqw;
  letter-spacing: -.035em; line-height: 1;
}
.zf-e4 .zf-traeger em {
  font: 500 1.5cqw/1 var(--mono); font-style: normal; letter-spacing: .14em; opacity: .7;
}
.zf-e4 .zf-traeger:nth-of-type(1) { --t: clamp(0, calc((var(--zf-local) - .06) * 3.6), 1); left: 3.5%;  top: 3.5%; }
.zf-e4 .zf-traeger:nth-of-type(2) { --t: clamp(0, calc((var(--zf-local) - .18) * 3.6), 1); right: 3.5%; top: 3.5%; }
.zf-e4 .zf-traeger:nth-of-type(3) { --t: clamp(0, calc((var(--zf-local) - .30) * 3.6), 1); left: 3.5%;  bottom: 3.5%; }
.zf-e4 .zf-traeger:nth-of-type(4) { --t: clamp(0, calc((var(--zf-local) - .42) * 3.6), 1); right: 3.5%; bottom: 3.5%; }
.zf-bogen { background: #fffdf8; box-shadow: 0 2cqw 4cqw -1.6cqw rgba(0,0,0,.5); }
.zf-bogen b, .zf-bogen em { color: var(--accent-ink); }
.zf-screen { background: #07120e; box-shadow: 0 2cqw 4cqw -1.6cqw rgba(0,0,0,.55); }
.zf-screen b { color: var(--accent-2); } .zf-screen em { color: #8fd9be; }
.zf-screen::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(70% 60% at 50% 118%, rgba(134,239,206,.36), transparent 70%);
}
.zf-textil {
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.06) 0 .45cqw, transparent .45cqw .9cqw),
    repeating-linear-gradient(0deg, rgba(0,0,0,.10) 0 .45cqw, transparent .45cqw .9cqw),
    linear-gradient(rgba(12,45,34,.72), rgba(12,45,34,.72)),
    url(assets/mat-gewebe.webp) center / 12cqw repeat,
    #0c2d22;
  box-shadow: 0 2cqw 4cqw -1.6cqw rgba(0,0,0,.5);
}
.zf-textil b, .zf-textil em { color: #eafff5; }
.zf-schild { background: #e6f2ec; box-shadow: 0 1.6cqw 3.4cqw -1.4cqw rgba(0,0,0,.45); overflow: visible; }
.zf-schild b, .zf-schild em { color: var(--accent-ink); }
.zf-schild::after {
  content: ""; position: absolute; left: 26%; right: 26%; bottom: -24%; height: 24%;
  border-left: 1.5cqw solid rgba(5,46,33,.45); border-right: 1.5cqw solid rgba(5,46,33,.45);
}
.zf-e4 .zf-marginal { color: rgba(234,255,245,.45); right: auto; left: 50%; transform: translateX(-50%); top: 3%; }
.zf-schnipsel {
  position: absolute; width: 12%; height: 2.6%; border-radius: .3cqw;
  background: rgba(134,239,206,.5); opacity: calc(var(--zf-local) * .9);
}
.zf-sn1 { left: 8%;  top: 34%;    transform: rotate(-11deg); }
.zf-sn2 { right: 9%; bottom: 33%; transform: rotate(8deg); }

/* ---------- 05 · ES IST IM EINSATZ — alles hing an EINEM Band ----------
   Letzte Etappe: hier nistet nichts mehr, die Mitte darf voll sein.
   viewBox 100:60 == Boxformat 100 % : 60 % ⇒ `meet` verzerrt nicht, das
   dicke Band bleibt rund. Die Strichstärke skaliert bewusst MIT dem Zoom. */
.zf-weite {
  position: absolute; inset: -4%; border-radius: 3cqw;
  background:
    linear-gradient(168deg, rgba(253,250,243,.30) 0%, rgba(230,220,198,.34) 100%),
    url(assets/zf-05-weite.webp) center / cover no-repeat,
    repeating-linear-gradient(0deg, rgba(5,46,33,.05) 0 .1cqw, transparent .1cqw 7cqw),
    linear-gradient(168deg, #fdfaf3 0%, #f0e8d8 74%, #e6dcc6 100%);
  box-shadow: inset 0 0 14cqw rgba(5,46,33,.10);
  -webkit-mask-image: radial-gradient(circle closest-side at 50% 50%, #000 0 62%, transparent 100%);
          mask-image: radial-gradient(circle closest-side at 50% 50%, #000 0 62%, transparent 100%);
}
.zf-e5 .zf-linie { position: absolute; left: 0; top: 20%; width: 100%; height: 60%; overflow: visible; }
.zf-e5 .zf-linie-pfad {
  stroke: var(--accent); stroke-width: 7; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
}
.zf-station {
  position: absolute; width: 6.5cqw; aspect-ratio: 1; border-radius: 50%;
  background: var(--accent-ink);
  transform: translate(-50%, -50%) scale(var(--zf-local));
}
.zf-station em {
  position: absolute; left: 50%; top: 128%; transform: translateX(-50%);
  font: 500 2cqw/1 var(--mono); font-style: normal; letter-spacing: .14em;
  color: var(--accent-ink); white-space: nowrap; opacity: var(--zf-local);
}
/* Station 1 ist der Funke aus Etappe 01 — damit schließt sich der Flug. */
.zf-st-1 { left: 8%;  top: 62%; background: var(--accent-deep); width: 9cqw;
  box-shadow: 0 0 9cqw 1.5cqw rgba(62,201,155,.45); }
.zf-st-2 { left: 30%; top: 50%; }
.zf-st-3 { left: 52%; top: 56%; }
.zf-st-4 { left: 74%; top: 38%; }
.zf-st-5 { left: 92%; top: 30%; }

/* ============================================================
   DUNKEL-AKT — Unsere Maschine
   ============================================================ */
/* Reiner schwarzer Hintergrund — die Bühne für den Ella-Schwarm. */
.machine { position: relative; background: #000; color: var(--d-text); overflow: hidden;
  min-height: 100svh; padding-block: clamp(70px, 10vw, 120px); }
.machine-glow { position: absolute; z-index: 1; width: 70vw; height: 70vw; left: 50%; top: 55%; transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(82,219,171,.12), transparent 60%); filter: blur(30px); pointer-events: none; }
.machine-inner { position: relative; z-index: 2; max-width: 900px; text-align: center; margin-inline: auto;
  transition: opacity .6s var(--ease); }
.machine-inner h2 { margin: 18px 0 24px; }
.machine .h-sec { font-size: clamp(1.9rem, 4.2vw, 3.6rem); }
.machine-lede { margin: 0 auto; }
/* Heading tritt zurück, sobald der Schwarm die Karte projiziert. */
.machine.projecting .machine-inner { opacity: .22; }
/* Projektion sitzt zentral in der Bühne, der Schwarm rahmt sie im Bild.
   Absolut zentriert, damit der WebGL-Rahmen (folgt der mp-card-Rect) sie
   mittig im Licht-Pool trägt statt sie nach unten aus dem Bild rutschen zu lassen. */
.machine-projection { --machine-surface: 0; --machine-reveal: 0; --machine-clip: 46%; --machine-scale: .975;
  --machine-rim-angle: -70deg;
  position: absolute; z-index: 2; left: 50%; top: 52%; transform: translate(-50%, -50%);
  width: min(90vw, 560px); display: grid; place-items: center; }
@media (max-width: 600px) {
  .machine-projection { width: min(72vw, 560px); }
}
.machine-projection::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 20px;
  pointer-events: none;
  /* Sobald die finale Card erscheint, ist ihre Fläche bereits opak. Nur die
     Skalierung wächst aus der Würfelmitte; so gibt es keinen graugrünen,
     transparenten Zwischen-Screen auf schwarzem Grund. */
  opacity: 1;
  clip-path: inset(var(--machine-clip) round 18px);
  transform: scale(var(--machine-scale));
  background:
    radial-gradient(105% 78% at 22% 8%, #ffffff 0%, rgba(255,255,255,.86) 27%, transparent 58%),
    linear-gradient(145deg, #f4fffb 0%, #dff8ef 48%, #c9f1e3 100%);
  box-shadow:
    0 32px 96px -50px rgba(93, 238, 186, .66),
    inset 0 1px 0 rgba(255,255,255,.95);
}
.machine-projection:not(.is-projecting)::before,
.machine-projection:not(.is-projecting)::after { opacity: 0; }
.machine-projection::after {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 2;
  padding: 1.5px;
  border-radius: 21px;
  pointer-events: none;
  opacity: var(--machine-surface);
  clip-path: inset(var(--machine-clip) round 18px);
  transform: scale(var(--machine-scale));
  background: conic-gradient(
    from var(--machine-rim-angle),
    rgba(31, 149, 107, .2) 0deg,
    rgba(255, 255, 255, .98) 18deg,
    rgba(80, 218, 168, .48) 42deg,
    rgba(23, 128, 91, .16) 112deg,
    rgba(255, 255, 255, .88) 186deg,
    rgba(71, 210, 159, .38) 214deg,
    rgba(31, 149, 107, .2) 360deg
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

/* Pitch-Zeilen links & rechts, die beim Reinfliegen gestaffelt auftauchen. */
.machine-pitch { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.mp-side { position: absolute; top: 0; height: 100%; display: flex; flex-direction: column;
  justify-content: center; gap: clamp(28px, 7vh, 72px); width: min(28vw, 340px); }
.mp-left { left: var(--pad); align-items: flex-start; text-align: left; }
.mp-right { right: var(--pad); align-items: flex-end; text-align: right; }
.mp-side p { font-family: var(--display); font-weight: 700; letter-spacing: -.02em; line-height: 1.15;
  font-size: clamp(1.05rem, 1.7vw, 1.65rem); color: var(--d-text); max-width: 18ch;
  transition: opacity .7s var(--ease), transform .7s var(--ease); }
.mp-left p { transform: translateX(-30px); }
.mp-right p { transform: translateX(30px); }
.mp-side em { color: var(--d-accent); font-style: normal; }
body.gsap-ready .mp-side p:not(.on) { opacity: 0; }
/* `--mp-x` ist der gestaffelte Vorbeizug aus dem Maschinen-Scrub. Er läuft
   über DIESELBE `transform` wie der Auftritt (vorher `none`) — zwei Schreiber
   auf einer Eigenschaft hätten einander überschrieben. Die Transition trägt
   den Übergang vom Auftrittsversatz in den laufenden Drift. */
.mp-side p.on { opacity: 1; transform: translateX(var(--mp-x, 0px)); }
@media (max-width: 900px) { .machine-pitch { display: none; } }
.eyebrow.dark { color: var(--d-accent); }
.eyebrow.dark::before { background: var(--d-accent); }
.body.dark { color: #c7d6cf; max-width: 60ch; }
.machine .accent-word { color: var(--d-accent); }
.btn-mint { background: linear-gradient(135deg, var(--accent-2), var(--accent)); color: var(--accent-ink);
  margin-top: 30px; box-shadow: 0 12px 32px rgba(134,239,206,.24); }
.btn-mint:hover { transform: translateY(-2px); }

/* Projektion: der Ella-Schwarm bildet im fixed WebGL-Layer einen Rahmen um
   diese Karte; die Karte selbst ist DOM und wird beim Scrollen „projiziert".
   (Positionierung oben konsolidiert — hier nur noch die Glut/Karte.) */
.mp-glow { position: absolute; width: min(78vw, 760px); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgba(82,219,171,.22), transparent 62%);
  filter: blur(34px); pointer-events: none; opacity: calc(var(--machine-reveal) * .42); }
.mp-card { position: relative; z-index: 1; text-align: center; display: grid; gap: 16px; justify-items: center;
  padding: clamp(28px, 4vw, 52px) clamp(30px, 5vw, 76px);
  background: transparent; border: 0; border-radius: 20px;
  backdrop-filter: none; box-shadow: none;
  opacity: var(--machine-reveal);
  clip-path: inset(var(--machine-clip) round 18px);
  transform: scale(var(--machine-scale));
  will-change: opacity, clip-path, transform; }
.mp-card .btn-mint { margin-top: 8px; }
.machine-projection .btn-mint {
  background: #073c2c;
  color: #d9fff1;
  box-shadow: 0 14px 34px -18px rgba(4, 54, 39, .62);
}
.mp-eyebrow { font-family: var(--mono); font-size: .74rem; letter-spacing: .24em; text-transform: uppercase; color: #147453; }
.mp-line { font-family: var(--display); font-weight: 700; letter-spacing: -.02em;
  font-size: clamp(1.3rem, 2.6vw, 2rem); color: #0a2c21; max-width: 18ch; }
/* Ohne aktive Motion (reduced / kein JS / ?static) direkt sichtbar. */
body.gsap-ready .machine-projection:not(.is-projecting) .mp-card { opacity: 0; }
body.gsap-ready .machine-projection:not(.is-projecting) .mp-glow { opacity: 0; }

/* ============================================================
   ARBEITEN — horizontale Galerie
   ============================================================ */
.works { position: relative; padding-top: clamp(80px, 12vw, 160px); padding-bottom: 0; }
.works-head { margin-bottom: clamp(40px, 6vw, 72px); }
.works-head h2 { margin-top: 16px; }
.works-track-wrap { overflow: hidden; position: relative; }
/* Die Tiefenebene der fahrenden Galerie bewegt sich waagerecht, deshalb hier
   seitliche Reserve statt der senkrechten des Grundtyps. Sie wird in
   agentur.js eingehängt (nur mit Smoother) — im Markup steht sie nicht,
   weil sie ohne die horizontale Tween keinen Fortschritt hätte. */
.works-grund { inset: 0 -12%; }
.works-track { position: relative; z-index: 1;
  display: flex; gap: clamp(20px, 3vw, 44px); width: max-content;
  padding-inline: var(--pad); padding-bottom: clamp(80px, 12vw, 160px); }
.work-card { flex: 0 0 auto; width: min(84vw, 540px); }
.work-media { border-radius: 18px; overflow: hidden; box-shadow: var(--shadow-soft); aspect-ratio: 4 / 3; position: relative; }
.work-system {
  padding: clamp(22px, 3vw, 38px); display: flex; flex-direction: column;
  justify-content: flex-end; color: var(--accent-ink); border: 1px solid var(--line);
  background: #dff8ee;
}
.work-system::before {
  content: ""; position: absolute; inset: 0; opacity: .28;
  background: repeating-linear-gradient(90deg, transparent 0 11.9%, rgba(5,46,33,.12) 12%);
}
.work-system strong {
  position: relative; z-index: 1; font-family: var(--display); font-weight: 800;
  font-size: clamp(3.6rem, 8vw, 7rem); letter-spacing: -.075em; line-height: .8;
}
.work-system > div { position: relative; z-index: 1; display: flex; gap: 7px; margin-top: 24px; flex-wrap: wrap; }
.work-system > div span {
  padding: 6px 11px; border: 1px solid rgba(5,46,33,.2); border-radius: 100px;
  font: 500 .58rem/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
}
.ws-handel { background: #f4efe5; }
.ws-fitness { color: #eafff5; background: #0c2d22; }
.ws-fitness > div span { border-color: rgba(234,255,245,.3); }
.ws-gastro { background: #bcefdc; }
.ws-b2b { color: #eafff5; background: #07120e; }
.ws-b2b > div span { border-color: rgba(234,255,245,.3); }
.work-num { position: absolute; top: 16px; left: 18px; z-index: 2; font-family: var(--mono);
  font-size: .72rem; letter-spacing: .16em; color: #fff; mix-blend-mode: difference; }
/* ---- Akt IV: die Vorhaben-Tafeln materialisieren wie die Leistungstafeln ----
   Nutzer-Auftrag vom 2026-07-27: „sie sollten auch die displays des marquees
   bilden, so wie der eine orb es vorher bei den einzelnen cards macht."

   Bewusst NICHT über die Klasse `.orb-card-target`: die bringt `aspect-ratio:
   16/9`, einen eigenen Hintergrund und `overflow: visible` mit — das sind die
   Vorgaben der Leistungsflächen und würden die Systemkacheln zerlegen. Die
   Vorhaben-Tafeln behalten Rahmen, Format und Farbe; materialisiert wird nur
   ihr INHALT. Der stehende Rahmen ist hier zusätzlich nötig, weil die Tafeln
   in Fahrt sind: ein wachsender Rahmen würde in der Galerie flackern.

   Alles unter `body.gsap-ready` — ohne JS und bei reduced-motion (die Klasse
   wird dann nicht gesetzt) sind die Tafeln sofort vollständig lesbar. */
body.gsap-ready .work-media[data-orb-card] {
  --orb-card-reveal: 0;
  --orb-card-clip: 48%;
  --orb-card-saturation: .72;
  --orb-card-contrast: 1;
}
body.gsap-ready .work-media[data-orb-card] > *,
body.gsap-ready .work-media[data-orb-card]::before {
  opacity: var(--orb-card-reveal);
  clip-path: inset(var(--orb-card-clip) round 12px);
  filter: saturate(var(--orb-card-saturation)) contrast(var(--orb-card-contrast));
  will-change: opacity, clip-path, filter;
}
body.gsap-ready .work-media[data-orb-card]::before { opacity: calc(var(--orb-card-reveal) * .28); }
/* Solange die Tafel materialisiert, liegt der WebGL-Kranz auf ihrer Kontur.
   Ein zarter Saum macht sichtbar, dass die Körper die Tafel halten. */
body.gsap-ready .work-media[data-orb-card].is-materialized {
  box-shadow: var(--shadow-soft), inset 0 0 0 1px rgba(203, 255, 235, .5);
}

.work-cap { margin-top: 20px; }
.work-cap .idx { display: block; margin-bottom: 8px; color: var(--accent-deep); }
.work-cap p { color: var(--text-soft); max-width: 42ch; }
.work-cta { width: min(74vw, 440px); display: grid; place-items: center; align-self: stretch; }
.work-cta-inner { text-align: center; }
.work-cta-inner h3 { margin-bottom: 24px; }

/* ============================================================
   AKT V — DER RAHMEN
   Vorher drei aufeinanderfolgende Info-Sektionen (Arbeitsweise →
   dunkles Proof-Band → Budget). Das las sich als Anhang und nahm
   dem Schluss die Luft. Jetzt EIN Akt mit innerem Gefälle:
   Haltung → Zusagen → Zahlen. Das dunkle Band ist aufgelöst; der
   Tonwechsel gehört dem Schluss.
   ============================================================ */
.rahmen { padding-block: clamp(96px, 14vw, 200px); background: var(--bg-2); overflow: hidden; }
.rahmen > .wrap { position: relative; z-index: 1; }
.rahmen-kopf { margin-bottom: clamp(40px, 6vw, 72px); }
.rahmen-kopf h2 { max-width: 20ch; }
.rahmen-grid { display: grid; gap: clamp(36px, 5vw, 64px); align-items: start; }
@media (min-width: 900px) { .rahmen-grid { grid-template-columns: 1fr 1fr; } }
.rahmen-copy .body { margin-bottom: 16px; }

/* Zusagen — früher vier Display-Wörter im 4-Spalten-Raster, die sich
   bei „Erweiterbar"/„Transparent" gegenseitig überschrieben. Als
   Zeilenliste können die Wortlängen nicht mehr kollidieren. */
.zusagen {
  list-style: none; padding: 0; margin: clamp(48px, 7vw, 88px) 0 0;
  border-top: 1px solid var(--hair);
}
.zusagen li {
  display: grid; grid-template-columns: minmax(180px, .7fr) 1.3fr; gap: 28px;
  padding: clamp(15px, 1.8vw, 21px) 0; border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.zu-k {
  font-family: var(--display); font-weight: 700; letter-spacing: -.02em;
  font-size: clamp(1.05rem, 1.6vw, 1.4rem); color: var(--accent-ink);
}
.zu-t { color: var(--text-soft); }
@media (max-width: 620px) { .zusagen li { grid-template-columns: 1fr; gap: 4px; } }

/* Budget — eigener Atemzug im selben Akt, nicht mehr eigene Sektion. */
.budget { margin-top: clamp(90px, 13vw, 170px); }
.budget-kopf { margin-bottom: clamp(42px, 6vw, 72px); }
.budget-kopf h3 { max-width: 18ch; margin: 18px 0 24px; }

.warum-table { border: 1px solid var(--line); border-radius: 16px; overflow: hidden;
  background: var(--bg-raise); box-shadow: var(--shadow-soft); }
.wt-head, .wt-row { display: grid; grid-template-columns: 1fr 1fr; }
.wt-head span, .wt-row span { padding: 15px 18px; border-bottom: 1px solid var(--line); }
.wt-head span:first-child, .wt-row span:first-child { border-right: 1px solid var(--line); }
.wt-head { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.wt-row span { font-size: .92rem; }
.wt-row .yes { color: var(--text); }
.wt-row .no { color: var(--muted); }
.wt-row .yes::before { content: "✓ "; color: var(--accent-deep); font-weight: 700; }
.wt-row .no::before { content: "– "; color: var(--muted); }
.wt-row:last-child span { border-bottom: 0; }

/* ============================================================
   BUDGET-TAFELN — wenige klare Pakete statt Preisetiketten überall
   ============================================================ */
.investment-lede { margin-bottom: clamp(42px, 6vw, 72px); }
.investment-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 26px);
}
.investment-card {
  min-height: 330px; display: flex; flex-direction: column; align-items: flex-start;
  padding: clamp(24px, 3vw, 38px); border-top: 1px solid var(--hair);
  background: rgba(255,255,255,.35);
}
.investment-card.featured {
  color: var(--d-text); background: var(--accent-ink); border-color: var(--accent-2);
}
.investment-card.featured .idx, .investment-card.featured .investment-price {
  color: var(--accent-2);
}
.investment-card h3 { font-size: clamp(1.5rem, 2.5vw, 2.2rem); margin-top: 42px; }
.investment-card > p:last-child { color: var(--muted); margin-top: auto; max-width: 34ch; }
.investment-card.featured > p:last-child { color: var(--d-muted); }
.investment-price {
  font-family: var(--display); font-size: clamp(2rem, 3.5vw, 3.4rem);
  font-weight: 800; letter-spacing: -.04em; color: var(--accent-deep); margin: 12px 0 32px;
}
.investment-lines { margin-top: clamp(32px, 5vw, 60px); border-top: 1px solid var(--hair); }
.investment-lines p {
  display: grid; grid-template-columns: minmax(180px, .8fr) 1.4fr; gap: 28px;
  padding: 18px 0; border-bottom: 1px solid var(--line);
}
.investment-lines span { color: var(--muted); }
.investment-note { margin-top: 20px; max-width: 90ch; color: var(--muted); font-size: .82rem; }
@media (max-width: 900px) {
  .investment-grid { grid-template-columns: 1fr; }
  .investment-card { min-height: 270px; }
}
@media (max-width: 620px) {
  .investment-lines p { grid-template-columns: 1fr; gap: 4px; }
  .scroll-cue { display: none; }
  .hero-coordinate, .axis-y { display: none; }
  .hero-ghost { font-size: 15rem; }
  .ghost-a { left: -32vw; top: 18vh; }
  .ghost-b { left: 22vw; top: 50vh; }
  .work-system strong { font-size: clamp(3rem, 17vw, 5rem); }
  .these-copy .display { font-size: clamp(2rem, 9vw, 2.6rem); }
}

/* ============================================================
   AKT VI — DER SCHLUSS
   Die Seite endete bisher mit einer Preisliste und einer hellen
   Kontaktkarte. Ein Film hört nicht mit dem Anhang auf: der
   Schluss ist jetzt dunkel, groß und leer — der zweite und letzte
   Tonwechsel, der den Bogen zum Maschinen-Akt schließt.
   ============================================================ */
.schluss {
  background: var(--d-bg); color: var(--d-text);
  padding-block: clamp(120px, 20vw, 260px);
}
.schluss-inner { display: grid; justify-items: center; text-align: center; }
.schluss .display {
  font-size: clamp(2.6rem, 8vw, 7rem);
  margin: clamp(14px, 2vw, 26px) 0 clamp(26px, 3.4vw, 44px);
}
.schluss .accent-word { color: var(--d-accent); }
/* Auf Schwarz zeichnete der Glasrahmen der Orb-Tafel einen sichtbaren Kasten
   um die Schlusszeile. Die Materialisierung bleibt, der Rahmen entfällt —
   die Zeile soll frei im Dunkeln stehen. */
.schluss .orb-card-target { background: transparent; }
body.gsap-ready .schluss .orb-card-target::after { content: none; }
/* Der Frost-Schleier (rgb(239 255 249 / .022)) ist auf hellem Grund unsichtbar,
   auf Schwarz aber ein klar erkennbarer heller Kasten. Im Schluss abschalten. */
.schluss .orb-card-content::after { background: transparent; }
.schluss-lede { color: var(--d-muted); margin-bottom: clamp(32px, 4vw, 48px); }
.schluss .hero-cta { justify-content: center; }
/* Ghost-Button auf dunklem Grund — der helle .btn-ghost verschwindet hier. */
.btn-ghost-dark { border-color: var(--d-line); color: var(--d-text); }
.btn-ghost-dark:hover { border-color: var(--d-accent); color: var(--d-accent); }

/* ============================================================
   FOOTER
   ============================================================ */
footer { border-top: 1px solid var(--line); padding-block: clamp(56px, 8vw, 96px); }
.foot-big { font-family: var(--display); font-weight: 800; letter-spacing: -.04em; line-height: .92;
  font-size: clamp(2.6rem, 10vw, 8rem); margin-bottom: clamp(40px, 6vw, 72px); }
.foot-inner { display: grid; gap: 32px; padding-top: 40px; border-top: 1px solid var(--line); }
@media (min-width: 760px) { .foot-inner { grid-template-columns: 1.5fr 1fr 1fr; align-items: start; } }
.foot-brand { display: flex; gap: 14px; align-items: flex-start; }
.foot-brand p { font-size: .95rem; line-height: 1.5; }
.muted-t { color: var(--muted); }
.foot-nav, .foot-sub { display: flex; flex-direction: column; gap: 10px; font-size: .92rem; }
.foot-nav a, .foot-sub a { color: var(--muted); }
.foot-nav a:hover, .foot-sub a:hover { color: var(--text); }

/* ---------- CTA: Puls, wenn der Ella-Stein darauf tippt ---------- */
.btn.is-poked { animation: poke-pulse 1.1s var(--ease) infinite; }
@keyframes poke-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(62,201,155,.5); }
  50%      { transform: scale(1.04); box-shadow: 0 0 0 14px rgba(62,201,155,0); }
}

/* ---------- Diagonale Panels (statt statischer Karten) ----------
   Grundzustand vor dem Einfahren wird von agentur.js (data-fly) gesetzt;
   hier nur der ruhende, weniger „karten"-hafte Look. */
.service-media, .work-media { transform-origin: center; }
body.gsap-ready .service-media[data-fly],
body.gsap-ready .work-card[data-fly] { transform-origin: center; }

@media (max-width: 760px) {
  .service { position: relative; min-height: auto; }
  .service-inner { padding-block: 72px; }
  .works-track-wrap { overflow-x: auto; scrollbar-width: none; }
  .works-track-wrap::-webkit-scrollbar { display: none; }
}

/* ============================================================
   Reduced Motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  body.gsap-ready [data-reveal] { opacity: 1; }
  #stein-canvas { position: absolute; height: 100svh; }
  .service { position: relative; min-height: 0; padding-block: 40px; }
  .signature { height: auto; padding-block: 120px; }
  /* Der Zoomflug wird zur ruhigen Liste: fünf Etappen untereinander, jede
     in ihrem Endzustand (--zf-local bleibt auf 1). Kein Pin, kein Zoom. */
  .these { min-height: 0; padding-block: 90px; }
  .zf-etappen li { opacity: 1; }
  #preloader { display: none; }
}
