/* ============================================================================
   /pitch/ — Bühne + HUD, Grundstyles (Task 1: nur Gerüst, noch keine
   Szenen-Inhalte und noch keine Umblende-Logik, die kommt mit dem Szenen-
   Motor in einer der folgenden Wellen). Farben ausschließlich über
   var(--…)-Tokens aus colors_and_type.css, dunkle Bühne im Deep-Sea-Wells-Ton
   (--color-surface-sunken-dark, #14202F) wie der Leistungs-Viewer.
   Animations-Grundregel: nur transform/opacity, feste Layout-Boxen.
   ============================================================================ */

html, body { height: 100%; }

.pitch-body {
  margin: 0;
  overflow: hidden;
  background: var(--color-surface-sunken-dark);
  color: var(--fg-default);
  font-family: var(--font-body);
  /* HUD-Safe-Area (Feedback F1, zentraler Wert): unterer Sicherheitsabstand,
     der zentrierten Inhalt nach oben ausweichen lässt, damit er nie hinter
     der fixed positionierten HUD-Leiste (unten, ~84px hoch inkl. Abstand)
     landet. Einmal hier definiert statt an sechs Stellen dupliziert (siehe
     Verwendung bei .scene und den vier video-stage-Reasserts). */
  --hud-safe: clamp(110px, 12vh, 160px);
}

/* ---------- Bühne ---------- */
.stage {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* Szenen liegen absolut übereinander; nur .active ist sichtbar. Der
   Szenen-Motor (spätere Welle) setzt/entfernt .active und .entered. */
.scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3xl);
  /* HUD-Safe-Area (Feedback F1, global, Wert siehe --hud-safe auf .pitch-body):
     unterer Innenabstand vh-gedeckelt größer als die übrigen Seiten, damit
     zentrierter Inhalt nach oben ausweicht und nie hinter der fixed
     positionierten HUD-Leiste (unten, ~84px hoch inkl. Abstand) landet. Gilt
     für alle Szenen, die direkt über .scene zentrieren (2/4/5/6/7/9/11/12).
     Szenen mit eigener video-stage-Ebene (1/3/8/10) reasserten denselben Wert
     auf ihrem jeweiligen Zentrier-Container (.s1-beat/.s3-beat/.s8-wrap/
     .s10-wrap), weil deren position:absolute;inset:0 dieses Scene-Padding
     sonst umgeht (siehe dort). */
  padding-bottom: var(--hud-safe);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--motion-slow) var(--ease-out);
}
.scene.active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* Betreten-Animation (Grundmuster): Überschrift kommt beim Erscheinen leicht
   von unten. Der Szenen-Motor entfernt/setzt .entered bei jedem go(n) neu
   (mit Reflow dazwischen), damit die Animation auch bei wiederholtem
   Ansteuern derselben Szene neu abspielt. Minimal gehalten — eigene
   Szenen-Inhalte (Task 4 ff.) bekommen bei Bedarf eigene, feinere Auswahl. */
.scene .headline-display {
  opacity: 0;
  transform: translateY(16px);
}
.scene.entered .headline-display {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-slow) var(--ease-out), transform var(--motion-slow) var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  .scene .headline-display { transform: none; }
  .scene.entered .headline-display { transition: opacity var(--motion-fast) var(--ease-out); }
}

/* ---------- HUD (schwebende Leiste, unten zentriert) ---------- */
.hud {
  position: fixed;
  left: 50%;
  bottom: var(--space-lg);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-lg);
  z-index: 10;
  /* HUD-Auto-Hide (Task D10): Grundzustand sichtbar. Übergang fürs
     Wieder-Einblenden (Erscheinen: --ease-out); der Idle-Zweig unten setzt
     dieselbe Dauer mit eigener Kurve fürs Verschwinden. Tokens verbatim aus
     dem Brief, keine neuen Timings. */
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}

/* Idle-Zustand (Task D10): pitch.js setzt/entfernt diese Klasse über genau
   EINEN Idle-Timer (Muster wie kinoTimeout), sobald ~2,5s keine Maus-,
   Tastatur- oder Zeigerinteraktion stattfand. Rein optisch (Opacity) — kein
   display:none/visibility:hidden/aria-hidden, die Knöpfe bleiben im
   Accessibility-Tree und per Tab erreichbar (Brief Punkt 4). pointer-events:
   none verhindert Klicks auf die unsichtbare Leiste (Brief Punkt 2); die
   erste Interaktion räumt in pitch.js beides sofort wieder auf, bevor
   geklickt werden kann. */
.hud.hud-idle {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--motion-base) var(--ease-in);
}

/* A11y-Leitplanke (Brief Punkt 3, nicht verhandelbar): liegt der
   TASTATUR-Fokus in der HUD-Leiste, bleibt sie IMMER sichtbar — unabhängig
   vom Idle-Timer. Bewusst :has(:focus-visible) statt :focus-within: ein
   Maus-Klick auf einen HUD-Knopf fokussiert ihn zwar ebenfalls (:focus-within
   wäre dann true), gilt aber nicht als ":focus-visible" (Chromium/Firefox-
   Heuristik zeigt den Fokusring nur bei Tastatur-Navigation) — mit
   :focus-within würde ein Play-Klick das HUD dauerhaft offen halten und die
   Idle-Regel für Maus-Nutzer faktisch aushebeln (per Playwright-Probe
   verifiziert: #play.matches(':focus-visible') ist nach echtem Klick false,
   .hud.matches(':focus-within') aber true). :focus-visible ist im Haus
   bereits die etablierte Konvention für genau diese Unterscheidung (siehe
   .hud-btn:focus-visible/.hud-dot:focus-visible oben, site.css). CSS-seitig
   abgesichert statt nur per JS: drei Selektor-Stufen (0,3,0) schlagen
   .hud.hud-idle (0,2,0) über reine Spezifität, unabhängig von der
   Regel-Reihenfolge im File. :has() ist im Projekt-Basisstand ohnehin
   vorausgesetzt (color-mix() an mehreren Stellen verlangt bereits
   Firefox 113+/Chrome 111+, :has() liegt mit Firefox 121+ nur knapp darüber). */
.hud.hud-idle:has(:focus-visible) {
  opacity: 1;
  pointer-events: auto;
  transition: opacity var(--motion-base) var(--ease-out);
}

/* Wächter (Welle-C-Sammelliste M3): solange der Ton-Dialog offen ist, darf
   der Idle-Timer die HUD-Leiste nicht ausblenden — der Dialog gehört zur
   Leiste, ein unsichtbares HUD unter offener Frage wäre desorientierend.
   #sound-ask steht im DOM direkt vor nav.hud, daher genügt der
   Folge-Geschwister-Kombinator; (1,3,0) schlägt .hud.hud-idle (0,2,0)
   — :not([hidden]) steuert die Attribut-Stufe bei. */
#sound-ask:not([hidden]) ~ .hud.hud-idle {
  opacity: 1;
  pointer-events: auto;
  transition: opacity var(--motion-base) var(--ease-out);
}

/* Reduced Motion (Brief Punkt 3, letzter Spiegelstrich): kein Fade, nur ein
   hartes, sofortiges Ein/Aus — der Sichtbarkeitswechsel selbst (Opacity/
   pointer-events) bleibt unverändert, nur die Transition entfällt. */
@media (prefers-reduced-motion: reduce) {
  .hud,
  .hud.hud-idle,
  .hud.hud-idle:has(:focus-visible),
  #sound-ask:not([hidden]) ~ .hud.hud-idle {
    transition: none;
  }
}

.hud-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
/* hidden muss gewinnen: die display:inline-flex-Basisregel oben schlägt
   sonst das UA-Stylesheet für [hidden] — der ⋯- und der Vollbild-Knopf
   belegten dann trotz hidden-Attribut 44px Leistenbreite (Netz-Befund
   2026-07-24, HUD-Breiten 320/414px). */
.hud-btn[hidden] { display: none; }
.hud-btn:hover { background: var(--line-on-dark-default); color: var(--fg-default); }
.hud-btn:focus-visible { outline: var(--focus-ring-dark); outline-offset: 2px; }
.hud-btn[aria-pressed="true"] { color: var(--color-brand-teal); }

.hud-ico { width: 20px; height: 20px; }

/* #play-Icon-Wechsel (Kino-Modus, Task 8): zwei Lucide-SVGs im selben Knopf
   (Play/Pause), Sichtbarkeit rein per CSS über aria-pressed geschaltet —
   kein Style per JS (CSP-konform: JS setzt hier nur das aria-pressed-
   Attribut selbst, siehe pitch.js). Ruhezustand (aria-pressed="false")
   zeigt Play, laufender Kino-Modus (aria-pressed="true") zeigt Pause; die
   Teal-Einfärbung im gedrückten Zustand kommt bereits aus der generischen
   .hud-btn[aria-pressed="true"]-Regel oben. */
#play .ico-pause { display: none; }
#play[aria-pressed="true"] .ico-play { display: none; }
#play[aria-pressed="true"] .ico-pause { display: block; }

/* Vollbild-Knopf (Stefan 2026-07-24): Icon-Wechsel exakt nach dem
   #play-Muster — aria-pressed spiegelt den echten Vollbild-Zustand
   (fullscreenchange-Listener in pitch.js), CSS schaltet nur die Icons. */
#fullscreen-btn .ico-fs-exit { display: none; }
#fullscreen-btn[aria-pressed="true"] .ico-fs-enter { display: none; }
#fullscreen-btn[aria-pressed="true"] .ico-fs-exit { display: block; }

/* Platz-Tausch auf schmalen Screens (<=530px, deckungsgleich mit Stufe 1
   der HUD-Breiten-Rechnung unten): der Druck-Knopf weicht dem neuen
   Vollbild-Knopf — Drucken ist ein Desktop-Flow, auf schmalen Touch-
   Screens bleibt der PDF-Download für denselben Zweck. Damit bleibt die
   Knopfzahl der Leiste in beiden Engstufen exakt wie vor dem Vollbild-
   Knopf und die dokumentierten Breiten-Budgets (404px/316px) gelten
   unverändert. max-width ist eine reine Screen-Größe — der Druckbogen
   (A4 quer, 1123px) bleibt davon unberührt. */
@media (max-width: 530px) {
  #print-btn { display: none; }
}

.hud-dots {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0 var(--space-xs);
}

.hud-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background: var(--line-on-dark-default);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--ease-out), transform var(--motion-fast) var(--ease-out);
}
.hud-dot:hover { background: var(--fg-muted); }
.hud-dot:focus-visible { outline: var(--focus-ring-dark); outline-offset: 2px; }
/* Härtung P2: aria-current statt aria-selected (Punkte sind native
   <button>-Elemente ohne role-Attribut, kein role="tab" mehr — siehe
   pitch.js buildDots/Report). */
.hud-dot[aria-current="true"] { background: var(--color-brand-teal); transform: scale(1.3); }

/* ---------- Szenen-Vorschau über den Punkten (Stefan 2026-07-23) ----------
   Kleine Karte im HUD-Stil (raised-dark, line-on-dark, radius, Schatten)
   über dem gerade berührten Punkt. Existiert visuell NUR auf Hover-fähigen
   Geräten mit feinem Zeiger (display-Gate unten) — auf Touch bleibt sie
   display:none und pitch.js lädt dort auch keine Bilder. left setzt
   pitch.js auf die Punkt-Mitte (CSSOM-Positionswert, kein Inline-HTML —
   die „kein Style per JS"-Konvention meint Sichtbarkeits-Zustände, die
   gehören weiter in Klassen). Erscheinen: reiner Opacity-Fade plus 4px
   Rise in EINER transform-Property (ein Bewegungskanal). */
.dot-preview {
  display: none;
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  width: 240px;
  padding: var(--space-xs);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translate(-50%, 4px);
  pointer-events: none;
  transition: opacity var(--motion-fast) var(--ease-out), transform var(--motion-fast) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .dot-preview { display: block; }
}
.dot-preview.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
.dot-preview-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--radius-lg) - 4px);
  background: var(--color-surface-sunken-dark);
}
.dot-preview-label {
  margin: 6px 4px 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--fg-muted);
}
@media (prefers-reduced-motion: reduce) {
  .dot-preview { transition: none; }
}
@media print {
  .dot-preview { display: none; }
}

/* ---------- ⋯-Popover (Stefan 2026-07-24, Touch-Querformat) ----------
   Aufgeräumte Leiste: Download/Teilen/Drucken ziehen per DOM-Move (pitch.js)
   in diese Karte um — Optik wie die Szenen-Vorschau (raised-dark, Radius,
   Schatten), die Knöpfe stapeln sich als unveränderte 44px-Ziele. Der
   Idle-Wächter unten hält die Leiste sichtbar, solange das Menü offen ist
   (Muster der :has(:focus-visible)-Regel oben). */
.more-menu {
  position: absolute;
  bottom: calc(100% + 10px);
  right: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-xs);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.more-menu[hidden] { display: none; }
.hud.hud-idle:has(#more-menu:not([hidden])) {
  opacity: 1;
  pointer-events: auto;
  transition: opacity var(--motion-base) var(--ease-out);
}
@media print {
  .more-menu, #more-btn { display: none; }
}

/* Toast-Rückmeldung „Link kopiert" für den Teilen-Knopf (Stefan-Bestellung
   2026-07-17), nur wenn der Browser kein natives Teilen-Menü hat und auf den
   Zwischenablage-Fallback zurückfällt — Optik-Pendant zu .share-toast in
   /leistung/ (assets/css/onepager.css), hier auf die dunkle Bühne übertragen:
   Karte/Rand/Radius/Schatten wie die übrigen dunklen Requisiten dieser Datei
   (.s4-card-Familie: --color-surface-raised-dark, --line-on-dark-default,
   --radius-lg, --shadow-xl), Text var(--fg-default). Zentriert ÜBER der HUD,
   in derselben --hud-safe-Reserve wie .s0-corner. pointer-events:none, weil
   der Toast rein informativ ist und nie Klicks abfangen darf. Nur
   opacity-transitioniert (kein transform/Slide wie beim One-Pager) — damit
   automatisch Reduced-Motion-verträglich, kein eigener RM-Block nötig (Brief
   Punkt 8). Im Druck ausgeblendet zusammen mit HUD/#sr-status (ein
   .share-toast-Zusatz im bestehenden @media-print-Block unten) statt einer
   eigenen .screen-only-Regel — derselbe Verbund, ein Selektor mehr. */
.share-toast {
  position: fixed;
  left: 50%;
  bottom: var(--hud-safe);
  transform: translateX(-50%);
  background: var(--color-surface-raised-dark);
  color: var(--fg-default);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: var(--space-sm) var(--space-md);
  font-family: var(--font-body);
  font-size: 14px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--motion-base) var(--ease-out);
  z-index: 10;
}
.share-toast.show { opacity: 1; visibility: visible; }

/* Ton-Opt-in-Dialog: kleine Karte über der HUD-Leiste (Hausmuster
   .share-toast: bottom über --hud-safe). Liegt ÜBER dem HUD (z-index 10). */
.sound-ask {
  position: fixed; left: 50%; bottom: var(--hud-safe);
  transform: translateX(-50%);
  z-index: 40;
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  padding: var(--space-md) var(--space-lg);
  box-shadow: 0 6px 18px rgba(24, 39, 58, 0.22);
}
.sound-ask[hidden] { display: none; }
.sound-ask-q { color: var(--fg-on-dark-default); margin: 0 0 var(--space-sm); text-align: center; }
.sound-ask-row { display: flex; gap: var(--space-sm); justify-content: center; }
.sound-ask-quiet {
  background: none; border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-md); color: var(--fg-on-dark-soft);
  padding: 14px 26px; font-size: 16px; cursor: pointer;
  transition: color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
.sound-ask-quiet:hover { color: var(--fg-on-dark-default); border-color: var(--line-on-dark-strong); }
/* Ton-Knopf: Icon-Paar wie #play (ico-play/ico-pause-Muster). */
#sound-btn .ico-sound-on { display: none; }
#sound-btn[aria-pressed="true"] .ico-sound-on { display: block; }
#sound-btn[aria-pressed="true"] .ico-sound-off { display: none; }
/* Ohne Videos ist der Ton-Knopf ein toter Knopf: unter RM ausblenden
   (löst zugleich die engste HUD-Breite dort). */
@media (prefers-reduced-motion: reduce) { #sound-btn { display: none; } }

/* Härtung P1 (Befund: HUD klippt seitlich bei ~375px und darunter): 5 feste
   44px-Knöpfe + 13 Punkte sprengen bei den Basiswerten (~416px Gesamtbreite)
   bereits deutlich über 375px hinaus. Fix rührt NUR Abstände/Punktgröße an
   (Brief-Vorgabe), NIE die 44px-Knopfmaße — die bleiben ein Mindest-Tastziel,
   Steuerelemente dürfen nie aus dem sichtbaren Fenster ragen, aber auch nie
   Szenen-Text überdecken.

   Teilen-Welle (Stefan-Bestellung 2026-07-17, sechster Knopf, zwei Stufen
   NEU gerechnet — Rechnung/Messung im Report): ein sechster 44px-Knopf
   (#share-btn) macht die HUD-Gesamtbreite größer, in JEDER Stufe:
     unkondensiert: 6×44px Knöpfe (264) + Punktleiste (13×8px + 12×--space-xs-
       Gaps + 2×--space-xs-Innenabstand = 160) + 6 Kind-Gaps×--space-xs (24)
       + HUD-Innenabstand 2×--space-sm (16) + Rand 2×1px (2) = 466px (real
       gemessen 465–467px, siehe Report).
     Stufe 1 (Gaps/Punktgröße wie bisher kondensiert, --space-2xs/4px-Punkte):
       264 + Punktleiste (13×4 + 12×--space-2xs + 0 Innenabstand = 76) + 6
       Kind-Gaps×--space-2xs (12) + HUD-Innenabstand 2×--space-2xs (4) + Rand
       (2) = 358px — überläuft 320px, DAHER Stufe 2 nötig (Brief-Knackpunkt).
   Erste Kondensier-Stufe bleibt Gaps/Punktgröße wie bisher, NUR der
   Breakpoint wandert von 420px auf 480px hoch, mit Marge über die neu
   gemessenen ~466px (statt vorher ~418px) — deckt zusätzlich denselben
   414px-iPhone-Fall wie zuvor ab, jetzt mit mehr Luft als die alte
   2px-Marge, weil die Messung leicht schwankte (465–467px, s. Report).
   ZWEITE Kondensier-Stufe (neu, ≤370px): blendet die Punktleiste (#dots)
   komplett aus. Begründung: die Punkte sind ergänzende Sprung-Navigation;
   Pfeil-Knöpfe, Pfeiltasten, Wischen und die #sr-status-Ansagen bleiben
   vollständig erhalten — das ist der A11y-schonendste Weg, eine sechste
   44px-Zielfläche unterzubringen, ohne die Mindest-Tastziele anzutasten.
   Rechnerisch ohne Punktleiste: 264 (Knöpfe) + 5 Gaps×--space-2xs (10) + HUD-
   Innenabstand 2×--space-2xs (4) + Rand (2) = 280px ≤ 320px ✓ (Report zeigt
   die reale Messung). 370px liegt zwischen der überlaufenden 358px-Stufe-1-
   Breite und der geprüften 375px-Marke (Stufe 1 muss dort noch stehen), mit
   Marge auf beiden Seiten.

   Ton-Welle (Task A4, siebter Knopf #sound-btn, Prüf-Befund Z3 — die alte
   Plan-Rechnung vergaß Dots-Restbreite und den 2px-Rand, hier mit derselben
   Methode neu gerechnet):
     unkondensiert: 7×44px Knöpfe (308) + Punktleiste (160, wie oben) + 7
       Kind-Gaps×--space-xs (28) + HUD-Innenabstand 2×--space-sm (16) + Rand
       2×1px (2) = 514px.
     Stufe 1 (Gaps/Punktgröße wie bisher kondensiert): 308 + Punktleiste (76,
       wie oben) + 7 Kind-Gaps×--space-2xs (14) + HUD-Innenabstand
       2×--space-2xs (4) + Rand (2) = 404px — Breakpoint daher von 480px auf
       530px angehoben, mit Marge über die 514px unkondensierte Breite.
     Stufe 2 (Dots weiterhin ausgeblendet, NEU: gap auf 1px verengt statt
       --space-2xs, horizontales HUD-Padding auf 0 statt --space-2xs):
       308 (Knöpfe) + 6 Kind-Gaps×1px (6) + Rand (2) = 316px — Breakpoint
       daher von 370px auf 410px angehoben, mit Marge über die 404px-Stufe-1-
       Breite. `.hud-btn { flex: none; }` (oben) ist der Wächter dazu: ohne
       ihn würde Flex die 44px-Knöpfe bei diesen engen Gaps stauchen und der
       Overflow-Check wäre trügerisch grün. */
@media (max-width: 530px) {
  .hud {
    gap: var(--space-2xs);
    padding: var(--space-2xs);
  }
  .hud-dots {
    gap: var(--space-2xs);
    padding: 0;
  }
  .hud-dot {
    width: 4px;
    height: 4px;
  }
}
@media (max-width: 410px) {
  #dots {
    display: none;
  }
  .hud {
    gap: 1px;
    padding: var(--space-2xs) 0;
  }
}

/* Screenreader-only Statuszeile für Szenenwechsel-Ansagen (spätere Welle füllt sie). */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Weiter-Pfeil (Stefan 2026-07-23, global) ----------
   Dezenter Hinweis am rechten Rand, dass die Szene fertig erzählt ist und
   es weitergeht. pitch.js setzt .show (scheduleNextHint) — hier nur Optik.
   Grundzustand unsichtbar UND klick-durchlässig (Muster .hud.hud-idle).
   Die Drift-Animation liegt allein auf dem Icon und bewegt NUR transform
   (ein Bewegungskanal pro Element, Motion-Doktrin); der Button selbst
   blendet nur. 44px-Ziel wie .hud-btn. z-index 6: über Szenen/Korn (4)
   und Logo (5), unter HUD (10) — räumlich kollidiert ohnehin nichts. */
.next-hint {
  position: fixed;
  top: 50%;
  right: clamp(10px, 2.5vw, 36px);
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--fg-soft);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--motion-slow) var(--ease-out), background-color var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
  z-index: 6;
}
.next-hint.show {
  opacity: 1;
  pointer-events: auto;
}
.next-hint:hover {
  background: var(--line-on-dark-default);
  color: var(--fg-default);
}
.next-hint .hud-ico { width: 22px; height: 22px; }
.next-hint.show .hud-ico {
  animation: next-hint-drift 2.8s var(--ease-in-out) infinite;
}
@keyframes next-hint-drift {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .next-hint { transition: none; }
  .next-hint.show .hud-ico { animation: none; }
}
@media print {
  .next-hint { display: none; }
}

/* ---------- Hochkant-Vorhang (Stefan 2026-07-23, global) ----------
   Breitbild-Doktrin fürs Deck: im Hochkantmodus auf Touch-Geräten legt
   sich dieser opake Vorhang über ALLES (z-index 20 > HUD 10) und fängt
   die Zeiger-Events — echtes Orientation-Lock existiert im Browser nicht
   (iOS nie, Android nur Fullscreen). Rein deklaratives CSS: die Media-
   Query ist der einzige Schalter, Drehen blendet sofort um, kein JS.
   pointer: coarse hält Desktop-Hochkant-Fenster draußen; 920px deckt
   Phones und Tablets im Portrait. screen-Prefix hält Druck/PDF (rendert
   quer, A4-Landscape-Viewport) doppelt sicher frei. Das Handy-Icon dreht
   ruhig um 90° mit langer Standzeit (ein Kanal: transform). */
.rotate-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--color-surface-sunken-dark);
  align-items: center;
  justify-content: center;
  text-align: center;
}
@media screen and (orientation: portrait) and (pointer: coarse) and (max-width: 920px) {
  .rotate-overlay { display: flex; }
}
.rotate-overlay-inner {
  display: grid;
  justify-items: center;
  gap: var(--space-md);
  padding: var(--space-xl);
}
.rotate-phone {
  width: 48px;
  height: 48px;
  color: var(--color-brand-teal);
  animation: rotate-phone-turn 3.6s var(--ease-in-out) infinite;
}
@keyframes rotate-phone-turn {
  0%, 18% { transform: rotate(0deg); }
  42%, 100% { transform: rotate(90deg); }
}
.rotate-head {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--fg-default);
}
.rotate-sub {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--fg-muted);
}
/* Zurück-Weg (Stefan 2026-07-24): dezenter Marken-Pill, klar abgesetzt von
   der Botschaft (margin-top zusätzlich zum grid-gap). Ruhiger Ghost-Stil
   auf Dunkel (transparenter Grund, line-on-dark-strong-Rahmen, Cream-86%-
   Text), Hover/Aktiv hebt Rahmen, Text UND Icon auf Teal — im data-theme=
   "dark" ist var(--color-brand-teal) das aufgehellte, WCAG-AA-lesbare
   #2FB6A8 (Token-Layer, kein roher Hex). min-height 44px = Fingerziel
   (WCAG 2.5.8). Der Chevron gleitet beim Aktivieren leicht nach links
   (ein Bewegungskanal: transform), Marken-Motion wie beim Weiter-Pfeil. */
.rotate-back {
  margin-top: var(--space-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 44px;
  padding: 10px 20px;
  box-sizing: border-box;
  border: 1px solid var(--line-on-dark-strong);
  border-radius: var(--radius-full);
  color: var(--fg-strong-muted);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  transition: color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
.rotate-back:hover,
.rotate-back:active {
  color: var(--color-brand-teal);
  border-color: var(--color-brand-teal);
}
.rotate-back-ico {
  width: 18px;
  height: 18px;
  transition: transform var(--motion-fast) var(--ease-out);
}
.rotate-back:hover .rotate-back-ico,
.rotate-back:active .rotate-back-ico {
  transform: translateX(-3px);
}
@media (prefers-reduced-motion: reduce) {
  .rotate-phone { animation: none; transform: rotate(90deg); }
  .rotate-back, .rotate-back-ico { transition: none; }
}

/* ---------- Logo (Feedback W5, global; Link seit 2026-07-23) ----------
   Eine feste Ebene über der Bühne statt szenen-eigener Duplikate: liegt im
   <body> neben #stage, damit sie auf jeder Szene sichtbar ist und beim
   Druck auf jeder Seite wiederholt wird. Seit Stefans Bestellung 2026-07-23
   ein Link zur Startseite: der ANKER trägt die feste Position (fixed-
   Wiederholung im Druck bleibt erhalten, nur der Träger wechselt), das Bild
   füllt ihn. Klickfläche per padding/negativem margin auf >= 24px Höhe
   gebracht (WCAG 2.5.8), ohne die optische Logo-Position zu verschieben.
   Dezenz bleibt: opacity 0.85, Hover hebt nur auf 1 (--motion-fast). */
.pitch-logo-link {
  position: fixed;
  top: calc(clamp(20px, 3vw, 40px) - 6px);
  left: calc(clamp(20px, 3vw, 40px) - 6px);
  width: clamp(110px, 9vw, 150px);
  padding: 6px;
  z-index: 5;
  display: block;
  line-height: 0;
  border-radius: var(--radius-sm);
}
.pitch-logo-link:focus-visible {
  outline: var(--focus-ring-dark);
  outline-offset: 2px;
}
.pitch-logo {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0.85;
  transition: opacity var(--motion-fast) var(--ease-out);
}
.pitch-logo-link:hover .pitch-logo,
.pitch-logo-link:focus-visible .pitch-logo {
  opacity: 1;
}

/* ---------- Filmkorn (Feedback W-A, global) ----------
   Eine feste Overlay-Ebene nach demselben Muster wie .pitch-logo direkt
   darüber: liegt fix im body, deckt die ganze Bühne ab (z-index 4, also
   ÜBER den Szenen, die ohne eigenen z-index im Auto-Stapel liegen, aber
   UNTER Logo/HUD). Kachelbare Graustufen-Rauschtextur (echte Datei, kein
   data:-URI — die CSP erlaubt nur self-Bilder), extrem dezente Deckkraft
   (Ziel: der Effekt darf erst auffallen, wenn man ihn wegnimmt). Statisch,
   keine Animation, aria-hidden, kein Klick-/Tastaturziel. Im Druck sinnlos
   (und würde nur Tinte verbrauchen) — daher ausgeblendet. */
.pitch-grain {
  position: fixed;
  inset: 0;
  z-index: 4;
  background: url('/assets/img/grain.png') repeat;
  /* Nacharbeit (Stefan-Feedback WA): 0.05 wirkte zu stark — Textur weicher
     (Gauß-geblurrtes, gröberes Korn) und Deckkraft deutlich leiser.
     Nacharbeit 2 (Stefan 2026-07-23): Korn immer noch zu grob sichtbar —
     die 128px-Kachel wird auf 64px dargestellt, das Korn ist halb so groß. */
  background-size: 64px 64px;
  opacity: 0.02;
  pointer-events: none;
}
@media print {
  .pitch-grain { display: none; }
}

/* ============================================================================
   Animations-Vokabular (.fx-*) — feste Klassen-Bibliothek, aus der ALLE
   Szenen ihre Bewegung beziehen; keine Szene erfindet eigene Keyframes.
   Grundregel für jede Klasse hier: Animation läuft NUR unter .scene.entered,
   davor sitzt das Element im Ruhezustand (Startwerte oben je Klasse).
   Animiert wird ausschließlich transform/opacity (Animations-Grundregel,
   feste Layout-Boxen, kein Pixel-Wackeln). Timing: Mikro-Bewegung über die
   Basis-Tokens (--motion-fast/base/slow), Szenen-Choreografie über die
   Choreografie-Tokens (--motion-reveal 600 ms, --motion-draw 800 ms) —
   beide unter der 900-ms-Obergrenze je Element. Einzige bewusste Ausnahme:
   der JS-Zähler (.fx-count) läuft über --motion-count (1200 ms), weil das
   Token exakt dafür benannt ist und die Zähl-Prüfung 1,5 s Toleranz vorsieht.

   Vier dokumentierte Paint-only-Ausnahmen von der Transform/Opacity-Regel
   (rein malend, kein Layout-Einfluss, keine Layout-Box wackelt): filter:
   blur() (Schärfe-Auf-Blenden, Szene 1), color (Wort-Einfärbung, Szene 1/5),
   clip-path bei .fx-reveal (Masken-Reveal, Szenen 3/4/5/11, seit Feedback
   W-A von Stefan am 2026-07-15 freigegeben) und filter: saturate() (Szene 8,
   von Stefan am 2026-07-15 freigegeben).

   Unter prefers-reduced-motion: reduce verhalten sich ALLE .fx-* wie
   .fx-fade — keine Translation, kein Zoom, keine Schreibmaschine, Text
   steht sofort (siehe gebündelte Media-Query am Ende des Blocks). .fx-reveal
   ist die eine Ausnahme von diesem Fallback-Muster: statt auf eine
   Opacity-Blende zurückzufallen, steht der Text sofort komplett freigelegt
   (Endzustands-Insets, siehe Klasse) — eine Blende wäre dieselbe Bewegung,
   die reduced motion gerade vermeiden soll.
   ============================================================================ */

/* ---------- .fx-rise — weiches Einsteigen von unten ---------- */
.fx-rise {
  opacity: 0;
  transform: translateY(var(--reveal-distance));
}
.scene.entered .fx-rise {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out),
              transform var(--motion-reveal) var(--ease-out);
}

/* Staffelung 0,15 s je Stufe (.d1 = sofort … .d8 = +1,05 s). Generisch, weil
   transition-delay überall dort greift, wo .fx-rise/.fx-depth/.fx-fade eine
   transition auslösen — nicht an .fx-rise gebunden. */
.d1 { transition-delay: 0s; }
.d2 { transition-delay: .15s; }
.d3 { transition-delay: .3s; }
.d4 { transition-delay: .45s; }
.d5 { transition-delay: .6s; }
.d6 { transition-delay: .75s; }
.d7 { transition-delay: .9s; }
.d8 { transition-delay: 1.05s; }

/* Spezifitäts-Fix: die .scene.entered-Regeln von .fx-rise, .fx-depth und
   .fx-fade (je 0,3,0) setzen die transition-Kurzform und damit
   transition-delay implizit auf 0 zurück — das schlägt die generischen
   .dN-Klassen oben (0,1,0). Darum hier ein Re-Assert je Stufe (0,4,0), der
   nur die transition-delay-Longhand neu setzt; Dauer/Property/Kurve bleiben
   unberührt aus der jeweiligen Vokabular-Regel. .fx-count braucht keinen
   Re-Assert (läuft komplett über JS, keine transition-Kurzform).
   Bleibt unter den ID-spezifischen Szenen-Reasserts von #s3–#s6 (1,4,0),
   die weiterhin gewinnen — siehe dort. */
.scene.entered .fx-rise.d1, .scene.entered .fx-depth.d1, .scene.entered .fx-fade.d1 { transition-delay: 0s; }
.scene.entered .fx-rise.d2, .scene.entered .fx-depth.d2, .scene.entered .fx-fade.d2 { transition-delay: .15s; }
.scene.entered .fx-rise.d3, .scene.entered .fx-depth.d3, .scene.entered .fx-fade.d3 { transition-delay: .3s; }
.scene.entered .fx-rise.d4, .scene.entered .fx-depth.d4, .scene.entered .fx-fade.d4 { transition-delay: .45s; }
.scene.entered .fx-rise.d5, .scene.entered .fx-depth.d5, .scene.entered .fx-fade.d5 { transition-delay: .6s; }
.scene.entered .fx-rise.d6, .scene.entered .fx-depth.d6, .scene.entered .fx-fade.d6 { transition-delay: .75s; }
.scene.entered .fx-rise.d7, .scene.entered .fx-depth.d7, .scene.entered .fx-fade.d7 { transition-delay: .9s; }
.scene.entered .fx-rise.d8, .scene.entered .fx-depth.d8, .scene.entered .fx-fade.d8 { transition-delay: 1.05s; }

/* ---------- .fx-depth — räumlicher Auftritt aus der Tiefe (Wow-Baustein) ----------
   Die Szene bekommt die perspective; das Element selbst skaliert von 0.6 auf
   1 und rückt aus translateZ(-360px) nach vorn. */
.scene { perspective: 1200px; }
.fx-depth {
  opacity: 0;
  transform: translateZ(-360px) scale(.6);
}
.scene.entered .fx-depth {
  opacity: 1;
  transform: translateZ(0) scale(1);
  transition: opacity var(--motion-draw) var(--ease-out),
              transform var(--motion-draw) var(--ease-out);
}

/* ---------- .fx-reveal — Masken-Reveal, Text wird von links nach rechts
   freigelegt statt eingeblendet (Baustein 7, Feedback W-A) ----------
   clip-path ist die dritte dokumentierte Paint-only-Ausnahme (siehe
   Kopf-Kommentar des Abschnitts) neben blur()/color: rein malend, kein
   Layout-Einfluss. Start komplett verdeckt (rechter Inset 100 %), Ende ganz
   offen — Dauer über --motion-draw (800 ms, liegt im geforderten
   700–900-ms-Band). Oben/unten/links/Ende-rechts sind bewusst NEGATIV
   (Stefan-Befund WA-Fix): die Headline-Zeilenhöhen (line-height ~1.04–1.2)
   sind kleiner als die Font-Bounding-Box, Unterlängen (g/p/y) und
   Umlaut-Punkte ragen deshalb über die Element-Box hinaus — ein Inset von 0
   würde sie dauerhaft abschneiden (gemessen: ~0.19em Überhang unten bei
   Szene 3). Die negativen Werte lassen Luft, ohne den Wipe zu verändern:
   animiert wird weiterhin nur die rechte Kante (100 % → -0.4em), top/
   bottom/left bleiben konstant. Läuft hier generisch über .scene.entered;
   die vier Szenen, die die Klasse tatsächlich nutzen (3/4/5/11), binden sie
   stattdessen an ihr eigenes Phasen-Gate (Muster wie bei .fx-depth dort),
   weil der generische Trigger sonst beim Szeneneintritt zu früh feuern
   würde. */
.fx-reveal {
  clip-path: inset(-0.2em 100% -0.3em -0.1em);
}
.scene.entered .fx-reveal {
  clip-path: inset(-0.2em -0.4em -0.3em -0.1em);
  transition: clip-path var(--motion-draw) var(--ease-out);
}

/* fx-type-caret — blinkender Schreib-Cursor, wiederverwendet von den
   echten (JS-getriebenen) Tipp-Effekten in Szene 1/3/12 (runQueries/
   runFileGag in pitch.js). Die frühere reine-CSS-Schreibmaschine .fx-type/
   .fx-type-ghost/.fx-type-reveal wurde entfernt (Whole-Session-Review
   2026-07-16: ungenutzte Vokabular-Familie, kein Konsument in HTML/JS) —
   dieses Keyframe blieb, weil es an drei realen Stellen referenziert wird. */
@keyframes fx-type-caret {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ---------- .fx-count[data-to] — Zähler, läuft komplett über pitch.js ----------
   Kein Keyframe nötig, nur tabular-nums: wechselnde Ziffernbreiten (z. B.
   "9" → "10") sollen die Umgebung nicht verschieben. */
.fx-count { font-variant-numeric: tabular-nums; }

/* ---------- .fx-fade — schlichte Blende, zugleich Reduced-Motion-Ersatz ---------- */
.fx-fade { opacity: 0; }
.scene.entered .fx-fade {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}

/* ---------- Reduced Motion: alle .fx-* verhalten sich wie .fx-fade ----------
   !important ist hier bewusst gesetzt (üblicher, akzeptierter Reset-Pattern
   für Barrierefreiheits-Overrides), weil die Staffel-Selektoren sonst per
   Spezifität gegen die Aufhebung gewinnen würden. */
@media (prefers-reduced-motion: reduce) {
  .fx-rise, .fx-depth,
  .scene.entered .fx-rise, .scene.entered .fx-depth {
    transform: none !important;
  }
  .scene.entered .fx-rise,
  .scene.entered .fx-depth,
  .scene.entered .fx-fade {
    transition: opacity var(--motion-fast) var(--ease-out) !important;
    transition-delay: 0s !important;
  }
  .d1, .d2, .d3, .d4, .d5, .d6, .d7, .d8 {
    transition-delay: 0s !important;
  }
  /* .fx-reveal: kein Wipe, Text steht sofort komplett freigelegt (Baustein 7,
     Feedback W-A) — !important, weil die vier ID-scoped Phasen-Gate-Regeln
     (s3/s4/s5/s11) sonst durch Spezifität gewinnen würden. Negative Insets
     wie im Endzustand der Klasse (Unterlängen-Schutz, siehe dort). */
  .fx-reveal, .scene.entered .fx-reveal {
    clip-path: inset(-0.2em -0.4em -0.3em -0.1em) !important;
    transition: none !important;
  }
}

/* ============================================================================
   WELLE 1 — Szenen-Layouts (Szene 1 Opener, 2 Claim, 12 CTA).
   Nur Layout + Timing (transition-delay). Bewegung stammt komplett aus dem
   .fx-*-Vokabular oben; keine Szene erfindet eigene Keyframes. Animiert wird
   ausschließlich transform/opacity (feste Layout-Boxen, kein Pixel-Wackeln).
   Farben/Fonts nur über var(--…)-Tokens.
   ============================================================================ */

/* ---------- Szene 0: Titel im Slide-Kit-Cover-Aufbau (Feedback W9) ----------
   Struktur nach dem Cover-Archetyp des Slide-Kits (linksbündig statt
   zentriert): #s0 überschreibt die generische .scene-Zentrierung auf
   justify-content:flex-start (vertikal bleibt zentriert), damit .s0-wrap
   am linken Bühnenrand sitzt statt als Block in der Mitte zu schweben.

   Hintergrund (.s0-bg/.s0-wash/.s0-dots): Werte VERBATIM aus dem Slide-Kit
   übernommen (Werkbank/slide-kit/slide-kit.css, Zeilen 52 .bg-dark, 55
   .wash-teal, 57 .dots) — tiefer Deep-Sea-Grund + Teal-Wash + feines
   Punktraster. Liegt als eigene Ebene UNTER den Geister-Fenstern (die für
   s0 in der Deckkraft zurückgenommen sind, damit der Verlauf trägt, statt
   den Verlauf selbst zu verwässern) und dem Inhalt (Stapelreihenfolge über
   z-index: 0 Hintergrund, 1 Geister, 2 Inhalt/Fuß).

   Eyebrow (.fx-fade) und die zwei Headline-Zeilen (je eigene .fx-depth-Stufe
   .d1/.d3, generischer Reassert unten wie #s2) landen ruhig; Zeile 2 setzt
   danach ihren Gold-Punkt (Opacity-Delay nach der Landung, Muster wie #s2
   .s2-claim .gold-dot) — Zeile 1 bleibt seit Feedback W10 punktlos (Stefans
   Regel: max. EIN Gold-Punkt im Titel). Die Signatur-Linie zieht sich erst
   danach auf — bespoke transform:scaleX()-Übergang, kein .fx-*-Baustein
   bildet ein "Aufziehen von links" ab, kein neues @keyframes.

   Layout-Fix Feedback W10 (Review-Befund: Button/Hinweis/Absenderblock
   überlappten sich bei ~1900×950): der Absenderblock (.s0-sender) ist kein
   eigener .s0-foot-Block mit position:absolute mehr, sondern ganz normales
   Fluss-Kind von .s0-wrap, direkt nach dem Start-Bereich — der Kit-Stapel
   (Eyebrow → Headline → Signatur-Linie → Start-Button → Hinweiszeile →
   Absenderblock) wächst/schrumpft damit als EIN Block, den .s0-wrap als
   Ganzes vertikal zentriert; eine Überlappung zwischen Start-Bereich und
   Absenderblock ist so strukturell ausgeschlossen (kein zweiter, unabhängig
   positionierter Block mehr, der hineinwachsen könnte). Der Flex-Gap plus
   ein zusätzlicher margin-top auf .s0-sender liefert die geforderte "Luft"
   vor dem Absenderblock. Headline-Schriftgröße und die Stapel-Gaps sind
   zusätzlich vh-gedeckelt (Muster #s4/#s11: `clamp(min, min(Xvw, Yvh), max)`
   bzw. `clamp(min, Yvh, max)`), damit der Stapel bei flachen Fenstern
   schrumpft statt zu wachsen. Das Ecken-Label (.s0-corner, "PITCH · 2026")
   bleibt wie zuvor absolut unten rechts verankert (eigener Block, kollidiert
   nicht mit dem linken Stapel) und teilt sich weiter den HUD-Safe-Area-Wert
   mit dem Scene-Padding.

   Geister-Fenster: additive Wiederverwendung der Szene-1-Requisiten
   (.s1-ghost*, kein s1-HTML-Change) als eigene s0-Instanzen. Ruhig stehend
   bewusst minimal gehalten — Szene 0 hat keine Punchline-Phase, daher kein
   Wegflug-Trigger; Reduced-Motion-Verhalten kommt kostenlos aus der
   bestehenden generischen .s1-ghost-Regel weiter unten. */
#s0 { justify-content: flex-start; }

/* Feedback W12: linker Rand des Titel-Stapels wirkte gedrungen (zu nah am
   Bühnenrand). Eigener, größerer Innenabstand nur links (überschreibt das
   generische .scene-Padding, var(--space-3xl) = 64px, gezielt auf dieser
   Seite) — Ecken-Label (rechts/unten verankert) und HUD bleiben unberührt,
   da beide unabhängig vom linken Padding positioniert sind. Bei 1900px
   Breite ergibt der vw-Anteil ~152px (deutlich über 64px), bei 1280px
   proportional kleiner (~102px), aber weiterhin großzügiger als vorher. */
#s0 { padding-left: clamp(48px, 8vw, 180px); }

.s0-bg { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.s0-wash { position: absolute; inset: 0; background: radial-gradient(900px 620px at 78% 20%, rgba(13,148,136,0.42), rgba(13,148,136,0.10) 52%, transparent 74%); }
.s0-dots { position: absolute; inset: 0; background-image: radial-gradient(rgba(248,246,242,0.05) 1.5px, transparent 1.5px); background-size: 34px 34px; }
#s0 { background: var(--color-brand-deep-sea); }

.s0-ghosts { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; }
/* Deckkraft für s0 zurückgenommen (Stefan-Feedback: Verlauf soll tragen). */
#s0 .s1-ghost--a { opacity: .18; }
#s0 .s1-ghost--b { opacity: .12; }
#s0 .s1-ghost--c { opacity: .15; }

.s0-wrap {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* vh-gedeckelt (Muster #s4/#s12): bei flachen Fenstern rückt der ganze
     Stapel enger zusammen, statt in den HUD-Safe-Bereich zu wachsen. */
  gap: clamp(10px, 2.2vh, var(--space-lg));
  max-width: min(960px, 90vw);
}
.s0-eyebrow { margin: 0; color: var(--color-brand-gold); }
.s0-headline { margin: 0; }
.s0-line { margin: 0; text-wrap: balance; }
/* Headline-Größe zusätzlich vh-gedeckelt (Muster .s4-punch-line): zwei
   Zeilen dieser Größenordnung sprengen bei flachen Fenstern sonst den für
   den Stapel verfügbaren Raum. */
#s0 .s0-line.headline-display { font-size: clamp(32px, min(6vw, 7.2vh), 84px); }
#s0 .headline-display.fx-depth { transform: translateZ(-360px) scale(.6); }
#s0.scene.entered .headline-display.fx-depth {
  transform: translateZ(0) scale(1);
  transition-property: opacity, transform;
  transition-duration: var(--motion-draw);
  transition-timing-function: var(--ease-out);
}

/* Gold-Punkt: nur noch Zeile 2 trägt einen (Stefan-Regel, max. EIN
   Gold-Punkt im Titel, Feedback W10) — Opacity-Delay nach der Landung,
   Muster wie #s2 .s2-claim .gold-dot. Kein Layout-Shift (Punkt nimmt in
   .headline-display bereits vorab seinen Platz ein). */
.s0-line--2 .gold-dot { opacity: 0; }
#s0.scene.entered .s0-line--2 .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1.3s;
}
@media (prefers-reduced-motion: reduce) {
  .s0-line--2 .gold-dot { opacity: 1 !important; transition: none !important; }
}

.s0-sig { transform: scaleX(0); transform-origin: left; }
#s0.scene.entered .s0-sig {
  transform: scaleX(1);
  transition: transform var(--motion-draw) var(--ease-out) 1.6s;
}

.s0-start { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-sm); }
.s0-hint { margin: 0; }
#s0.scene.entered .s0-start.fx-rise {
  transition: opacity var(--motion-reveal) var(--ease-out) 2.4s,
              transform var(--motion-reveal) var(--ease-out) 2.4s;
}

/* Härtung P3-Nachtrag (Review-Fund, Task 11a): #start-btn sitzt in
   .s0-start.fx-rise (Basis opacity:0) und wird erst nach dem 2,4s-Delay
   oben sichtbar — in diesem Fenster aber bereits tab-fokussierbar:
   derselbe Stolperstein wie beim Szene-12-CTA, nur .entered- statt
   phasen-gegated. Gleicher Fix-Mechanismus (:has(:focus-visible)-Reassert,
   Muster #s12 .s12-cta-block): erhält der Start-Knopf Tastatur-Fokus, wird
   sein Block sofort sichtbar. Zweiter, .entered-qualifizierter Selektor ist
   nötig, weil die Delay-Regel direkt oben mit (1,4,0) sonst die
   transition-Kurzform (inkl. 2,4s-Delay) gegen einen einfachen
   (1,3,1)-Reassert behaupten würde — (1,5,1) gewinnt in jedem Zustand.
   Screen-only: im Druck ist .s0-start ohnehin .screen-only/display:none,
   unter RM erzwingt der generische RM-Block Delay 0s. */
#s0 .s0-start.fx-rise:has(button:focus-visible),
#s0.scene.entered .s0-start.fx-rise:has(button:focus-visible) {
  opacity: 1;
  transform: translateY(0);
  transition: none;
}

/* Absenderblock: seit Feedback W10 Fluss-Kind von .s0-wrap (kein eigener
   position:absolute-Block mehr, siehe Kommentar oben) — margin-top liefert
   die geforderte zusätzliche "Luft" vor dem Absenderblock, über den
   normalen Stapel-Gap hinaus, ebenfalls vh-gedeckelt. Kommt mit dem
   Start-Bereich zusammen (gleicher Reassert-Delay). */
.s0-sender {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: clamp(6px, 1.6vh, var(--space-md));
}
.s0-sender-name { margin: 0; font-family: var(--font-headline); font-weight: 600; font-size: clamp(15px, 1.6vw, 19px); color: var(--fg-default); }
.s0-sender-url { margin: 0; font-family: var(--font-body); font-size: clamp(12px, 1.1vw, 14px); color: var(--fg-soft); }
#s0.scene.entered .s0-sender.fx-rise {
  transition: opacity var(--motion-reveal) var(--ease-out) 2.4s,
              transform var(--motion-reveal) var(--ease-out) 2.4s;
}

/* Ecken-Label: bleibt eigenständig absolut unten rechts verankert (Muster
   Kit-Cover-Footer) — kollidiert nicht mit dem linken Stapel, teilt sich
   weiter den HUD-Safe-Area-Wert mit dem Scene-Padding. */
/* KI-Hinweis der Videoszenen: Optik-Muster verbatim von .s0-corner (Mono-Ecke,
   --fg-soft, HUD-Safe-Zone), sichtbar nur über die has-video-Regel im
   @media-screen-Block oben. pointer-events:none wie .share-toast — rein
   informativ, fängt nie Klicks. aria-hidden im HTML: die zugängliche
   KI-Offenlegung trägt die Transparenz-Zeile in Szene 12 (Screenreader
   bekommen die Videos selbst ebenfalls nicht). */
.ki-note {
  display: none;
  position: absolute;
  right: var(--space-3xl);
  /* Auf Höhe der HUD-Leiste (Stefan-Entscheid): HUD sitzt bei bottom
     --space-lg, der 15px-Zuschlag zentriert das kleine Label optisch gegen
     die 44px-Knöpfe. Auf schmalen Viewports rückt das HUD nah an den Rand —
     dort weicht die Ecke nach oben in die HUD-Safe-Zone aus (s.u.). */
  bottom: calc(var(--space-lg) + 15px);
  z-index: 3;
  margin: 0;
  /* Label-Optik nach Designsystem (.label: Inter 500, 0.06em) — Mono ist
     laut Werkbank der Code-Auszeichnung vorbehalten (Stefan-Befund 2026-07-21). */
  font-family: var(--font-body);
  font-weight: 500;
  /* Untergrenze = Token font-size.micro (12px); ein kleinerer Wert stünde
     außerhalb der Designsystem-Skala (Prüf-Welle 2026-07-21). */
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--fg-soft);
  /* Träger gegen helle Videoframes: In Szene 1 läuft der Spot OHNE Abdunklung,
     im Ordnerregal-Shot (17,8–18,9 s) stehen helle Ordnerrücken genau in dieser
     Ecke — gemessen 1,90:1, also unter AA. Eine hellere Schrift löst das nicht
     (selbst volles Cream erreicht dort nur 2,43:1), nur ein Träger. Token ist
     dasselbe Deep-Sea-Sunken, mit dem Szene 8 ihr Overlay legt; mit 70 % steigt
     der schlechteste Frame auf 5,10:1. Chip-Geometrie nach component.tag. */
  background: color-mix(in oklab, var(--color-surface-sunken-dark) 70%, transparent);
  padding: 2px var(--space-sm);
  border-radius: var(--radius-full);
  pointer-events: none;
}
@media screen and (max-width: 900px) {
  /* Kollisionsschutz: unter ~900px kann die zentrierte HUD-Leiste bis in die
     rechte Ecke reichen — Hinweis dann oberhalb der HUD-Safe-Zone. */
  .ki-note { bottom: var(--hud-safe); }
}

.s0-corner {
  position: absolute;
  right: var(--space-3xl);
  bottom: var(--hud-safe);
  z-index: 2;
  margin: 0;
  /* Label-Optik nach Designsystem (.label: Inter 500, 0.06em) statt Mono —
     Mono ist der Code-Auszeichnung vorbehalten (Stefan-Befund 2026-07-21;
     die Datei-Requisiten in Szene 1/6/12 bleiben bewusst Mono = Code-Artefakt). */
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(11px, 1vw, 13px);
  letter-spacing: 0.06em;
  /* Marken-Ecken-Label „PITCH · 2026" (aria-hidden, Muster Kit-Cover-Footer).
     Auf Stefans Entscheid AA-konform auf --fg-soft gehoben (~7,7:1): zeigt echte
     Wörter, soll trotz Deko-Rahmung gut lesbar sein. Die reinen „·"-Trenner
     (.s8-mid/.s9-wall-sep) bleiben dagegen faint (WCAG-1.4.3-Deko-Ausnahme). */
  color: var(--fg-soft);
}
#s0.scene.entered .s0-corner.fx-rise {
  transition: opacity var(--motion-reveal) var(--ease-out) 2.4s,
              transform var(--motion-reveal) var(--ease-out) 2.4s;
}

@media (prefers-reduced-motion: reduce) {
  /* Sig-Line ist bespoke (kein .fx-*), darum eigener Sofort-Zustand — sonst
     bliebe die Linie bis zum abgelaufenen Übergang unsichtbar dünn. */
  .s0-sig { transform: none !important; transition: none !important; }
}

/* Druck-Vorgriff (volle Druckfassung folgt in Welle 3): Start-Button und
   Hinweiszeile sind reine Bildschirm-Elemente. */
@media print {
  .screen-only { display: none !important; }
}

/* ---------- Szene 1: Der KI-Praktikant (zugleich Video-Platz) ----------
   Kino-Choreografie: sechs Beats füllen nacheinander die Bühne, immer nur einer
   sichtbar (Filmschnitt). Der Takt kommt aus dem Szene-1-Dirigenten in pitch.js,
   der auf der Section die Phasen-Klassen .phase-b1…​.phase-b6 setzt (genau eine
   zur Zeit). ALLE Bewegung liegt hier in CSS-Übergängen, die an diesen Klassen
   hängen; Unter-Timing eines Beats über transition-delay (relativ zum Beat-Start,
   weil die Phasen-Klasse genau dann gesetzt wird). Kein szeneneigenes @keyframes
   (der Cursor nutzt das bestehende fx-type-caret). Animiert wird transform/opacity
   plus — als bewusste, für diesen Umbau abgenommene Ausnahme — filter: blur()
   für die Schärfe-Auf-Blenden (rein malend, kein Layout-Einfluss, Werte moderat).
   Der langsame Dauer-Zoom je Beat ist ebenfalls bewusst länger als die 900-ms-
   Mikro-Obergrenze: reiner transform-Übergang (kinematischer Push-In), keine
   Layout-Box wackelt. Farben nur über var(--…)-Tokens; Teal auf Dunkel ist
   automatisch das aufgehellte --color-brand-teal (data-theme="dark"). */
/* Bühne full-bleed: der Spot füllt die komplette Szenenfläche (auch fürs
   spätere <video> richtig). Innenabstände liegen an den Text-Ebenen, nicht hier. */
.video-stage {
  position: absolute;
  inset: 0;
}

/* ===== Video-Welle: Spot-Ebenen (nur Screen — der Druck bleibt unberührt,
   der PDF-Export läuft OHNE Reduced Motion und hätte has-video gesetzt) ===== */
@media screen {
  .scene-video { display: none; }
  .scene.has-video .scene-video {
    display: block;
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    /* Kein z-index (bewusst): Malreihenfolge Backdrop → Video → Overlay/Text. */
  }
  /* Szene 1: Beat-Ebene ruht per Opacity (bleibt im A11y-Baum — die Beats
     b1–b5 sind echter Inhalt, kein Deko, und behalten ihre Erzähl-
     reihenfolge); Deko-Ghosts komplett aus. Über dem Video laufen statt-
     dessen drei aria-hidden-Duplikate: Insert A (= b1, Prämisse) durch die
     Phasen b1 UND b2, Insert B (= b3, Suchfeld-Paar) in Phase b3, Insert C
     (= b4 ohne Explorer) im Zeitfenster s1-kalk. Alle drei sind auf
     .has-video gescopet — ohne das Scoping würden sie in Reduced Motion,
     ohne JS und bei Ladefehler durchsickern und den Fallback doppeln
     (Prüf-Wellen-Auflage C1-1). Die Punchline .s1-b6 liegt unverändert
     als sichtbarer Endframe daneben. */
  .s1.has-video .s1-beatstage { opacity: 0; pointer-events: none; }
  .s1.has-video .s1-ghosts { display: none; }
  .s1.has-video.phase-b1 .s1-insert-a,
  .s1.has-video.phase-b2 .s1-insert-a { opacity: 1; }
  .s1.has-video.phase-b3 .s1-insert-b { opacity: 1; }
  .s1.has-video.s1-kalk .s1-insert-kalk { opacity: 1; }
  .s1 .video-stage > .s1-insert-a,
  .s1 .video-stage > .s1-insert-b,
  .s1 .video-stage > .s1-insert-kalk,
  .s1 .video-stage > .s1-b6 { z-index: 3; }
  /* Szene 8: Foto ruht; die Abdunkelung bleibt über dem Video, aber heller
     (.55 statt .86 — Startwert, Sichtentscheid am A6-Checkpoint: Beweis-Typo
     muss lesbar bleiben, der Spot sichtbar sein; Befund Z6). */
  .s8.has-video .s8-photo { display: none; }
  .s8.has-video .s8-photo-overlay { opacity: .55; }
  /* KI-Transparenz-Hinweis (Stefan-Entscheid 2026-07-21): dezentes Ecken-Label
     NUR auf den Videoszenen und NUR solange wirklich ein Spot läuft — im
     Fallback, unter RM und im Druck zeigt das Deck kein Video, also auch
     keinen Hinweis (Basis-Regel unten hält display:none in jedem Medium).
     Ergänzt die Transparenz-Zeile in Szene 12, ersetzt sie nicht. */
  .scene.has-video .ki-note { display: block; }
}
@media screen and (max-width: 620px) {
  /* Auf Handy-Breiten überläuft der Beweistext von Szene 8 seine eigene
     HUD-Safe-Zone; das Label landete dort zeilengenau IM Zitatsatz (gemessen
     bei 320/360/375/520 px, Prüf-Welle 2026-07-21). Zwischen Textunterkante
     und HUD bleibt kein Platz zum Ausweichen — deshalb ausblenden. Die
     KI-Offenlegung trägt auf diesen Geräten die Transparenz-Zeile in Szene 12,
     die dort unverändert sichtbar ist. Diese Regel MUSS nach der
     has-video-Einblendung stehen: gleiche Spezifität (0,3,0), es entscheidet
     die Reihenfolge. */
  .scene.has-video .ki-note { display: none; }
}

/* Deko-Hintergrund: Deep-Sea-Verlauf + leises Teal-Glimmen am Horizont + Vignette. */
.s1-backdrop { position: absolute; inset: 0; z-index: 0; overflow: hidden; background: var(--grad-dark-depth); }
.s1-glimmer {
  position: absolute; inset: 0;
  background: radial-gradient(62% 42% at 50% 110%, color-mix(in oklab, var(--color-brand-teal) 22%, transparent) 0%, transparent 70%);
  opacity: .7;
  transition: opacity var(--motion-slow) var(--ease-out);
}
.s1-vignette {
  position: absolute; inset: 0;
  background: radial-gradient(122% 92% at 50% 45%, transparent 50%, color-mix(in oklab, var(--color-surface-sunken-dark) 80%, transparent) 100%);
}
/* Zur Punchline zieht das Glimmen leise an. */
.s1.phase-b6 .s1-glimmer { opacity: 1; }

/* Geister-Fenster: unscharfe, token-getönte Rechtecke in der Tiefe (Deko).
   Liegen zwischen Hintergrund und Beat-Ebene; fliegen zur Punchline nach außen. */
.s1-ghosts { position: absolute; inset: 0; z-index: 1; overflow: hidden; }
.s1-ghost {
  position: absolute;
  border-radius: var(--radius-lg);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  filter: blur(6px);
  opacity: .32;
  transition: transform 1100ms var(--ease-in), opacity 900ms var(--ease-in), filter 1100ms var(--ease-in);
}
.s1-ghost--a { width: 34%; height: 42%; top: 6%;  left: 4%;  transform: rotate(-4deg); }
.s1-ghost--b { width: 26%; height: 34%; top: 48%; left: 30%; opacity: .20; }
.s1-ghost--c { width: 30%; height: 38%; top: 12%; right: 6%; transform: rotate(3deg); opacity: .26; }
/* Punchline: die Fenster fliegen an der Kamera vorbei (nach außen, groß, unscharf,
   weg) — gestaffelt über transition-delay. Nur transform/opacity/filter. */
.s1.phase-b6 .s1-ghost--a { transform: translate(-90%, -70%) scale(6); opacity: 0; filter: blur(12px); }
.s1.phase-b6 .s1-ghost--b { transform: translate(80%, 90%) scale(6); opacity: 0; filter: blur(12px); transition-delay: .1s; }
.s1.phase-b6 .s1-ghost--c { transform: translate(95%, -80%) scale(6); opacity: 0; filter: blur(12px); transition-delay: .2s; }

/* ---- Beat-Ebene: jeder Beat füllt die Bühne, genau einer sichtbar ---- */
.s1-beatstage { position: absolute; inset: 0; z-index: 2; }
.s1-beat {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-lg);
  /* HUD-Safe-Area-Reassert (Feedback F1): .s1-beat liegt in der video-stage
     (position:absolute;inset:0) und umgeht damit das Padding von .scene —
     derselbe Sicherheitswert wird hier direkt auf dem eigenen
     Zentrier-Container gesetzt (siehe Kommentar bei .scene). */
  padding: 0 clamp(16px, 6vw, 96px) var(--hud-safe);
  opacity: 0;
  /* Basis-Übergang regelt das Zurückfallen in die Dunkelheit (Klasse entfernt). */
  transition: opacity var(--motion-slow) var(--ease-out);
  pointer-events: none;
}
.s1.phase-b1 .s1-b1,
.s1.phase-b2 .s1-b2,
.s1.phase-b3 .s1-b3,
.s1.phase-b4 .s1-b4,
.s1.phase-b5 .s1-b5,
.s1.phase-b6 .s1-b6 { opacity: 1; }

/* Dauer-Zoom je Beat: der Inhalt drückt über die Beat-Länge langsam heran. */
.s1-zoom { display: flex; flex-direction: column; align-items: center; gap: var(--space-lg); width: 100%; transform: scale(1); }
.s1.phase-b1 .s1-b1 .s1-zoom { transform: scale(1.05); transition: transform 3200ms linear; }
.s1.phase-b2 .s1-b2 .s1-zoom { transform: scale(1.06); transition: transform 3400ms linear; }
.s1.phase-b3 .s1-b3 .s1-zoom { transform: scale(1.05); transition: transform 4600ms linear; }
.s1.phase-b4 .s1-b4 .s1-zoom { transform: scale(1.04); transition: transform 9200ms linear; }
.s1.phase-b5 .s1-b5 .s1-zoom { transform: scale(1.07); transition: transform 4400ms linear; }

/* Cursor (blinkt über das bestehende fx-type-caret-Keyframe, kein neues).
   .px-caret ist der generische zweite Selektor (Task 2, Szene 3): identische
   Basisoptik, kein Kopie-Regelblock; die Blink-Animation selbst hängt an
   eigenen, szenen-spezifischen Phasen-Selektoren weiter unten. */
.s1-caret, .px-caret {
  display: inline-block;
  width: .09em; height: 1.05em;
  margin-left: .06em;
  vertical-align: -.12em;
  background: var(--color-brand-teal);
  border-radius: 1px;
  opacity: 0;
}
.s1.phase-b2 .s1-b2 .s1-caret,
.s1.phase-b3 .s1-b3 .s1-caret,
.s1.phase-b4 .s1-b4 .s1-caret,
.s1.phase-b5 .s1-b5 .s1-caret,
.s1.phase-b3 .s1-insert-b .s1-caret,
.s1.s1-kalk .s1-insert-kalk .s1-caret {
  animation: fx-type-caret .9s steps(1, jump-none) infinite;
}

/* ---- Beat 1: eine zentrierte Zeile, Schärfe-Auf-Blende; „klügste Mitarbeiterin"
   färbt sich ~1,2 s später ins Teal um — direkt per color-Transition auf dem einen
   Span (bewusste Paint-only-Ausnahme wie blur(): rein malend, kein Layout; die
   frühere Kreuzblende mit Text-Kopie sprang bei umbrechendem Inline-Text). */
.s1-b1-line {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(30px, 4.2vw, 80px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  margin: 0;
  max-width: 20ch;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(24px);
  filter: blur(9px);
}
.s1.phase-b1 .s1-b1-line {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  transition: opacity 900ms var(--ease-out), transform 900ms var(--ease-out), filter 900ms var(--ease-out);
}
.s1-hl { white-space: nowrap; color: var(--fg-default); }
.s1.phase-b1 .s1-hl { color: var(--color-brand-teal); transition: color var(--motion-reveal) var(--ease-out) 1200ms; }

/* ---- Beat 2: „Eine KI." / „Erster Arbeitstag." stapeln (gedämpftes Cream),
   dann „Hochmotiviert." riesig in Teal mit Cursor, die zwei Zeilen dimmen auf ~45 %. */
.s1-b2-lines { display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); opacity: 1; }
.s1.phase-b2 .s1-b2-lines { opacity: .45; transition: opacity var(--motion-reveal) var(--ease-out) 1400ms; }
.s1-b2-l1, .s1-b2-l2 {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(24px, 3.1vw, 60px);
  line-height: 1.1;
  color: var(--fg-muted);
  margin: 0;
  opacity: 0;
  transform: translateY(16px);
  filter: blur(6px);
}
.s1.phase-b2 .s1-b2-l1 { opacity: 1; transform: translateY(0); filter: blur(0); transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out); }
.s1.phase-b2 .s1-b2-l2 { opacity: 1; transform: translateY(0); filter: blur(0); transition: opacity var(--motion-reveal) var(--ease-out) .5s, transform var(--motion-reveal) var(--ease-out) .5s, filter var(--motion-reveal) var(--ease-out) .5s; }
.s1-b2-big {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(42px, 5.6vw, 108px);
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--color-brand-teal);
  margin: 0;
  opacity: 0;
  transform: scale(1.14);
  filter: blur(7px);
}
.s1.phase-b2 .s1-b2-big { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 1.4s, transform 700ms var(--ease-out) 1.4s, filter 700ms var(--ease-out) 1.4s; }
.s1-b2-big .s1-caret { height: .72em; width: .13em; }

/* ---- Such-Beats (3 · 5, Grundmuster) + Beat 4 (Kalkulation mit Explorer) ---- */
/* Dunkles Firmen-Suchfeld, materialisiert aus der Tiefe; die KI tippt (JS).
   .px-search/.px-search-ico/.px-search-dim sind die generischen zweiten
   Selektoren (Task 2, Szene 3 verlangt die Wiederverwendung derselben Optik
   ohne Kopie-Regelblock und ohne Änderung am s1-HTML); die Auslöser-Regeln
   (wann materialisiert/dimmt) bleiben getrennt — s1 behält seine
   Beat-Klassen, Szene 3 bekommt eigene Phasen-Selektoren weiter unten. */
.s1-search, .px-search {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  width: min(920px, 80%);
  padding: clamp(12px, 2.4vh, 26px) clamp(18px, 3vw, 34px);
  background: var(--color-surface-sunken-dark);
  border: 1px solid var(--line-on-dark-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--color-brand-teal) 32%, transparent), var(--shadow-xl);
  opacity: 0;
  transform: translateY(34px) scale(.9);
  filter: blur(8px);
}
.s1.scene.entered .s1-b3 .s1-search,
.s1.scene.entered .s1-b4 .s1-search,
.s1.scene.entered .s1-b5 .s1-search {
  /* Materialisieren wird von der jeweiligen Phase gezündet (siehe unten). */
}
.s1.phase-b3 .s1-b3 .s1-search,
.s1.phase-b4 .s1-b4 .s1-search,
.s1.phase-b5 .s1-b5 .s1-search,
.s1.phase-b3 .s1-insert-b .s1-search,
.s1.s1-kalk .s1-insert-kalk .s1-search {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out);
}
.s1-search-ico, .px-search-ico { width: clamp(24px, 3vw, 34px); height: clamp(24px, 3vw, 34px); color: var(--fg-soft); flex: none; }
/* .fx-query ist die generische Klasse für die getippte Frage (Task 1 Engine,
   hier zum ersten Mal in der CSS genutzt): identische Optik zu .s1-query. */
.s1-query, .fx-query {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(18px, 1.8vw, 34px);
  line-height: 1;
  color: var(--fg-default);
  white-space: nowrap;
}
/* Wenn die Antwort eintrifft, zieht der Fokus vom Feld weg (dim + leichter Blur).
   Verweilzeiten (Stefan-Feedback, mitlesbar): die fertig getippte Frage steht
   ~1,1s voll (Caret blinkt weiter), erst dann dimmt das Feld und die Antwort
   landet; die gelandete Antwort hält danach ≥1,2s volle Deckkraft, bevor der
   Beat ausblendet (B4: bevor der Lift/Explorer-Einsatz beginnt). */
.s1-search-dim, .px-search-dim { opacity: 1; }
.s1.phase-b3 .s1-b3 .s1-search-dim { opacity: .55; filter: blur(2px); transition: opacity var(--motion-reveal) var(--ease-out) 2.7s, filter var(--motion-reveal) var(--ease-out) 2.7s; }
.s1.phase-b4 .s1-b4 .s1-search-dim { opacity: .55; filter: blur(2px); transition: opacity var(--motion-reveal) var(--ease-out) 2.2s, filter var(--motion-reveal) var(--ease-out) 2.2s; }
.s1.phase-b5 .s1-b5 .s1-search-dim { opacity: .55; filter: blur(2px); transition: opacity var(--motion-reveal) var(--ease-out) 2.4s, filter var(--motion-reveal) var(--ease-out) 2.4s; }
/* Insert-Duplikate: Suchfeld dimmt zurück, sobald die Antwort landet —
   jeweils mit derselben Verzögerung wie die Antwort-Regel oben. */
.s1.phase-b3 .s1-insert-b .s1-search-dim { opacity: .55; filter: blur(2px); transition: opacity var(--motion-reveal) var(--ease-out) 2.7s, filter var(--motion-reveal) var(--ease-out) 2.7s; }
.s1.s1-kalk .s1-insert-kalk .s1-search-dim { opacity: .55; filter: blur(2px); transition: opacity var(--motion-reveal) var(--ease-out) 1.3s, filter var(--motion-reveal) var(--ease-out) 1.3s; }

/* Antwort landet groß unter dem Feld (Schärfe + Skalen-Settle). */
.s1-answer {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(28px, 4vw, 76px);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  margin: 0;
  max-width: 22ch;
  text-wrap: balance;
  opacity: 0;
  transform: scale(1.08);
  filter: blur(8px);
}
.s1.phase-b3 .s1-b3 .s1-answer { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 2.7s, transform 700ms var(--ease-out) 2.7s, filter 700ms var(--ease-out) 2.7s; }
.s1.phase-b5 .s1-b5 .s1-answer { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 2.4s, transform 700ms var(--ease-out) 2.4s, filter 700ms var(--ease-out) 2.4s; }
.s1-b4 .s1-answer { font-size: clamp(24px, 3.3vw, 64px); }
.s1.phase-b4 .s1-b4 .s1-answer { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 2.2s, transform 700ms var(--ease-out) 2.2s, filter 700ms var(--ease-out) 2.2s; }
/* Insert-Duplikate: Antwort-Landung wie beim jeweiligen Original-Beat.
   Insert B folgt b3 (2,7s), Insert C landet 1,3s nach Fenster-Start
   (Tipp-Ende ~12,4 im Spot) und hält bis 16,0 (~2,6s Lesezeit). */
.s1.phase-b3 .s1-insert-b .s1-answer { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 2.7s, transform 700ms var(--ease-out) 2.7s, filter 700ms var(--ease-out) 2.7s; }
.s1.s1-kalk .s1-insert-kalk .s1-answer { opacity: 1; transform: scale(1); filter: blur(0); transition: opacity 700ms var(--ease-out) 1.3s, transform 700ms var(--ease-out) 1.3s, filter 700ms var(--ease-out) 1.3s; }

/* Beat 4: Suche+Antwort heben sich, das Explorer-Fenster steigt aus der Tiefe. */
.s1-b4 .s1-zoom { position: relative; height: 100%; justify-content: center; }
.s1-b4-lift { display: flex; flex-direction: column; align-items: center; gap: var(--space-lg); transform: translateY(0); }
.s1.phase-b4 .s1-b4-lift { transform: translateY(-14vh); transition: transform 700ms var(--ease-in-out) 4.1s; }

/* Explorer-Fenster (Raised Surface). Basis = tief unten in der Dunkelheit; die
   Phase hebt es (mit Verzögerung) nach vorn, beim Phasenende sinkt es zurück
   (Basiszustand = Tiefe) — ein einziger Zwei-Wege-Übergang, kein Keyframe.
   .px-explorer* sind die generischen zweiten Selektoren (Task 7, Szene 12):
   identische Optik, kein Kopie-Regelblock; Größe/Position der Szene-12-
   Mini-Ausgabe werden dort gezielt überschrieben (additive Erweiterung). */
.s1-explorer, .px-explorer {
  position: absolute;
  left: 50%;
  /* Safe-Area: bleibt oberhalb der HUD-Leiste (fixed unten, ~84px hoch).
     Bewusst GRÖSSER als der generische --hud-safe-Wert (12vh/160px) und
     NICHT darauf vereinheitlicht: das Explorer-Fenster ist (anders als die
     zentrierten Text-Blöcke, die --hud-safe nutzen) eine absolut
     positionierte, sichtbar gerahmte Requisiten-Fläche (border + --shadow-xl)
     und sitzt tiefer im Stapel als reiner Text — der zusätzliche Puffer
     verhindert, dass Rahmen/Schatten optisch an die HUD-Leiste stoßen. Nur
     .s1-explorer nutzt diesen bottom-Wert wirklich: die Szene-12-Instanz
     (.s12-gag .px-explorer) überschreibt auf position:static, dort greift
     bottom gar nicht mehr. */
  bottom: clamp(110px, 16vh, 190px);
  width: min(720px, 76%);
  transform: translate(-50%, 60px) scale(.86);
  transform-origin: center bottom;
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  opacity: 0;
  filter: blur(10px);
  transition: opacity var(--motion-slow) var(--ease-in), transform var(--motion-slow) var(--ease-in), filter var(--motion-slow) var(--ease-in);
}
.s1.phase-b4 .s1-b4 .s1-explorer {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-draw) var(--ease-out) 4.2s, transform var(--motion-draw) var(--ease-out) 4.2s, filter var(--motion-draw) var(--ease-out) 4.2s;
}
.s1-explorer-bar, .px-explorer-bar {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  background: var(--color-surface-sunken-dark);
  border-bottom: 1px solid var(--line-on-dark-default);
}
.s1-folder, .px-folder { width: 18px; height: 18px; color: var(--color-brand-teal); flex: none; }
.s1-explorer-body, .px-explorer-body { padding: var(--space-sm) var(--space-md) var(--space-md); display: flex; flex-direction: column; gap: var(--space-xs); }
.s1-filerow, .px-filerow {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-sm);
}
.s1-filerow--active, .px-filerow--active { background: var(--line-on-dark-default); }
.s1-file-ico, .px-file-ico {
  width: 16px; height: 18px; flex: none;
  border-radius: 2px;
  background: var(--line-on-dark-strong);
}
.s1-file-ico--xls, .px-file-ico--xls {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-brand-teal);
  color: var(--color-surface-sunken-dark);
  font-family: var(--font-mono); font-size: 11px; font-weight: 700;
}
/* Skelett-Balken (Deko, kein Text). */
.s1-sk { display: inline-block; height: 8px; border-radius: var(--radius-full); background: var(--line-on-dark-default); }
.s1-sk--bar1 { width: 70px; }
.s1-sk--bar2 { width: 34px; background: var(--line-on-dark-strong); }
.s1-sk--row  { width: 58%; }
.s1-sk--row2 { width: 44%; }

/* Datei-Gag: fester Kasten (Ghost reserviert Breite), Live-Text tippt sich
   per JS um (pitch.js, runFileGag). Nur die Textbreite wächst — feste Box. */
.fx-filegag {
  position: relative;
  display: inline-block;
  font-family: var(--font-mono);
  font-size: clamp(13px, 1.2vw, 22px);
  white-space: nowrap;
}
.filegag-ghost { visibility: hidden; }
.filegag-live { position: absolute; inset: 0 auto 0 0; white-space: nowrap; color: var(--fg-default); }
.filegag-ext { color: var(--fg-soft); }

/* ---- Beat 6: Punchline-Endframe. Dunkler Wasch legt sich über die vorbei-
   fliegenden Fenster; Zeile 1 landet aus der Tiefe, schiebt sich hoch und dimmt,
   Zeile 2 kommt größer durch sie hindurch, der Gold-Punkt blendet still ein. */
.s1-punch { gap: var(--space-md); background: transparent; }
.s1.phase-b6 .s1-b6 { background: radial-gradient(120% 100% at 50% 50%, color-mix(in oklab, var(--color-surface-sunken-dark) 62%, transparent) 0%, color-mix(in oklab, var(--color-surface-sunken-dark) 82%, transparent) 100%); }
.s1-punch-1 {
  font-family: var(--font-headline);
  font-weight: 500;
  font-size: clamp(20px, 3.2vw, 62px);
  line-height: 1.2;
  letter-spacing: -0.025em;
  color: var(--fg-strong-muted);
  margin: 0;
  max-width: 26ch;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(0) scale(.5);
  filter: blur(16px);
}
.s1.phase-b6 .s1-punch-1 {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity 900ms var(--ease-out) .55s, transform 900ms var(--ease-out) .55s, filter 900ms var(--ease-out) .55s;
}
/* Zeile 1 rückt hoch und tritt zurück, sobald Zeile 2 durchkommt. */
.s1.phase-b6.s1-shift .s1-punch-1 {
  transform: translateY(-18vh) scale(.82);
  opacity: .5;
  filter: blur(3px);
  transition: opacity 700ms var(--ease-in-out), transform 700ms var(--ease-in-out), filter 700ms var(--ease-in-out);
}
.s1-punch-2 {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(30px, 5.4vw, 104px);
  line-height: 1.06;
  letter-spacing: -0.035em;
  color: var(--fg-default);
  margin: 0;
  max-width: 18ch;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(40px) scale(.4);
  filter: blur(20px);
}
.s1.phase-b6.s1-shift .s1-punch-2 {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity 1000ms var(--ease-out), transform 1000ms var(--ease-out), filter 1000ms var(--ease-out);
}
.s1-punch-2 .gold-dot { opacity: 0; }
.s1.phase-b6.s1-dot .s1-punch-2 .gold-dot { opacity: 1; transition: opacity var(--motion-reveal) var(--ease-out); }

/* Reduced Motion Szene 1: die Beats laufen zeitlich weiter (Geschichte bleibt),
   aber jeder Übergang ist nur eine ruhige Opacity-Blende — keine Translation,
   kein Zoom, kein Blur, keine Schreibmaschine, kein Fenster-Flug. */
@media (prefers-reduced-motion: reduce) {
  .s1-glimmer,
  .s1-ghost,
  .s1-zoom,
  .s1-b1-line,
  .s1-b2-lines, .s1-b2-l1, .s1-b2-l2, .s1-b2-big,
  .s1-search, .s1-search-dim, .s1-query, .s1-answer,
  .s1-b4-lift, .s1-explorer,
  .s1-punch-1, .s1-punch-2, .s1-punch-2 .gold-dot,
  .s1.phase-b1 .s1-b1 .s1-zoom, .s1.phase-b2 .s1-b2 .s1-zoom,
  .s1.phase-b3 .s1-b3 .s1-zoom, .s1.phase-b4 .s1-b4 .s1-zoom,
  .s1.phase-b5 .s1-b5 .s1-zoom,
  .s1.phase-b1 .s1-b1-line,
  .s1.phase-b2 .s1-b2-lines, .s1.phase-b2 .s1-b2-l1, .s1.phase-b2 .s1-b2-l2, .s1.phase-b2 .s1-b2-big,
  .s1.phase-b3 .s1-b3 .s1-search, .s1.phase-b4 .s1-b4 .s1-search, .s1.phase-b5 .s1-b5 .s1-search,
  .s1.phase-b3 .s1-b3 .s1-search-dim, .s1.phase-b4 .s1-b4 .s1-search-dim, .s1.phase-b5 .s1-b5 .s1-search-dim,
  .s1.phase-b3 .s1-b3 .s1-answer, .s1.phase-b4 .s1-b4 .s1-answer, .s1.phase-b5 .s1-b5 .s1-answer,
  .s1.phase-b4 .s1-b4-lift, .s1.phase-b4 .s1-b4 .s1-explorer,
  .s1.phase-b6 .s1-punch-1, .s1.phase-b6.s1-shift .s1-punch-1,
  .s1.phase-b6.s1-shift .s1-punch-2,
  .s1.phase-b6 .s1-ghost--a, .s1.phase-b6 .s1-ghost--b, .s1.phase-b6 .s1-ghost--c {
    transform: none !important;
    filter: none !important;
    transition: opacity var(--motion-base) var(--ease-out) !important;
    transition-delay: 0s !important;
  }
  /* Die zwei Zeilen von Beat 2 bleiben ruhig sichtbar (kein Dimmen), Fenster nur weg-blenden. */
  .s1.phase-b2 .s1-b2-lines { opacity: 1 !important; }
  .s1.phase-b6 .s1-ghost--a, .s1.phase-b6 .s1-ghost--b, .s1.phase-b6 .s1-ghost--c { opacity: 0 !important; }
  .s1-caret { display: none !important; }
}

/* Wort + Gold-Punkt zusammenhalten (der Punkt ersetzt das Satzzeichen und darf
   nie in eine eigene Zeile umbrechen). Pendant zur .nowrap-Nutzung der Website. */
.nowrap { white-space: nowrap; }

/* ---------- Szene 2: Claim (Feinschliff Task 2) ----------
   Breiten in px statt ch: die ch-Werte (an der 16px-Basisschrift des Wraps
   gemessen) klemmten die Spalte auf ~550px und zerlegten den Claim bei
   mittleren Viewports in Ein-Wort-Zeilen. Ziel: maximal 3 ausgewogene Zeilen
   bei 1024/1280/1920 (text-wrap: balance verteilt sie gleichmäßig).
   Die frühere Unterzeile (.s2-sub) ist ersatzlos raus (Task 2), daher hier
   keine eigene Regel mehr dafür. */
.s2-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-lg);
  max-width: min(1120px, 92vw);
}
.s2-eyebrow { margin: 0; }
.s2-claim { margin: 0; max-width: min(1120px, 92vw); text-wrap: balance; }

/* Gold-Punkt der Szene-2-Headline setzt bewusst zuletzt (nach der Landung
   der Headline): eigener Opacity-Übergang mit transition-delay, nur Opacity,
   kein Layout-Shift (der Punkt nimmt in .headline-display bereits vorab
   seinen Platz ein). Reduced Motion: Punkt steht sofort mit dem Rest des
   Claims (kein Delay, wie überall sonst). */
.s2-claim .gold-dot { opacity: 0; }
#s2.scene.entered .s2-claim .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1.3s;
}
@media (prefers-reduced-motion: reduce) {
  .s2-claim .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* Szene 2: .fx-depth soll die Transform auf .headline-display-Elementen
   besitzen (die Basis-Regel .scene .headline-display würde die Ruhe-Transform
   sonst per Spezifität gewinnen und den Tiefen-Auftritt kippen). Reassert nur
   die vorhandenen Vokabular-Werte, kein neues Keyframe. Szene 12 hat seit
   Task 7 ein eigenes Phasen-Gate (siehe dort) statt des generischen
   .scene.entered-Triggers, daher hier nur noch #s2. */
#s2 .headline-display.fx-depth {
  transform: translateZ(-360px) scale(.6);
}
#s2.scene.entered .headline-display.fx-depth {
  transform: translateZ(0) scale(1);
  transition-property: opacity, transform;
  transition-duration: var(--motion-draw);
  transition-timing-function: var(--ease-out);
}

/* ---------- Szene 12: Der erste Schritt + Button-Gag „Gefunden" (Task 7) ----------
   CTA-Block (Eyebrow/Headline/Subline/Button+Zeile) als kumulative Folge über
   den generischen Beat-Dirigenten (data-phases → .phase-p1…p6, Muster wie
   Szene 4/8): der Dirigent setzt immer nur EINE phase-pN-Klasse gleichzeitig,
   darum listen die kumulativen Regeln unten jeweils alle Phasen, ab denen ein
   Element sichtbar bleiben soll. Eyebrow läuft über das generische
   .fx-rise/.scene.entered-Vokabular (kein Phasen-Gate nötig, wie Beat 1 in
   Szene 8/10/11). */
/* Der CTA-Block zentriert sich über die generische .scene-Regel
   (align-items/justify-content center + globale HUD-Safe-Area als
   padding-bottom, Feedback F1). Kein eigenes Bühnen-Padding mehr nötig: der
   Gag ist seit Feedback F8 kein separat verankertes Element mehr, sondern
   ein normales, letztes Kind von .s12-wrap (siehe .s12-gag unten) — er zieht
   damit automatisch mit demselben Zentrierungs-Container um und bekommt
   seinen Abstand zum CTA-Block über den normalen Flex-Gap der Spalte. */
.s12-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* vh-gedeckelt (Muster Szene 4): bei sehr flachen Fenstern rücken Eyebrow/
     Headline/Subline/CTA/Gag etwas enger zusammen, statt den verfügbaren
     Zentrierungs-Raum zu sprengen. */
  gap: clamp(14px, 3vh, var(--space-lg));
  max-width: min(560px, 92vw);
}
.s12-head { margin: 0; max-width: 15ch; font-size: clamp(38px, min(5.4vw, 7.4vh), 64px); }
.s12-sub {
  margin: 0;
  max-width: 42ch;
  font-family: var(--font-body);
  font-size: clamp(15px, min(1.6vw, 2.4vh), 19px);
  line-height: 1.5;
  color: var(--fg-soft);
  text-wrap: balance;
}
.s12-cta-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  margin-top: var(--space-sm);
}
.s12-cta { margin: 0; }
.s12-secondary {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--fg-soft);
  margin: 0;
}

/* Transparenz-Zeile (Task A5, Stefan-Gate 2026-07-18): reiner Fluss-Nachbar
   von .s12-cta-block innerhalb von .s12-wrap (kein eigenes margin-top nötig,
   der bestehende Flex-Gap der Spalte liefert den Abstand, Muster wie .s12-gag
   darunter). --fg-soft statt eines expliziten --fg-on-dark-soft: identischer
   Wert, weil .pitch-body auf [data-theme="dark"] steht (colors_and_type.css)
   — dieselbe Ebene wie .s12-sub/.s12-secondary in dieser Szene, AA-lesbar
   (68 %), bewusst NICHT die blassere --fg-faint-Deko-Stufe, weil die Zeile
   eine echte Aussage trägt. Schriftgröße an .s12-secondary/.s12-gag-found
   angelehnt (13/14px-Familie der Szene), hier am unteren Rand dieser
   Spanne, weil die Zeile die unwichtigste der drei ist. Sichtbarkeit im
   Druck: die Klasse .screen-only im Markup (Hausmuster .s0-start) blendet
   sie über die bestehende @media-print-Regel weiter oben aus — kein
   zusätzlicher Selektor im großen Druck-Block nötig. Phasen-Gate (.fx-rise)
   teilt sich die Selektorliste von .s12-cta-block weiter unten (Phase 4):
   die Zeile soll nicht vor dem Button auftauchen. */
.s12-transparency {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--fg-soft);
}

/* Headline: eigenes Phasen-Gate statt .scene.entered (Startwert 800 ms liegt
   weit über der .dN-Staffel, max. 1,05 s) — Basiswerte wie das Vokabular,
   nur der Auslöser wechselt auf Phase 2 (kumulativ bis Phase 6). */
#s12 .headline-display.fx-depth { opacity: 0; transform: translateZ(-360px) scale(.6); transition: none; }
#s12.phase-p2 .headline-display.fx-depth,
#s12.phase-p3 .headline-display.fx-depth,
#s12.phase-p4 .headline-display.fx-depth,
#s12.phase-p5 .headline-display.fx-depth,
#s12.phase-p6 .headline-display.fx-depth {
  opacity: 1;
  transform: translateZ(0) scale(1);
  transition: opacity var(--motion-draw) var(--ease-out), transform var(--motion-draw) var(--ease-out);
}
.s12-head .gold-dot { opacity: 0; }
#s12.phase-p2 .s12-head .gold-dot,
#s12.phase-p3 .s12-head .gold-dot,
#s12.phase-p4 .s12-head .gold-dot,
#s12.phase-p5 .s12-head .gold-dot,
#s12.phase-p6 .s12-head .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1s;
}

/* Subline (Phase 3, 2400 ms): weiches Einsteigen von unten, Basiswert re-
   assertiert mit transition:none (Muster #s3 .s3-double .fx-rise). */
#s12 .s12-sub.fx-rise { opacity: 0; transform: translateY(var(--reveal-distance)); transition: none; }
#s12.phase-p3 .s12-sub.fx-rise,
#s12.phase-p4 .s12-sub.fx-rise,
#s12.phase-p5 .s12-sub.fx-rise,
#s12.phase-p6 .s12-sub.fx-rise {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}

/* CTA-Block: Button + Zeile gemeinsam (Phase 4, 4200 ms). Die Transparenz-
   Zeile (Task A5) läuft in derselben Phase mit — sie hängt direkt unter dem
   Block und soll nicht vor dem Button auftauchen; kein eigener Block, reine
   Selektor-Erweiterung auf demselben Timing/Token-Satz. */
#s12 .s12-cta-block.fx-rise,
#s12 .s12-transparency.fx-rise { opacity: 0; transform: translateY(var(--reveal-distance)); transition: none; }
#s12.phase-p4 .s12-cta-block.fx-rise,
#s12.phase-p5 .s12-cta-block.fx-rise,
#s12.phase-p6 .s12-cta-block.fx-rise,
#s12.phase-p4 .s12-transparency.fx-rise,
#s12.phase-p5 .s12-transparency.fx-rise,
#s12.phase-p6 .s12-transparency.fx-rise {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}

/* Härtung P3 (Review-Fund M3, final-review-korrektheit.md): der einzige
   fokussierbare Link/Button innerhalb eines phasen-gegateten Blocks im
   ganzen Deck (Inventar aller a/button in phasen-gegateten Blöcken über
   alle 13 Szenen, siehe Report) — der Termin-Buchungsweg selbst, das
   Projektziel. Vor Phase 4 (4200 ms) steht der Block bei opacity:0, bleibt
   aber im Tab-Index; ein Tastatur-Nutzer, der schneller tabbt als die
   Szene dauert, würde einen unsichtbaren CTA fokussieren. Fix: erhält der
   Link Tastatur-Fokus, wird sein Block sofort sichtbar — Muster wie die
   HUD-Auto-Hide-Fokus-Ausnahme oben (.hud.hud-idle:has(:focus-visible)):
   :has() statt einer zweiten JS-Zustandsspur, reine Spezifität (kein
   !important nötig) schlägt die phase-pN-Regeln oben (1 Element mehr in
   der Selektorkette). transition:none macht die Sichtbarkeit sofort statt
   erst nach --motion-reveal wirksam. Print/RM unberührt: dort gilt ohnehin
   immer der volle Endzustand (RM: sofortige letzte Phase in pitch.js;
   Print: eigener !important-Spiegel weiter unten), :focus-visible tritt in
   keinem der beiden Fälle real auf. */
#s12 .s12-cta-block.fx-rise:has(a:focus-visible) {
  opacity: 1;
  transform: translateY(0);
  transition: none;
}

/* ---- Button-Gag „Gefunden" ----
   Feedback F8: der Gag stand vorher eigenständig unten verankert (Floor
   statt Zentrierungs-Fluss) — bei flachen Fenstern wanderte dieser Floor
   in den CTA-Block hinein (Kollision). Robuster Ersatz: der Gag ist jetzt
   das letzte normale Kind von .s12-wrap, sitzt also IM FLUSS direkt unter
   dem CTA-Block; der Flex-Gap der Spalte (oben, vh-gedeckelt) liefert den
   garantierten Mindestabstand, unabhängig von der Viewport-Höhe. Seine
   eigene Größe ist zusätzlich vh-gedeckelt (Muster Szene 4): bei sehr
   flachen Fenstern schrumpft der Gag zuerst, nie der CTA-Block. Suchfeld-
   Optik = die .s1-search*-Regeln über den generischen .px-search-Selektor
   (Szene 1/3), Explorer-Optik = die .s1-explorer*-Regeln über den
   generischen .px-explorer-Selektor (Szene 1, additive Erweiterung oben) —
   Größe hier gezielt für die Mini-Ausgabe überschrieben, kein
   Kopie-Regelblock. Weiterhin aria-hidden + pointer-events:none, der
   CTA-Button bleibt jederzeit klickbar. */
.s12-gag {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  pointer-events: none;
}

/* Mini-Suchfeld (Phase 5, 6500 ms), deutlich kleiner als Szene 1/3;
   Innenabstand/Icon zusätzlich vh-gedeckelt. */
.s12-gag .px-search { width: min(300px, 78vw); padding: clamp(6px, 1.4vh, 10px) clamp(12px, 2.6vw, 16px); gap: var(--space-sm); }
.s12-gag .px-search-ico { width: clamp(14px, 2.2vh, 18px); height: clamp(14px, 2.2vh, 18px); }
.s12-gag .fx-query { font-size: clamp(13px, min(1.6vw, 2vh), 17px); }
#s12.phase-p5 .s12-gag .px-search,
#s12.phase-p6 .s12-gag .px-search {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out);
}
#s12.phase-p5 .s12-gag .px-caret {
  animation: fx-type-caret .9s steps(1, jump-none) infinite;
}
/* Feld dimmt, sobald der Fund materialisiert (Phase 6) — Zwei-Elemente-Trick
   wie .s1-search-dim. */
#s12.phase-p6 .s12-gag .px-search-dim {
  opacity: .55;
  filter: blur(2px);
  transition: opacity var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out);
}

/* Fund (Phase 6, 9200 ms): „Gefunden·" + Mini-Explorer nebeneinander (Zeile
   statt Spalte — hält die Gag-Gruppe flach, wichtig für den Sicherheitsabstand
   zur HUD-Leiste), beide statisch — die Datei ist diesmal SOFORT da, kein
   Umbenenn-Tipp-Gag wie in Szene 1. */
.s12-gag-result { display: flex; align-items: center; gap: var(--space-sm); }
.s12-gag-found {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13px;
  color: var(--color-brand-teal);
  white-space: nowrap;
  opacity: 0;
  transition: none;
}
#s12.phase-p6 .s12-gag-found {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}
.s12-gag-found .gold-dot { opacity: 0; }
#s12.phase-p6 .s12-gag-found .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) .5s;
}

/* Mini-Explorer: Position/Breite auf den normalen Fluss der Gag-Gruppe
   umgeschrieben (statt viewport-verankertem Absolut-Float wie in Szene 1) —
   der visuelle Rest (Fläche, Radius, Schatten) kommt unverändert aus der
   .px-explorer-Basisregel oben. Schmaler + kleinere Mono-Schrift, damit die
   Dateizeile einzeilig bleibt (kein zusätzlicher Höhenverbrauch). */
.s12-gag .px-explorer {
  position: static;
  width: min(280px, 62vw);
  transform: translateY(16px) scale(.94);
  transform-origin: center;
}
#s12.phase-p6 .s12-gag .px-explorer {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out);
}
.s12-gag .px-explorer-bar { padding: clamp(4px, 1vh, 6px) var(--space-sm); }
.s12-gag .px-explorer-body { padding: clamp(4px, 1vh, 6px) var(--space-sm) clamp(4px, 1vh, 6px); }
.s12-gag-filename {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--fg-default);
  /* Passt bei 280px Fensterbreite knapp einzeilig; falls nicht (schmale
     Viewports), lieber lesbar umbrechen als abschneiden — die Pointe ist der
     volle Dateiname, kein Ellipsis-Verlust. */
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.25;
}

/* Reduced Motion: kompletter CTA-Block sofort lesbar, Gag-Endzustand ruhig
   sichtbar (kein Tippen, kein Materialisieren) — der Dirigent aktiviert unter
   reduced motion ohnehin nur die letzte Phase (phase-p6); die harten
   !important-Overrides hier lösen sich bewusst von der Phasen-Kaskade
   (Muster Szene 4/11). */
@media (prefers-reduced-motion: reduce) {
  #s12 .headline-display.fx-depth,
  #s12 .s12-sub.fx-rise,
  #s12 .s12-cta-block.fx-rise,
  #s12 .s12-transparency.fx-rise {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .s12-head .gold-dot { opacity: 1 !important; transition: none !important; }
  .s12-gag .px-search, .s12-gag .px-explorer {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
  .s12-gag .px-search-dim { opacity: .55 !important; filter: none !important; }
  .s12-gag-found, .s12-gag-found .gold-dot { opacity: 1 !important; transition: none !important; }
}
/* ============================================================================
   WELLE 2 — Szenen-Layouts (Szene 3 Es liegt nicht an ihr, 5 Mechanismus,
   6 Vorgehen). Nur Layout + Timing. Bewegung stammt komplett aus dem
   .fx-*-Vokabular oben (.fx-rise-Staffel, .fx-depth-Schluss); keine Szene
   erfindet eigene Keyframes. Animiert wird ausschließlich transform/opacity
   (feste Layout-Boxen). Farben/Fonts nur über var(--…)-Tokens aus
   colors_and_type.css. Kein neuer Übergang außerhalb des Vokabulars, daher
   greift die bestehende Reduced-Motion-Media-Query (alle .fx-* verhalten
   sich wie .fx-fade) auch für Szene 6; Szene 3 hat wegen ihrer eigenen
   Beat-Phasen einen zusätzlichen, eigenen Reduced-Motion-Block (siehe dort),
   ebenso Szene 4/5 (Task 3, kumulative Phasen-Spalten statt Beat-Wechsel).
   ============================================================================ */

/* ---------- Szene 3: Es liegt nicht an ihr (Task 2, komplett neu) ----------
   Sequenzieller Filmschnitt wie Szene 1: vier Beats füllen nacheinander die
   Bühne (Diagnose · Doppelzeile · Callback-Staffel · Punchline), genau einer
   sichtbar. Der Takt kommt aus dem generischen Beat-Dirigenten (data-phases
   → .phase-p1…​.phase-p7 auf der Section). Die Beat-Texte sind bespoke
   Klassen (kein .fx-rise/.fx-depth direkt am Element, siehe HTML-Kommentar)
   außer bei der Doppelzeile/Punchline, die das Vokabular per Phasen-Gate
   wiederverwenden — Basiswert kommt vom Vokabular, der Auslöser ist hier die
   Beat-Phase statt der generische .scene.entered-Trigger (der sonst beim
   Szeneneintritt zu früh feuern würde). Kein eigenes @keyframes, nur
   transform/opacity-Übergänge. */
.s3-beat {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-lg);
  /* HUD-Safe-Area-Reassert (Feedback F1), siehe .s1-beat weiter oben. */
  padding: 0 clamp(16px, 6vw, 96px) var(--hud-safe);
  opacity: 0;
  transition: opacity var(--motion-slow) var(--ease-out);
  pointer-events: none;
}
.s3.phase-p1 .s3-diagnose, .s3.phase-p2 .s3-diagnose { opacity: 1; }
.s3.phase-p3 .s3-double { opacity: 1; }
.s3.phase-p4 .s3-callback, .s3.phase-p5 .s3-callback, .s3.phase-p6 .s3-callback { opacity: 1; }
.s3.phase-p7 .s3-punch { opacity: 1; }

/* Geister-Fenster (Feedback WB, Baustein 1): additive Rückkehr der Szene-1/
   Titelfolien-Requisiten (.s1-ghost-Basis liefert Form/Blur/Farbe, kein
   s1/s0-Change) — eigene Positions-/Deckkraft-Klassen mit Szene-3-Präfix.
   Deckkraft deutlich unter dem Text (Zielband .1–.18), z-index 0 (hinter der
   Beat-Ebene, die im DOM danach folgt). Sehr langsames Driften: ein einziger
   Transform-Übergang über die volle Szenendauer (Muster: lange, lineare
   Übergänge wie .s1-zoom/.s5-intro), ausgelöst vom generischen
   .scene.entered-Trigger. Nur transform/opacity, kein neues @keyframes. */
.s3-ghosts { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.s3-ghost--a { width: 30%; height: 40%; top: 8%;  left: 6%;  opacity: .14; transform: rotate(-3deg) translate(0, 0); }
.s3-ghost--b { width: 25%; height: 33%; top: 50%; right: 8%; opacity: .11; transform: rotate(2deg) translate(0, 0); }
#s3.scene.entered .s3-ghost--a {
  transform: rotate(-3deg) translate(1.6%, -2.2%);
  transition: transform 18600ms linear;
}
#s3.scene.entered .s3-ghost--b {
  transform: rotate(2deg) translate(-1.6%, 2.2%);
  transition: transform 18600ms linear;
}
@media (prefers-reduced-motion: reduce) {
  .s3-ghost--a, .s3-ghost--b,
  #s3.scene.entered .s3-ghost--a, #s3.scene.entered .s3-ghost--b {
    transform: none !important;
    transition: none !important;
  }
}

/* ---- Beat 1+2 (Phasen 1–2) · Diagnose: Suchfeld-Frage, dann Antwort ----
   Suchfeld-Optik = .s1-search*-Regeln über den generischen .px-search-
   Selektor (oben bei Szene 1 erweitert). Materialisiert in Phase 1 und
   bleibt (gedimmt) in Phase 2 sichtbar — kein Schnitt, nur ein Dimm-Wechsel,
   wenn die Antwort landet (wie das s1-search-dim-Muster). Layout/Gap kommt
   bereits von .s3-beat oben, keine eigene Regel nötig. */
.s3.phase-p1 .s3-diagnose .px-search,
.s3.phase-p2 .s3-diagnose .px-search {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out), filter var(--motion-reveal) var(--ease-out);
}
.s3.phase-p1 .s3-diagnose .px-caret,
.s3.phase-p2 .s3-diagnose .px-caret {
  animation: fx-type-caret .9s steps(1, jump-none) infinite;
}
/* Antwort landet, sobald Phase 2 beginnt; das Feld dimmt gleichzeitig. */
.s3.phase-p2 .s3-diagnose .px-search-dim {
  opacity: .55;
  filter: blur(2px);
  transition: opacity var(--motion-reveal) var(--ease-out) .1s, filter var(--motion-reveal) var(--ease-out) .1s;
}
.s3-answer1 {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(28px, 4vw, 76px);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  max-width: 22ch;
  text-wrap: balance;
  opacity: 0;
  transform: scale(1.08);
  filter: blur(8px);
}
.s3.phase-p2 .s3-answer1 {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  transition: opacity var(--motion-reveal) var(--ease-out) .1s, transform var(--motion-reveal) var(--ease-out) .1s, filter var(--motion-reveal) var(--ease-out) .1s;
}

/* ---- Beat 3 (Phase 3) · Doppelzeile ----
   Zwei kurze Sätze, gestaffelt über das .fx-rise-Vokabular — per Phasen-Gate
   an Phase 3 gebunden (Reset hält sie außerhalb ihrer Phase auf dem
   Ruhezustand, höhere Spezifität als der generische .scene.entered-Trigger,
   der sonst sofort beim Szeneneintritt feuern würde). */
/* Feedback W12: max-width saß bisher auf .s3-double selbst — das ist
   zugleich der .s3-beat-Vollbühnen-Container (position:absolute; inset:0).
   Ein max-width auf einem so verankerten Element "over-constrained" die
   Absolut-Positionierung: der Browser hält links:0 fest und verwirft
   rechts:0, die Box blieb links kleben statt zu zentrieren (Bounding-Box
   nur ~halbe Bühnenbreite, x=0). Muster wie .s3-punch-line (Punchline trägt
   ihr max-width ebenfalls selbst, nicht der umschließende .s3-punch): das
   max-width gehört auf die Textzeilen, die Bühne (.s3-double) bleibt
   uneingeschränkt volle Breite, ihr align-items:center zentriert die Zeilen. */
.s3-double-l1, .s3-double-l2 {
  margin: 0;
  max-width: min(760px, 88vw);
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(22px, 2.8vw, 42px);
  line-height: 1.28;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  text-wrap: balance;
}
#s3 .s3-double .fx-rise { opacity: 0; transform: translateY(var(--reveal-distance)); transition: none; }
#s3.phase-p3 .s3-double .fx-rise.d1 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
#s3.phase-p3 .s3-double .fx-rise.d3 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out) .3s, transform var(--motion-reveal) var(--ease-out) .3s;
}

/* ---- Beat 4 (Phasen 4–6) · Callback-Staffel ----
   Drei Zeilen an derselben zentrierten Position (absolut übereinander),
   ein Ersetzen statt Stapeln: pro Phase ist genau eine Zeile bei Opacity 1,
   schneller Cross-Fade (var(--motion-base), zackig — bewusst kürzere Dwells,
   weil hier Bekanntes zitiert wird). */
.s3-cb {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  width: 100%;
  max-width: 28ch;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(24px, 3.4vw, 52px);
  line-height: 1.22;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  text-wrap: balance;
  opacity: 0;
  transition: opacity var(--motion-base) var(--ease-out);
}
.s3.phase-p4 .s3-cb--1,
.s3.phase-p5 .s3-cb--2,
.s3.phase-p6 .s3-cb--3 { opacity: 1; }

/* ---- Beat 5 (Phase 7) · Punchline (Endframe) ----
   Freigelegt statt eingeblendet (Baustein 7, Feedback W-A): der Wipe
   (.fx-reveal) trägt jetzt den Haupteindruck, die Tiefe (.fx-depth) ist auf
   ein leichtes Rest-Maß zurückgenommen (war translateZ(-360px) scale(.6))
   und Opacity bleibt konstant 1 (kein Cross-Fade mehr) — beides per
   Phasen-Gate an Phase 7 gebunden (derselbe Grund wie bei der Doppelzeile
   oben). Der Gold-Punkt setzt eigenständig zuletzt, ~2 s nach der Landung
   (0,8 s Landung + 2 s Delay = 2,8 s ab Phasenbeginn), reiner
   Opacity-Übergang. */
.s3-punch-line { margin: 0; max-width: 18ch; font-size: clamp(30px, 4.6vw, 68px); text-wrap: balance; }
#s3 .headline-display.fx-depth { opacity: 1; transform: translateZ(-40px) scale(.97); transition: none; }
#s3.phase-p7 .headline-display.fx-depth {
  transform: translateZ(0) scale(1);
  transition: transform var(--motion-draw) var(--ease-out);
}
#s3 .headline-display.fx-reveal { clip-path: inset(-0.2em 100% -0.3em -0.1em); transition: none; }
#s3.phase-p7 .headline-display.fx-reveal {
  clip-path: inset(-0.2em -0.4em -0.3em -0.1em);
  transition: clip-path var(--motion-draw) var(--ease-out);
}
.s3-punch-line .gold-dot { opacity: 0; }
#s3.phase-p7 .s3-punch-line .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 2.8s;
}

/* Reduced Motion Szene 3: runPhases springt ohnehin sofort auf die letzte
   Phase (phase-p7, Punchline) — dieser Block sorgt zusätzlich dafür, dass
   keine der hier gesetzten Custom-Delays (Doppelzeile-Staffel, Gold-Punkt)
   das sofortige Stehen verzögert (Muster Szene 1 gespiegelt: kein Tippen,
   kein Zoom, kein Blur, keine Verzögerung). */
@media (prefers-reduced-motion: reduce) {
  #s3.phase-p3 .s3-double .fx-rise.d1,
  #s3.phase-p3 .s3-double .fx-rise.d3,
  #s3.phase-p7 .headline-display.fx-depth {
    transition-delay: 0s !important;
  }
  .s3-punch-line .gold-dot { opacity: 1 !important; transition: none !important; }
  .px-caret { display: none !important; }
}

/* ---------- Szene 4: Die Boeing-Akte ----------
   Ruhige Akten-Szene, bewusster Kontrast zum Bewegungs-Feuerwerk drumherum:
   keine Requisiten, kein Push-In. Die Eyebrow steht über den generischen
   .fx-fade-Trigger sofort; die drei Boeing-Zeilen bauen sich nacheinander auf
   und BLEIBEN stehen (kein Ersetzen) — dafür genügt eine normale, kumulative
   Spalte (kein exklusiver Beat-Wechsel wie bei Szene 1/3). Getaktet wird
   trotzdem über den generischen Beat-Dirigenten (data-phases → .phase-p1…p5),
   weil (a) die Punchline eine echte Phase braucht (Basiszustand aus, wie
   #s3.phase-p7 vorgemacht) und (b) das leichte Dimmen einer bereits gelandeten
   Zeile an den Start der jeweils NÄCHSTEN Phase gebunden ist. Die Fußnote ist
   echter Inhalt (kein aria-hidden), steht ab Phase 2 (erste Boeing-Zeile)
   dauerhaft klein am unteren Rand, oberhalb der HUD-Safe-Area (Muster wie
   .s1-explorer: bottom-clamp statt fixer px-Wert). Kein eigenes @keyframes,
   nur opacity-Übergänge (Akten-Ruhe). */
.s4-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Gaps und Schriftgrößen zusätzlich vh-gedeckelt: bei kleinen Viewport-
     Höhen schrumpft der Akten-Block mit, statt in die Fußnoten-Zone zu
     wachsen (Review-Fix, zusammen mit dem padding-bottom unten). */
  gap: clamp(28px, 6vh, 48px);
  width: 100%;
  max-width: min(820px, 88vw);
  /* Live-Feedback-Fix LF-2 (2026-07-16): lokaler Puffer ist wieder da. Task 3
     (Commit 514d084) hatte ihn eingeführt, die HUD-Schutzzonen-Konsolidierung
     (Commit 4de288f) hat ihn wieder gestrichen, weil die globale
     --hud-safe-Zone auf .scene für sich genommen ausreichend schien. Neuer
     Stresstest bei ~1100×650 (schmaler UND flacher als bisher geprüft) zeigt:
     Karte und Fußnote sind beide unabhängig voneinander bodenverankert
     (Karte zentriert in der Safe-Zone, Fußnote per eigenem bottom-Floor) —
     bei dieser Kombination schrumpft die Luft dazwischen auf ~18px runter.
     Derselbe Wert wie damals (48–80px, Muster .s1-explorer-Puffer) hebt den
     Akten-Block zusätzlich an und schafft wieder durchgängig sichtbaren
     Abstand, ohne die Fußnote selbst zu verschieben. */
  padding-bottom: clamp(48px, 8vh, 80px);
}
.s4-eyebrow { margin: 0; }

/* Akten-Karte (Feedback WB, Baustein 2): ruhige, dunkle Dossier-Fläche im
   Stil der bestehenden dunklen Requisiten (.s1-explorer-/.s5-card-Familie:
   --color-surface-raised-dark, --line-on-dark-default-Rand, --radius-lg,
   --shadow-xl). Materialisiert ruhig mit dem ersten Boeing-Beat (Phase 2,
   zeitgleich mit Zeile 1) — fx-fade-Charakter (reiner Opacity-Übergang,
   kein Push-In/Blur), bleibt danach durchgängig stehen. Trägt Kopfzeile +
   Zeilen + Punchline gemeinsam; Timing/fx-reveal der Punchline bleiben
   unverändert (eigene Phasen-Gates weiter unten). */
.s4-card {
  display: flex;
  flex-direction: column;
  /* vh-gedeckelt (Review-Fix, Muster .s4-wrap): bei flachen Fenstern (Test
     1280×700) schrumpft der Innenabstand mit, statt die Karte in die
     Fußnoten-Zone wachsen zu lassen — reine vw-Werte (wie bei .s5-card, dort
     unkritisch, weil nur eine kurze Zeile) reichen hier nicht, weil die
     Karte deutlich mehr Inhalt stapelt (Kopfzeile + 3 Zeilen + Punchline). */
  gap: clamp(14px, 3vh, 32px);
  width: 100%;
  padding: clamp(14px, 3vh, 40px) clamp(20px, 3.2vw, 44px);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  transition: none;
}
.s4.phase-p2 .s4-card,
.s4.phase-p3 .s4-card,
.s4.phase-p4 .s4-card,
.s4.phase-p5 .s4-card {
  opacity: 1;
  transition: opacity var(--motion-slow) var(--ease-out);
}

/* Kopfzeile: angedeutete Akten-Metadaten, kein echter Text (reine Deko,
   aria-hidden im HTML) — Skeleton-Balken im Muster des Szene-1-Explorers
   (.s1-sk-Basis: Höhe/Radius/Grundton kommen von dort, hier nur Breiten). */
.s4-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-bottom: clamp(12px, 2.4vh, 18px);
  border-bottom: 1px solid var(--line-on-dark-default);
}
.s4-sk--tag  { width: 56px; }
.s4-sk--date { width: 78px; background: var(--line-on-dark-strong); }
.s4-sk--id   { width: 42px; }

.s4-file {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 3vh, 24px);
  width: 100%;
}
.s4-line {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 500;
  font-size: clamp(20px, min(2.5vw, 3.6vh), 34px);
  line-height: 1.34;
  letter-spacing: -0.015em;
  color: var(--fg-default);
  text-wrap: balance;
  opacity: 0;
  transition: none;
}
/* Zeile 1 (Phase 2): landet, dimmt danach dauerhaft leicht. */
.s4.phase-p2 .s4-line--1 {
  opacity: 1;
  transition: opacity var(--motion-slow) var(--ease-out);
}
.s4.phase-p3 .s4-line--1,
.s4.phase-p4 .s4-line--1,
.s4.phase-p5 .s4-line--1 {
  opacity: .55;
  transition: opacity var(--motion-slow) var(--ease-out);
}
/* Zeile 2 (Phase 3): landet, dimmt danach dauerhaft leicht. */
.s4.phase-p3 .s4-line--2 {
  opacity: 1;
  transition: opacity var(--motion-slow) var(--ease-out);
}
.s4.phase-p4 .s4-line--2,
.s4.phase-p5 .s4-line--2 {
  opacity: .55;
  transition: opacity var(--motion-slow) var(--ease-out);
}
/* Zeile 3 (Phase 4): landet, dimmt zur Punchline hin nur leicht (jüngste Zeile). */
.s4.phase-p4 .s4-line--3 {
  opacity: 1;
  transition: opacity var(--motion-slow) var(--ease-out);
}
.s4.phase-p5 .s4-line--3 {
  opacity: .7;
  transition: opacity var(--motion-slow) var(--ease-out);
}

/* Punchline (Phase 5, Endframe): freigelegt statt eingeblendet (Baustein 7,
   Feedback W-A) — der Wipe (.fx-reveal) trägt den Haupteindruck, .fx-depth
   liefert nur noch eine leichte Rest-Tiefe (war translateZ(-360px) scale(.6)),
   Opacity bleibt konstant 1.
   Zwei Satz-Zeilen (Live-Feedback-Fix LF-1, 2026-07-16): vorher EIN <p> mit
   max-width:20ch + text-wrap:balance, das bei großen Fenstern dreizeilig
   MITTEN im Satz brach (20ch reichte für den 32-Zeichen-Satz 1 nicht). Jetzt
   Muster wie .s0-headline/.s0-line (Titelfolie) — je Satz ein eigenes <p>,
   dadurch bricht die Zeile immer an der Satzgrenze. Kein max-width mehr nötig,
   die Karte selbst deckelt die Breite (.s4-wrap). */
.s4-punch { margin: 0; }
.s4-punch-line { margin: 0; font-size: clamp(28px, min(4.2vw, 6vh), 60px); text-wrap: balance; }
#s4 .headline-display.fx-depth { opacity: 1; transform: translateZ(-40px) scale(.97); transition: none; }
#s4.phase-p5 .headline-display.fx-depth {
  transform: translateZ(0) scale(1);
  transition: transform var(--motion-draw) var(--ease-out);
}
#s4 .headline-display.fx-reveal { clip-path: inset(-0.2em 100% -0.3em -0.1em); transition: none; }
#s4.phase-p5 .headline-display.fx-reveal {
  clip-path: inset(-0.2em -0.4em -0.3em -0.1em);
  transition: clip-path var(--motion-draw) var(--ease-out);
}
.s4-punch-line .gold-dot { opacity: 0; }
#s4.phase-p5 .s4-punch-line .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 2.4s;
}

/* Fußnote: echter Inhalt, steht ab Phase 2 dauerhaft, dezente Fußnoten-Ebene.
   Härtung P4 (A11y): --fg-faint (42% auf Dunkel) lag bei 13px gegen den
   Bühnenhintergrund --color-surface-sunken-dark nur bei ~3,8:1 — unter dem
   WCAG-AA-Mindestwert 4,5:1 für Kleintext. Auf den dritten Wert der
   Dunkel-Leiter gehoben, --fg-soft (68%): rechnerisch ~7,7:1 gegen denselben
   Hintergrund, reicht deutlich — Rechnung im Härtungs-Report. */
.s4-footnote {
  position: absolute;
  left: 50%;
  bottom: clamp(110px, 11vh, 130px);
  transform: translateX(-50%);
  margin: 0;
  font-family: var(--font-body);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--fg-soft);
  opacity: 0;
  transition: none;
}
.s4.phase-p2 .s4-footnote,
.s4.phase-p3 .s4-footnote,
.s4.phase-p4 .s4-footnote,
.s4.phase-p5 .s4-footnote {
  opacity: 1;
  transition: opacity var(--motion-slow) var(--ease-out);
}

/* Reduced Motion: alle Boeing-Zeilen, die Fußnote und die Punchline stehen
   sofort voll lesbar — der generische Dirigent aktiviert unter reduced motion
   nur die LETZTE Phase (phase-p5); die harten !important-Overrides hier lösen
   sich bewusst von der Phasen-Kaskade, statt sich auf Zwischenphasen zu
   verlassen (Muster: Szene 3 macht dasselbe für Gold-Punkt/Punchline, hier
   zusätzlich auf die kumulativen Zeilen/Fußnote ausgeweitet, weil diese Szene
   anders als Szene 3 keinen exklusiven Beat-Wechsel nutzt, sondern alles
   dauerhaft nebeneinander stehen bleibt). */
@media (prefers-reduced-motion: reduce) {
  .s4-card, .s4-line, .s4-footnote { opacity: 1 !important; transition: none !important; }
  #s4 .headline-display.fx-depth { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s4-punch-line .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* ---------- Szene 5: Der Umbruch ----------
   Gewinner/Verlierer-Pendel (komplett neu, ersetzt die alten „Mechanismus"-
   Inhalte). Wie Szene 4 eine kumulative Spalte (kein exklusiver Beat-Wechsel):
   Intro (Beat 1+2) → Pendel (Bild A/B) → Punchline stehen normal untereinander,
   nicht als sich ablösende Vollbild-Beats — sonst müsste Reduced Motion (der
   Dirigent springt dort direkt auf die letzte Phase) zwangsläufig alles außer
   der Punchline verstecken. Getaktet über data-phases → .phase-p1…p5. Beat 1+2
   bekommen einen leichten Dauer-Push-In auf dem gemeinsamen .s5-intro-
   Container (Muster s1-zoom, aber szenen-generisch über transform gelöst);
   Beat 2 landet härter (kürzere Transition, kein sanftes Einschleichen). Das
   Pendel: zwei .s5-card-Flächen (dunkle Requisiten-Optik wie s1-search/
   -explorer, keine hellen Inseln) kommen nacheinander per .fx-depth-Optik aus
   der Tiefe; Bild A fällt beim Eintreffen von Bild B zurück (dim + blur,
   dokumentierte Paint-only-Ausnahme), Bild B bleibt stehen und färbt „beste
   Mitarbeiterin" per color-Transition teal (wie s1-hl). Punchline groß,
   Gold-Punkt setzt zuletzt. Kein eigenes @keyframes. */
/* Geister-Fenster (Feedback WB, Baustein 1): additive Rückkehr der Szene-1/
   Titelfolien-Requisiten (.s1-ghost-Basis liefert Form/Blur/Farbe, kein
   s1/s0-Change) — eigene Positions-/Deckkraft-Klassen mit Szene-5-Präfix.
   Deckkraft deutlich unter dem Text (Zielband .1–.18), z-index 0 (hinter dem
   .s5-wrap-Text, der im DOM danach folgt). Sehr langsames Driften: ein
   einziger Transform-Übergang über die volle Szenendauer (Muster: lange,
   lineare Übergänge wie .s1-zoom/.s5-intro), ausgelöst vom generischen
   .scene.entered-Trigger. Nur transform/opacity, kein neues @keyframes. */
.s5-ghosts { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.s5-ghost--a { width: 28%; height: 38%; top: 10%; left: 5%;  opacity: .13; transform: rotate(-2deg) translate(0, 0); }
.s5-ghost--b { width: 24%; height: 32%; top: 52%; right: 6%; opacity: .10; transform: rotate(3deg) translate(0, 0); }
#s5.scene.entered .s5-ghost--a {
  transform: rotate(-2deg) translate(-1.5%, 2%);
  transition: transform 17000ms linear;
}
#s5.scene.entered .s5-ghost--b {
  transform: rotate(3deg) translate(1.5%, -2%);
  transition: transform 17000ms linear;
}
@media (prefers-reduced-motion: reduce) {
  .s5-ghost--a, .s5-ghost--b,
  #s5.scene.entered .s5-ghost--a, #s5.scene.entered .s5-ghost--b {
    transform: none !important;
    transition: none !important;
  }
}

.s5-wrap {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2xl);
  width: 100%;
  max-width: min(860px, 90vw);
}
.s5-intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  transform: scale(1);
  transition: none;
}
.s5.phase-p1 .s5-intro { transform: scale(1.025); transition: transform 2600ms linear; }
.s5.phase-p2 .s5-intro,
.s5.phase-p3 .s5-intro,
.s5.phase-p4 .s5-intro,
.s5.phase-p5 .s5-intro { transform: scale(1.06); transition: transform 2200ms linear; }

.s5-line {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  color: var(--fg-default);
  text-wrap: balance;
  opacity: 0;
  transform: translateY(var(--reveal-distance));
  transition: none;
}
.s5-line--1 { font-size: clamp(22px, 2.8vw, 40px); line-height: 1.28; letter-spacing: -0.02em; max-width: 32ch; }
.s5-line--2 { font-size: clamp(26px, 3.4vw, 50px); line-height: 1.16; letter-spacing: -0.025em; max-width: 20ch; }

.s5.phase-p1 .s5-line--1 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s5.phase-p2 .s5-line--1,
.s5.phase-p3 .s5-line--1,
.s5.phase-p4 .s5-line--1,
.s5.phase-p5 .s5-line--1 {
  opacity: .6;
  transform: translateY(0);
  transition: opacity var(--motion-slow) var(--ease-out);
}
/* Beat 2 landet härter: kürzere Transition, kein sanftes Einschleichen. */
.s5.phase-p2 .s5-line--2 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}
.s5.phase-p3 .s5-line--2,
.s5.phase-p4 .s5-line--2,
.s5.phase-p5 .s5-line--2 {
  opacity: .6;
  transform: translateY(0);
  transition: opacity var(--motion-slow) var(--ease-out);
}
.s5.phase-p5 .s5-line--1,
.s5.phase-p5 .s5-line--2 { opacity: .4; }

/* ---- Pendel: zwei dunkle Karten an derselben Stelle ---- */
.s5-pendulum {
  position: relative;
  width: 100%;
  min-height: clamp(150px, 21vh, 230px);
}
.s5-card {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(640px, 86vw);
  padding: clamp(22px, 3.2vw, 42px) clamp(24px, 3.6vw, 52px);
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  transform: translate(-50%, -50%) translateZ(-360px) scale(.6);
  transition: none;
}
.s5-card-text {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(19px, 2.3vw, 30px);
  line-height: 1.32;
  letter-spacing: -0.018em;
  color: var(--fg-default);
  text-align: center;
  text-wrap: balance;
}
.s5-card--a { z-index: 1; }
/* Fix F-B (Baseline-Sprung beim Teal-Umfärben, Feedback LF-3): Playwright-
   Messung (getAnimations/currentTime-Scrub + Pixel-Analyse der gerenderten
   Screenshots) zeigt: getBoundingClientRect von .s5-hl bleibt während der
   ganzen Farb-Transition exakt gleich (Layout wackelt nicht) — der Sprung ist
   ein reiner Compositing-Effekt von Chromium. Ursache eingegrenzt: .s5-card--b
   erhält seine 3D-Einflug-Optik (translateZ/scale) über eine ECHTE
   transform-Transition (Beat: Karte kommt aus der Tiefe). Wird diese Ebene
   erst MIT dem Phasenwechsel neu promotet (statt von Anfang an zu bestehen),
   rastert Chromium den Text von .s5-hl beim späteren Farbwechsel cream→teal
   messbar ~1px höher (bestätigt bei 1280×800 und 1900×950). will-change
   promotet die Ebene bereits im Ruhezustand, bevor der Beat startet, und
   entschärft damit den Effekt, ohne Transition/Timing/Optik der Karte
   anzufassen — rein malend, keine neue Bewegung, kein Layout-Einfluss. */
.s5-card--b { z-index: 2; will-change: transform; }

.s5.phase-p3 .s5-card--a {
  opacity: 1;
  transform: translate(-50%, -50%) translateZ(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-draw) var(--ease-out), transform var(--motion-draw) var(--ease-out), filter var(--motion-draw) var(--ease-out);
}
.s5.phase-p4 .s5-card--a,
.s5.phase-p5 .s5-card--a {
  opacity: .3;
  transform: translate(-50%, -50%) translateZ(-160px) scale(.86);
  filter: blur(5px);
  transition: opacity var(--motion-slow) var(--ease-in), transform var(--motion-slow) var(--ease-in), filter var(--motion-slow) var(--ease-in);
}
.s5.phase-p4 .s5-card--b,
.s5.phase-p5 .s5-card--b {
  opacity: 1;
  transform: translate(-50%, -50%) translateZ(0) scale(1);
  filter: blur(0);
  transition: opacity var(--motion-draw) var(--ease-out), transform var(--motion-draw) var(--ease-out), filter var(--motion-draw) var(--ease-out);
}
.s5-hl { white-space: nowrap; color: var(--fg-default); }
.s5.phase-p4 .s5-card--b .s5-hl,
.s5.phase-p5 .s5-card--b .s5-hl {
  color: var(--color-brand-teal);
  transition: color var(--motion-reveal) var(--ease-out) 1200ms;
}

/* Punchline (Phase 5, Endframe): freigelegt statt eingeblendet (Baustein 7,
   Feedback W-A) — der Wipe (.fx-reveal) trägt den Haupteindruck, .fx-depth
   liefert nur noch eine leichte Rest-Tiefe (war translateZ(-360px) scale(.6)),
   Opacity bleibt konstant 1. */
.s5-punch-line { margin: 0; max-width: 20ch; font-size: clamp(30px, 4.4vw, 64px); text-wrap: balance; }
#s5 .headline-display.fx-depth { opacity: 1; transform: translateZ(-40px) scale(.97); transition: none; }
#s5.phase-p5 .headline-display.fx-depth {
  transform: translateZ(0) scale(1);
  transition: transform var(--motion-draw) var(--ease-out);
}
#s5 .headline-display.fx-reveal { clip-path: inset(-0.2em 100% -0.3em -0.1em); transition: none; }
#s5.phase-p5 .headline-display.fx-reveal {
  clip-path: inset(-0.2em -0.4em -0.3em -0.1em);
  transition: clip-path var(--motion-draw) var(--ease-out);
}
.s5-punch-line .gold-dot { opacity: 0; }
#s5.phase-p5 .s5-punch-line .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 2.4s;
}

/* Reduced Motion: Intro-Zeilen, Pendel-Endzustand (Bild A gefallen, Bild B
   teal) und Punchline stehen alle sofort — dieselbe Begründung wie bei
   Szene 4 (der Dirigent aktiviert unter reduced motion nur phase-p5). */
@media (prefers-reduced-motion: reduce) {
  .s5-intro { transform: none !important; transition: none !important; }
  .s5-line { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s5-card--a {
    opacity: .3 !important;
    transform: translate(-50%, -50%) scale(.86) !important;
    filter: blur(5px) !important;
    transition: none !important;
  }
  .s5-card--b {
    opacity: 1 !important;
    transform: translate(-50%, -50%) scale(1) !important;
    filter: none !important;
    transition: none !important;
  }
  .s5-card--b .s5-hl { color: var(--color-brand-teal) !important; transition: none !important; }
  #s5 .headline-display.fx-depth { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s5-punch-line .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* ---------- Szene 6: Die Einarbeitung ----------
   Eyebrow, darunter die neue Headline, darunter drei gleich breite
   Stationskarten (mobil gestapelt), die per .fx-rise .d1/.d3/.d5
   nacheinander auftreten, darunter die Abschlusszeile. */
.s6-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* vh-gedeckelt (Feedback WC, Review-Fix): die Spalte trägt seit Baustein 3
     ein zusätzliches Explorer-Requisit, darum darf der großzügige
     var(--space-2xl)-Fixwert bei flachen Fenstern (1280×700) nicht mehr
     stehen bleiben — sonst wandert die Abschlusszeile unter die HUD-Leiste
     (Muster .s4-wrap/.s7 Staffel-Reasserts: bei großen Fenstern unverändert
     48px, bei kleinen Höhen schrumpft nur der Abstand, nie der Inhalt).
     Task W-A: fünf statt vier Kinder (neu .s6-why) bedeuten einen vierten
     statt dritten Gap in derselben Spalte — der vh-Koeffizient ist deshalb
     etwas enger gefasst (5vh → 4vh) als vor dem Warum-Beat, sonst reicht die
     Höhe selbst bei 1280×800 nicht mehr (gemessen). */
  gap: clamp(12px, 2.6vh, 30px);
  width: 100%;
  max-width: min(1100px, 94vw);
  text-align: center;
}
.s6-eyebrow { margin: 0; }
.s6-headline { margin: 0; max-width: 22ch; font-size: clamp(30px, 3.4vw, 50px); }
.s6-stations {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  width: 100%;
}
.s6-station {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-xl);
  text-align: left;
  background: var(--color-surface-raised-dark);
  border: 1px solid var(--line-on-dark-default);
  border-radius: var(--radius-lg);
}
.s6-num {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1;
  color: var(--color-brand-teal);
  letter-spacing: -0.02em;
}
.s6-station-h {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(20px, 1.9vw, 27px);
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: var(--fg-default);
}
.s6-station-p {
  margin: 0;
  font-family: var(--font-body);
  font-size: clamp(15px, 1.15vw, 18px);
  line-height: 1.5;
  color: var(--fg-muted);
  text-wrap: pretty;
}
@media (max-width: 820px) {
  .s6-stations { grid-template-columns: 1fr; }
}

/* Staffel-Verzögerungen der Welle-2-Szenen. Die generischen .d-Klassen allein
   greifen bei .fx-rise nicht: der Vokabular-Selektor .scene.entered .fx-rise
   setzt die transition-Kurzform (und damit transition-delay auf 0) und gewinnt
   per Spezifität gegen die einfachen .d*-Klassen. Darum hier szenen-eigene,
   ID-spezifische transition-delays (vom Plan ausdrücklich erlaubt) passend zur
   .d-Leiter (0,15 s je Stufe), damit die Kernsätze bzw. Stationen tatsächlich
   nacheinander auftreten. Kein neues Keyframe, weiterhin nur opacity/transform.
   Reduced Motion fängt der generische !important-Override des Vokabulars
   (.scene.entered .fx-rise) weiterhin ab (Delay → 0, ruhige Blende). */
#s6.scene.entered .fx-rise.d3 { transition: opacity var(--motion-reveal) var(--ease-out) .3s,  transform var(--motion-reveal) var(--ease-out) .3s; }
#s6.scene.entered .fx-rise.d5 { transition: opacity var(--motion-reveal) var(--ease-out) .6s,  transform var(--motion-reveal) var(--ease-out) .6s; }

/* „Aktive Karte im Fokus, vorige dimmt LEICHT": statische Opacity-Abstufung
   je Station (kein Zwei-Phasen-Dimmwechsel, kein Phasen-Dirigent nötig - die
   Szene akkumuliert nur, nichts verschwindet). Nur die Opacity-LONGHAND wird
   hier neu gesetzt (ID-Spezifität gewinnt gegen die 3-Klassen-Basisregel
   .scene.entered .fx-rise), Timing/Kurve bleiben unberührt aus dem
   Vokabular bzw. den d3/d5-Reasserts oben. Station 03 bleibt bei 1 (kein
   Override nötig). Kontrast bleibt ausreichend, alles lesbar. */
#s6.scene.entered .s6-station:nth-child(1) { opacity: .8; }
#s6.scene.entered .s6-station:nth-child(2) { opacity: .92; }

.s6-close {
  margin: 0;
  max-width: 46ch;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(22px, 2.6vw, 34px);
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--fg-default);
  text-wrap: balance;
}
/* Abschlusszeile: kam bis Task W-A über einen festen .scene.entered-Delay
   (1,8s). Seit dem Warum-Beat (.s6-why, zwei neue Phasen p4/p5 dazwischen)
   ist ein fester Delay ab Szeneneintritt nicht mehr zuverlässig NACH der
   Punchline — die Zeile hängt jetzt stattdessen am Phasen-Gate (.phase-p6),
   siehe Reassert weiter unten beim Warum-Beat-Block. */

/* Feedback WC (Baustein 3): Stationen-Reihe + Explorer-Requisit gemeinsam in
   einer Spalte mit eigenem, knappen vh-gedeckelten Gap (deutlich enger als
   das äußere .s6-wrap-Gap) — hält den Zusatzblock bei flachen Fenstern
   (1280×700) kompakt. */
.s6-mid {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  gap: clamp(8px, 1.6vh, 20px);
}

/* Warum-Beat (Task W-A, Wissens-Welle): O-Ton-Zeile + Punchline zwischen
   Stationen-Reihe und Abschlusszeile. Eigene, knapp vh-gedeckelte Spalte
   (Muster #s4: font-size über clamp(min, min(vw, vh), max), damit Zeile UND
   Schriftgröße bei flachen Fenstern zusammen mitschrumpfen, statt nur über
   einen separaten Height-Breakpoint nachzuregeln) — Platz-Risiko (Szene war
   bei 1280×700 schon eng, siehe Ledger Feedback-WC). */
.s6-why {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(4px, 1.2vh, 12px);
  width: 100%;
}
/* O-Ton: Zitat-Optik (kursiv, gedämpft), kleiner als die Punchline, orientiert
   an der Zitat-Zeile von Szene 8 (.s8-close) — hier aber ohne jeden Akzent
   (Ein-Akzent-pro-Zeile-Regel, der Gold-Punkt sitzt allein auf der
   Punchline). */
.s6-oton {
  margin: 0;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(14px, min(1.3vw, 2.6vh), 18px);
  line-height: 1.45;
  color: var(--fg-muted);
  text-wrap: pretty;
}
/* Punchline: Größenordnung headline-h3 (NICHT display-groß, die Szene hat
   oben schon ihre Display-Headline). */
.s6-punch {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(21px, min(2.6vw, 4.6vh), 32px);
  line-height: 1.26;
  letter-spacing: -0.015em;
  color: var(--fg-default);
  text-wrap: balance;
}

/* Explorer-Requisit Szene 6: additive Instanz über der .px-explorer-
   Basisregel (Task 7/Szene 1), identische Optik, Größe/Position auf die
   Mini-Ausgabe im normalen Fluss umgeschrieben (Muster .s12-gag: kein
   Absolut-Anker, darum keine eigene Safe-Area-Rechnung nötig). Das Fenster
   selbst steht als ruhige Deko von Szenenbeginn an (kein eigenes
   Phasen-Gate, kein erfundener Inhalt); nur die sechs Zeilen darin füllen
   sich gruppenweise (siehe Beat-Dirigent-Regeln unten). Innenabstände/Icon
   zusätzlich vh-gedeckelt und knapper als die Szene-1/12-Vorlage (Review-Fix
   WC: die Stationen-Karten allein sind bereits fast raumfüllend, das
   zusätzliche Requisit darf bei 1280×700 nicht in die Abschlusszeile/HUD
   wachsen). Task W-B: sechs statt drei Zeilen bei unverändertem Platzbudget
   (seit Task W-A zusätzlich der Warum-Beat dazwischen) — Zeile/Icon/Innen-
   abstände hier nochmals enger gefasst als die ursprüngliche Drei-Zeilen-
   Fassung, sonst sprengt allein die verdoppelte Zeilenzahl die Höhe. */
.s6-explorer-slot { display: flex; justify-content: center; width: 100%; }
.s6-explorer-slot .px-explorer {
  position: static;
  width: min(280px, 58vw);
  transform: none;
  filter: none;
}
#s6.scene.entered .s6-explorer-slot .px-explorer { opacity: 1; }
.s6-explorer-slot .px-explorer-bar { padding: clamp(2px, .5vh, 4px) var(--space-sm); }
.s6-explorer-slot .px-folder { width: 13px; height: 13px; }
.s6-explorer-slot .px-explorer-body {
  padding: clamp(2px, .4vh, 4px) var(--space-sm) clamp(2px, .4vh, 4px);
  gap: clamp(1px, .35vh, 3px);
}
.s6-explorer-slot .px-filerow { padding: clamp(1px, .3vh, 3px) var(--space-sm); }
.s6-explorer-slot .px-file-ico { width: 11px; height: 12px; }
/* Zeilentext (Task W-B, ersetzt die vorigen .s1-sk-Skeleton-Balken): dezente
   Mono-Schrift auf muted-Ebene, orientiert an der Typo-Ebene des
   Szene-12-Gags (.s12-gag-filename), aber gedämpfter (fg-muted statt
   fg-default) — die Requisite bleibt der Bühne untergeordnet. Alle sechs
   Begriffe sind kurze Einzelwörter, darum bewusst einzeilig (kein Umbruch
   nötig wie beim langen Dateinamen in Szene 12). Review-Fix W-B: harte
   Untergrenze 10px in ALLEN Breakpoints (Szene-12-Niveau,
   .s12-gag-filename = 10px) — „lesbar" aus dem Brief ist bindend, der
   Höhenausgleich läuft über Icon/Padding/Gap, nie über die Schrift. */
.s6-file-name {
  font-family: var(--font-mono);
  font-size: clamp(10px, min(.95vw, 1.7vh), 11px);
  line-height: 1;
  color: var(--fg-muted);
  white-space: nowrap;
}

/* Unter ~1100px Fensterbreite entfällt das Requisit vollständig — die Szene
   trägt sich allein über die drei Stationen, kein Mangel ohne Explorer. */
@media (max-width: 1100px) {
  .s6-explorer-slot { display: none; }
}

/* Sehr flache Fenster (Review-Befund WC): der Height-Breakpoint ist das
   Gegenstück zum Width-Breakpoint oben. Bei ≤760px Höhe verbrauchte die
   Szene sonst fast die komplette globale HUD-Safe-Area (nur ~12px Restluft
   bei 1280×700 — bei realem Browser-Chrome, Zoom ≠ 100% oder Rundungen
   kippt so eine Marge ins Negative). Das Requisit schrumpft hier deutlich
   (Mini-Miniatur, bleibt aber als Story-Element erhalten), zusätzlich
   werden nur die szenen-eigenen Gaps enger gedeckelt — Wortlaut, Timing
   und Stationskarten bleiben unberührt. Ziel-Restluft ≥30px bei 1280×700.
   Task W-A (Warum-Beat): fünfte Spalten-Zeile, darum ein zusätzlicher Gap in
   derselben Spalte — Wrap-/Mid-Gap hier nochmals enger als vor dem
   Warum-Beat, plus ein eigener knapper Gap für .s6-why, gemessen nachgezogen
   auf dieselbe ≥30px-Zielmarge. Schwelle bei dieser Gelegenheit von 760px auf
   820px angehoben (gemessen): bei ≤800px Höhe (Pflicht-Testpunkt 1280×800)
   griff die Basisformel allein sonst noch nicht früh genug, die Marge fiel
   knapp über der alten Schwelle (761px) auf ~18px statt der angestrebten
   ≥30px — jetzt deckt derselbe enge Block beide Pflicht-Testpunkte (1280×700
   und 1280×800) durchgängig ab, kein Sprung mehr dazwischen.
   Task W-B (gemessen): sechs statt drei Explorer-Zeilen brauchen hier
   nochmals engere Werte als die Drei-Zeilen-Fassung (Icon/Zeilenpadding/Gap
   weiter reduziert, Zeilentext zusätzlich vh-gedeckelt) — sonst frisst allein
   die verdoppelte Zeilenzahl die zuvor erreichte ≥30px-Marge bei 1280×700
   wieder auf. */
@media (max-height: 820px) {
  #s6 .s6-wrap { gap: clamp(8px, 1.6vh, 14px); }
  #s6 .s6-mid { gap: clamp(3px, 0.8vh, 8px); }
  #s6 .s6-why { gap: clamp(2px, 0.6vh, 6px); }
  /* O-Ton/Punchline zusätzlich vh-gedeckelt enger (der vw-Term allein hält
     die Punchline sonst bei ihrer Obergrenze fest, siehe .s6-punch oben) —
     nötig, um die ≥30px-Zielmarge bei 1280×700 zu erreichen. */
  .s6-oton { font-size: clamp(13px, min(1.3vw, 2.2vh), 16px); }
  .s6-punch { font-size: clamp(19px, min(2.6vw, 3.6vh), 26px); }
  .s6-explorer-slot .px-explorer { width: min(240px, 52vw); }
  .s6-explorer-slot .px-explorer-bar { padding: 1px var(--space-sm); }
  .s6-explorer-slot .px-folder { width: 10px; height: 10px; }
  .s6-explorer-slot .px-explorer-body { padding: 1px var(--space-sm); gap: 1px; }
  .s6-explorer-slot .px-filerow { padding: 1px var(--space-sm); }
  .s6-explorer-slot .px-file-ico { width: 8px; height: 9px; }
  /* Review-Fix W-B: fest 10px statt clamp(8px…9px) — die Lesbarkeits-
     Untergrenze (Szene-12-Niveau) gilt auch am Pflicht-Testpunkt 1280×700.
     Der Höhenzuwachs (+1px je Zeile) wird nicht kompensiert: Icon, Zeilen-
     padding und Gap stehen hier bereits auf ihrem Minimum (1px/8×9px), und
     die gemessene Marge zur HUD trägt den Zuwachs (bindend ist nur: kein
     Overlap, keine Safe-Area-Verletzung). */
  .s6-file-name { font-size: 10px; }
}

/* Zeilen-Choreografie (Task W-B, ersetzt die vorige Ein-Zeile-je-Phase-
   Fassung): sechs statt drei Zeilen, neu in zwei Dreier-Gruppen an die
   Stationen gekoppelt — Zeilen 1–3 (Prozesse/Entscheidungen/Zuständigkeiten)
   kommen gestaffelt MIT Phase p2 (Station „Wissen erheben"), Zeilen 4–6
   (Playbooks/Begriffe/Systeme) ebenso gestaffelt MIT Phase p3 (Station
   „Anwenden") — der generische Beat-Dirigent setzt data-phases → .phase-p1…p6
   (#s6 oben). Innerhalb jeder Gruppe kleine Versätze (0/.15/.3s, dieselbe
   0,15s-Stufe wie das .d-Vokabular) direkt als transition-delay im
   ID-Selektor, weil die generischen .dN-Klassen hier wegen geringerer
   Spezifität nicht gegen die ID-Regel gewinnen würden (Muster wie
   #s6.scene.entered .fx-rise.d3/d5 oben). Muster wie .s9-wall-name: jede
   Zeile bleibt ab ihrer Phase in allen Folgephasen sichtbar (kumulativ,
   nichts verschwindet), die Reveal-Transition hängt nur an der jeweils
   EIGENEN ersten Phase, damit spätere Phasenwechsel sie nicht erneut
   animieren. */
.s6-explorer-row { opacity: 0; transform: translateY(8px); transition: none; }
#s6.phase-p2 .s6-explorer-row--1,
#s6.phase-p3 .s6-explorer-row--1,
#s6.phase-p4 .s6-explorer-row--1,
#s6.phase-p5 .s6-explorer-row--1,
#s6.phase-p6 .s6-explorer-row--1 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p2 .s6-explorer-row--1 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
#s6.phase-p2 .s6-explorer-row--2,
#s6.phase-p3 .s6-explorer-row--2,
#s6.phase-p4 .s6-explorer-row--2,
#s6.phase-p5 .s6-explorer-row--2,
#s6.phase-p6 .s6-explorer-row--2 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p2 .s6-explorer-row--2 {
  transition: opacity var(--motion-reveal) var(--ease-out) .15s, transform var(--motion-reveal) var(--ease-out) .15s;
}
#s6.phase-p2 .s6-explorer-row--3,
#s6.phase-p3 .s6-explorer-row--3,
#s6.phase-p4 .s6-explorer-row--3,
#s6.phase-p5 .s6-explorer-row--3,
#s6.phase-p6 .s6-explorer-row--3 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p2 .s6-explorer-row--3 {
  transition: opacity var(--motion-reveal) var(--ease-out) .3s, transform var(--motion-reveal) var(--ease-out) .3s;
}
#s6.phase-p3 .s6-explorer-row--4,
#s6.phase-p4 .s6-explorer-row--4,
#s6.phase-p5 .s6-explorer-row--4,
#s6.phase-p6 .s6-explorer-row--4 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p3 .s6-explorer-row--4 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
#s6.phase-p3 .s6-explorer-row--5,
#s6.phase-p4 .s6-explorer-row--5,
#s6.phase-p5 .s6-explorer-row--5,
#s6.phase-p6 .s6-explorer-row--5 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p3 .s6-explorer-row--5 {
  transition: opacity var(--motion-reveal) var(--ease-out) .15s, transform var(--motion-reveal) var(--ease-out) .15s;
}
#s6.phase-p3 .s6-explorer-row--6,
#s6.phase-p4 .s6-explorer-row--6,
#s6.phase-p5 .s6-explorer-row--6,
#s6.phase-p6 .s6-explorer-row--6 {
  opacity: 1;
  transform: translateY(0);
}
#s6.phase-p3 .s6-explorer-row--6 {
  transition: opacity var(--motion-reveal) var(--ease-out) .3s, transform var(--motion-reveal) var(--ease-out) .3s;
}

/* Fokus-Wechsel (Task F-C, Stefan-Live-Feedback LF-4: Szene zeigte am Ende zu
   viel Text gleichzeitig, besonders auf kleinen Bildschirmen): ab Phase p4
   gehört die Bühne dem Warum-Beat — Stationen-Reihe UND Explorer-Fenster
   dimmen gemeinsam auf eine deutlich zurückgenommene Stufe, nichts verschwindet,
   kein Layout ändert sich. .s6-mid ist ihr gemeinsamer Wrapper (enthält nur
   .s6-stations + .s6-explorer-slot) — Headline/Eyebrow/Warum-Block/
   Abschlusszeile liegen als Geschwister außerhalb in .s6-wrap und bleiben
   unberührt, ein einziges Rule deckt beide im Brief genannten Dimm-Ziele ab.
   Wert .4 (Technik am Bestand orientiert: die statische Stationen-Abstufung
   oben, hier deutlich weiter zurückgenommen wie gefordert) — multipliziert
   sich mit der bestehenden .8/.92-Abstufung der Karten 1/2 zu ~.32/~.37,
   bleibt damit durchgängig in der geforderten Größenordnung ~0.3–0.4. Nur die
   Opacity-Longhand, kumulative Selektor-Kette (Muster wie die
   Explorer-Zeilen/der O-Ton-Block hier im Umfeld), weil der Beat-Dirigent
   exklusiv je eine phase-Klasse setzt. Einheitlich auf allen Viewports, kein
   Breakpoint. @media screen: Druck bleibt ausdrücklich unbeeinflusst (ALLES
   sichtbar, keine Dimmung) — screen-only macht das unabhängig vom
   DOM-Klassenzustand robust (z. B. Druck-Emulation ohne Neuladen), statt sich
   allein auf „im Druck nie gesetzt" zu verlassen. Reduced-Motion-Pendant
   (RM landet direkt auf phase-p6, siehe runPhases in pitch.js) eigens
   gekapselt in @media screen and (prefers-reduced-motion: reduce) weiter
   unten bei den übrigen RM-Regeln der Szene. */
@media screen {
  #s6.phase-p4 .s6-mid,
  #s6.phase-p5 .s6-mid,
  #s6.phase-p6 .s6-mid {
    opacity: .4;
    transition: opacity var(--motion-reveal) var(--ease-out);
  }
}

/* Warum-Beat (Task W-A): O-Ton (Phase 4) und Punchline (Phase 5), getaktet
   über denselben generischen Beat-Dirigenten wie der Explorer oben. Beide
   Reasserts folgen dem etablierten Phasen-Gate-Muster (ID-Selektor schlägt
   die generische .scene.entered-Vokabular-Regel per Spezifität), Muster wie
   #s8 .headline-display.fx-depth. Kumulativ: einmal sichtbar, bleibt
   stehen (nichts dimmt weg). */
#s6 .s6-oton.fx-fade { opacity: 0; transition: none; }
#s6.phase-p4 .s6-oton.fx-fade,
#s6.phase-p5 .s6-oton.fx-fade,
#s6.phase-p6 .s6-oton.fx-fade {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}

#s6 .s6-punch.fx-depth { opacity: 0; transform: translateZ(-360px) scale(.6); transition: none; }
#s6.phase-p5 .s6-punch.fx-depth,
#s6.phase-p6 .s6-punch.fx-depth {
  opacity: 1;
  transform: translateZ(0) scale(1);
  transition: opacity var(--motion-draw) var(--ease-out),
              transform var(--motion-draw) var(--ease-out);
}
/* Gold-Punkt setzt zuletzt ein — etabliertes Muster wie .s8-close .gold-dot
   (eigener, weiter verzögerter Opacity-Übergang nach der Punchline-Landung). */
.s6-punch .gold-dot { opacity: 0; }
#s6.phase-p5 .s6-punch .gold-dot,
#s6.phase-p6 .s6-punch .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1s;
}

/* Abschlusszeile (Phase 6): läuft seit Task W-A über das Phasen-Gate statt
   über einen festen .scene.entered-Delay, siehe Kommentar weiter oben bei
   der alten Regel. */
#s6 .s6-close.fx-fade { opacity: 0; transition: none; }
#s6.phase-p6 .s6-close.fx-fade {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}

/* Reduced Motion: Fenster + alle sechs Zeilen stehen sofort komplett gefüllt
   (kein Materialisieren, keine Transform-Bewegung) — konsistent mit „Endbild
   sofort lesbar" wie im Rest des Decks (der Dirigent aktiviert unter
   reduced motion ohnehin sofort die letzte Phase, phase-p6, siehe
   pitch.js runPhases). Warum-Beat + Abschlusszeile (inkl. Gold-Punkt) stehen
   hier zusätzlich auf ihrem Endzustand, dieselbe Begründung wie bei Szene 8. */
@media (prefers-reduced-motion: reduce) {
  .s6-explorer-slot .px-explorer { opacity: 1 !important; }
  .s6-explorer-row { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s6-oton, .s6-punch, .s6-close {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .s6-punch .gold-dot { opacity: 1 !important; transition: none !important; }
}
/* Task F-C: Fokus-Wechsel-Dimmung (.s6-mid oben) steht unter Reduced Motion
   ebenfalls sofort — RM landet direkt auf phase-p6, siehe pitch.js
   runPhases. Eigens in „screen and (prefers-reduced-motion: reduce)" gekapselt
   statt im obigen Block: die Dimmung selbst muss (anders als Oton/Punchline/
   Abschluss, die im Druck ohnehin voll sichtbar sein sollen) im Druck immer
   unwirksam bleiben, auch wenn eine Druck-Emulation zufällig mit aktiver
   Reduced-Motion-Systemeinstellung zusammenfällt — !important nur, damit die
   Transitionskappung unabhängig von der Regelreihenfolge sicher gewinnt. */
@media screen and (prefers-reduced-motion: reduce) {
  #s6.phase-p6 .s6-mid { opacity: .4 !important; transition: none !important; }
}

/* ============================================================================
   WELLE 3 — Szenen-Layouts (Szene 7 Säulen, 8 Sie liefert, 9 Was ich mitbringe).
   Nur Layout + Timing. Bewegung stammt komplett aus dem .fx-*-Vokabular oben;
   keine Szene erfindet eigene Keyframes. Animiert wird ausschließlich
   transform/opacity (feste Layout-Boxen). Farben/Fonts nur über var(--…)-
   Tokens aus colors_and_type.css. Reduced-Motion greift über die bestehende
   gebündelte Media-Query oben (alle .fx-* → .fx-fade).
   ============================================================================ */

/* ---------- Szene 7: Der Ausbildungsplan ----------
   Eyebrow oben, darunter drei gleich breite Karten (mobil gestapelt). Je
   Karte kommt der Titel mit der Karte selbst (.fx-rise .d1/.d3/.d5, wie
   bisher), der Satz folgt mit kleinem Versatz (.fx-fade .d2/.d4/.d6 direkt
   am Absatz) — beides bestehendes Vokabular, kein neues Keyframe. Die
   Karten sind helle Inseln auf der dunklen Bühne: colors_and_type.css kennt
   nur [data-theme="dark"] als Overlay-Ebene auf :root, aber KEIN
   [data-theme="light"]-Reset zurück auf hell (geprüft — es existiert keine
   solche Regel). Ohne Gegenmaßnahme würde --fg-default/--color-surface-card
   hier die geerbten Dunkel-Werte des body[data-theme="dark"] behalten
   (Cream-auf-Cream). Der Block unten reasserted deshalb lokal, nur für die
   Karten-Insel, exakt dieselben :root-Werte (keine neuen Farben) — ein
   Pendant zu einem fehlenden [data-theme="light"]-Reset, aber im
   pitch-eigenen Layout-Scope statt in der gemeinsamen Token-Datei. */
.s7-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xl);
  width: 100%;
  max-width: min(1100px, 94vw);
  text-align: center;
}
.s7-eyebrow { margin: 0; }
.s7-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  width: 100%;
}
.s7-cards[data-theme="light"] {
  --color-surface-card: oklch(98.0% 0.004 80);
  --fg-default: #18273A;
  --fg-muted: color-mix(in oklab, #18273A 78%, transparent);
  --line-default: color-mix(in oklab, #18273A 12%, transparent);
}
.s7-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-xl);
  text-align: left;
  background: var(--color-surface-card);
  border: 1px solid var(--line-default);
  border-radius: var(--radius-lg);
}
.s7-card-h {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(19px, 1.9vw, 26px);
  line-height: 1.22;
  letter-spacing: -0.015em;
  color: var(--fg-default);
}
.s7-card-p {
  margin: 0;
  font-family: var(--font-body);
  font-size: clamp(14.5px, 1.1vw, 17px);
  line-height: 1.55;
  color: var(--fg-muted);
  text-wrap: pretty;
}
@media (max-width: 820px) {
  .s7-cards { grid-template-columns: 1fr; }
}

/* ---------- Szene 8: Sie liefert (zweiter Bam-Moment, D4-Beweis) ----------
   video-stage-Hülle wie Szene 1 (Inhaltsebene später durch <video> ersetzbar).
   Kumulative Spalte wie Szene 4/5 (kein exklusiver Beat-Wechsel; jeder Beat
   kommt dazu und bleibt stehen), getaktet über den generischen
   Beat-Dirigenten (data-phases → .phase-p1…p6, Feedback F5). Beat 1
   (Eyebrow + Quelle) läuft weiter über das generische
   .fx-rise/.scene.entered-Vokabular, ohne Phasen-Gate. Der Wandel-Moment ist
   EIN vollständiger Satz („Aus mehreren Tagen werden wenige Stunden"), auf
   zwei Beats gestaffelt statt eines Pendels: Beat 3 „Aus mehreren Tagen"
   (.s8-before) erscheint ruhig (.fx-fade-Charakter) und bleibt danach
   dauerhaft voll sichtbar stehen — anders als das Pendel in Szene 5 dimmt
   hier nichts weg, der ganze Satz muss am Ende lesbar sein. Beat 4, mit
   eigenem Dwell (≥ 1,2 s) versetzt, lässt „werden wenige Stunden" (.s8-after)
   per .fx-depth aus der Tiefe landen, Teal-Akzent nur auf „wenige Stunden"
   (.s8-hl). */

/* Feedback WD (Baustein 4): echtes D4-Projektfoto als gedimmte Bühne INNERHALB
   der video-stage-Hülle (Platzhalter, bis das <video> kommt — gleiche Ebene).
   Materialisiert ruhig über das generische .fx-fade (Beat 1, kein
   Phasen-Gate), danach statisch (kein Push-In). filter: saturate() ist eine
   von Stefan am 2026-07-15 freigegebene Erweiterung der dokumentierten
   Paint-only-Ausnahmefamilie (blur()/color()/clip-path, siehe Vokabular-Kopf)
   — rein malend, kein Layout-Einfluss. Die Deep-Sea-Überlagerung
   (.s8-photo-overlay) nimmt das Bild stark zurück, damit die Text-
   Choreografie klar führt (Muster: das Porträt in Szene 10 trägt als Bühne,
   ohne zu konkurrieren). Im Druck bleibt das Foto sichtbar (Endbild-
   Charakter, kein eigenes @media print nötig, Muster wie .s10-portrait):
   die hohe Overlay-Deckkraft (.86) hält Zitat-Zeile/Wandel-Teal auch auf
   Papier klar lesbar, geprüft per Screenshot-Stichprobe. */
.s8-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(.7);
}
.s8-photo-overlay {
  position: absolute;
  inset: 0;
  background: var(--color-surface-sunken-dark);
  opacity: .86;
}
.s8-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-sm);
  /* HUD-Safe-Area-Reassert (Feedback F1), siehe .s1-beat weiter oben. */
  padding: 0 clamp(16px, 6vw, 96px) var(--hud-safe);
}
.s8-src {
  margin: 0 0 var(--space-md);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(13px, 1.1vw, 15px);
  color: var(--fg-strong-muted);
}
/* aria-hidden reiner „·"-Trenner, reine Deko (WCAG-1.4.3-Ausnahme) — bleibt
   faint. Anders als .s0-corner, das echte Wörter zeigt und AA-geheizt ist. */
.s8-mid { color: var(--fg-faint); }

/* Beat 2 (Phase 2): Vorher-Satz, ruhige Blende (Optik wie .fx-fade — reiner
   Opacity-Übergang, keine Translation), bleibt danach kumulativ stehen. */
.s8-vorher {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 500;
  font-size: clamp(18px, 2vw, 27px);
  line-height: 1.42;
  letter-spacing: -0.01em;
  color: var(--fg-muted);
  max-width: 42ch;
  text-wrap: pretty;
  opacity: 0;
  transition: none;
}
.s8.phase-p2 .s8-vorher,
.s8.phase-p3 .s8-vorher,
.s8.phase-p4 .s8-vorher,
.s8.phase-p5 .s8-vorher,
.s8.phase-p6 .s8-vorher {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}

/* Beat 3+4 (Phase 3+4): Wandel-Satz in fester Box, damit nichts springt. */
.s8-wandel {
  position: relative;
  width: 100%;
  min-height: clamp(140px, 19vh, 190px);
  margin: var(--space-sm) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(4px, 1vh, 10px);
}
.s8-before, .s8-after { margin: 0; text-align: center; text-wrap: balance; }
/* Beat 3: „Aus mehreren Tagen" erscheint ruhig (.fx-fade-Charakter) und
   bleibt danach über alle Folgephasen hinweg voll sichtbar — der komplette
   Satz muss am Ende lesbar stehen (Feedback F5), anders als beim
   Karten-Pendel in Szene 5 dimmt hier nichts weg. */
.s8-before {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(18px, 2vw, 28px);
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--fg-muted);
  opacity: 0;
  transition: none;
}
.s8.phase-p3 .s8-before,
.s8.phase-p4 .s8-before,
.s8.phase-p5 .s8-before,
.s8.phase-p6 .s8-before {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}
.s8-after {
  max-width: none;
  font-size: clamp(32px, 4.6vw, 64px);
  color: var(--fg-default);
}
/* Teal-Akzent nur auf „wenige Stunden" (ein Akzent pro Zeile). */
.s8-hl { color: var(--color-brand-teal); }

/* Szene 8: .headline-display.fx-depth braucht denselben Reassert wie s2/s5/s12
   (die .scene .headline-display-Basisregel, 0,2,0, würde sonst die translateZ/
   scale-Ruhewerte von .fx-depth, 0,1,0, per Spezifität schlagen), hier zudem
   an Phase 4 statt an .scene.entered gebunden (die Headline soll erst mit
   „werden wenige Stunden" landen, mit Dwell nach Beat 3, nicht sofort beim
   Szeneneintritt). */
#s8 .headline-display.fx-depth {
  transform: translateZ(-360px) scale(.6);
  opacity: 0;
  transition: none;
}
#s8.phase-p4 .headline-display.fx-depth,
#s8.phase-p5 .headline-display.fx-depth,
#s8.phase-p6 .headline-display.fx-depth {
  opacity: 1;
  transform: translateZ(0) scale(1);
  transition: opacity var(--motion-draw) var(--ease-out) .3s,
              transform var(--motion-draw) var(--ease-out) .3s;
}

/* Beat 5 (Phase 5): Nachher-Satz, weiches Einsteigen von unten (Optik wie
   .fx-rise), bleibt danach kumulativ stehen. */
.s8-nachher {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 500;
  font-size: clamp(18px, 2vw, 27px);
  line-height: 1.42;
  letter-spacing: -0.01em;
  color: var(--fg-default);
  max-width: 42ch;
  text-wrap: pretty;
  opacity: 0;
  transform: translateY(var(--reveal-distance));
  transition: none;
}
.s8.phase-p5 .s8-nachher,
.s8.phase-p6 .s8-nachher {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}

/* Beat 6 (Phase 6): Zitat-Zeile als stehendes Schlussbild, Gold-Punkt setzt
   zuletzt (eigener Delay-Übergang, reiner Opacity-Übergang wie überall). */
.s8-close {
  margin: var(--space-lg) 0 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(18px, 1.9vw, 27px);
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--fg-default);
  max-width: 32ch;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(var(--reveal-distance));
  transition: none;
}
.s8.phase-p6 .s8-close {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s8-close .gold-dot { opacity: 0; }
.s8.phase-p6 .s8-close .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1s;
}

/* Reduced Motion: der generische Dirigent aktiviert unter reduced motion nur
   die letzte Phase (phase-p6) — alle kumulativen Beats (Vorher-Satz, der
   komplette Wandel-Satz „Aus mehreren Tagen werden wenige Stunden",
   Nachher-Satz, Zitat-Zeile inkl. Gold-Punkt) müssen deshalb hier
   zusätzlich auf ihren Endzustand erzwungen werden, dieselbe Begründung wie
   bei Szene 4/5. */
@media (prefers-reduced-motion: reduce) {
  .s8-vorher, .s8-nachher, .s8-close {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .s8-before { opacity: 1 !important; transition: none !important; }
  #s8 .headline-display.fx-depth { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s8-close .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* ---------- Szene 9: Was ich mitbringe ----------
   Drei Kennzahlen (Zähler + statischer „+"-Suffix bei 15) nebeneinander.
   Feedback F6 (Referenz-Wand statt Parade, Task W4): die frühere
   .fx-parade zeigte immer nur EINEN Namen — am Szenenende blieb zufällig
   der letzte allein stehen, die Verbindung zur 13er-Kennzahl war unklar.
   Jetzt: eine Eyebrow-Zeile „Darunter:" koppelt sichtbar an die 13, darunter
   wächst eine Referenz-Wand aus fünf Namen, die einzeln (getaktet über den
   generischen Beat-Dirigenten, data-phases → .phase-p1…p5, Muster wie
   .s11-item) landen und BLEIBEN stehen. Jeder Name landet mit demselben
   kurzen Scale-Moment (kein neues @keyframes, reiner
   transform/opacity-Übergang) — das gibt der Staffel Rhythmus, ohne dass
   ältere Namen je gedimmt würden; Endzustand: alle fünf gleichwertig, volle
   Deckkraft. Zwei Zeilen (3 + 2) halten die Wand auch auf schmalen
   Viewports (1280 px) lesbar, dezente „·"-Trennpunkte (aria-hidden) sitzen
   nur innerhalb einer Zeile. */
.s9-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xl);
  width: 100%;
  max-width: min(1100px, 94vw);
  text-align: center;
}
.s9-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-xl);
  width: 100%;
}
.s9-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  text-align: left;
}
.s9-stat-n {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(40px, 5vw, 64px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.s9-stat-suffix { color: var(--color-brand-teal); }
.s9-stat-t {
  margin: 0;
  font-family: var(--font-body);
  font-size: clamp(14px, 1.1vw, 17px);
  line-height: 1.5;
  color: var(--fg-muted);
  text-wrap: pretty;
}
@media (max-width: 820px) {
  .s9-stats { grid-template-columns: 1fr; }
}
.s9-refs {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
}
.s9-under { margin: 0; }
.s9-wall {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.6vh, 18px);
  width: 100%;
}
.s9-wall-row {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-sm) var(--space-md);
}
.s9-wall-name {
  font-family: var(--font-headline);
  font-weight: 600;
  font-size: clamp(20px, 2.4vw, 34px);
  letter-spacing: -0.015em;
  color: var(--fg-default);
  white-space: nowrap;
  opacity: 0;
  transform: scale(.88) translateY(10px);
  transition: none;
}
.s9-wall-sep {
  /* aria-hidden reiner „·"-Trenner, reine Deko (WCAG-1.4.3-Ausnahme) — bleibt
     faint. Anders als .s0-corner (echte Wörter, AA-geheizt). */
  color: var(--fg-faint);
  font-size: clamp(16px, 2vw, 26px);
  opacity: 0;
  transition: none;
}
/* Jeder Trennpunkt erscheint erst zusammen mit dem NACHFOLGENDEN Namen (statt
   von Anfang an zu stehen) — sonst hängen die Punkte während der Staffel
   sichtbar im Leeren, bevor ihr Nachbar gelandet ist (Review-Fix). */
.s9.phase-p2 .s9-wall-sep--a,
.s9.phase-p3 .s9-wall-sep--a,
.s9.phase-p4 .s9-wall-sep--a,
.s9.phase-p5 .s9-wall-sep--a {
  opacity: 1;
}
.s9.phase-p2 .s9-wall-sep--a { transition: opacity var(--motion-reveal) var(--ease-out); }
.s9.phase-p3 .s9-wall-sep--b,
.s9.phase-p4 .s9-wall-sep--b,
.s9.phase-p5 .s9-wall-sep--b {
  opacity: 1;
}
.s9.phase-p3 .s9-wall-sep--b { transition: opacity var(--motion-reveal) var(--ease-out); }
.s9.phase-p5 .s9-wall-sep--c {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}
/* Jeder Name landet in seiner eigenen Phase (Scale-Moment) und bleibt danach
   unverändert stehen — die Folgephasen setzen denselben Endzustand erneut,
   damit spätere Namen ihn nicht auf den Ruhewert von .s9-wall-name
   zurückfallen lassen (Muster wie .s11-item, hier zusätzlich mit Scale). */
.s9.phase-p1 .s9-wall-name--1,
.s9.phase-p2 .s9-wall-name--1,
.s9.phase-p3 .s9-wall-name--1,
.s9.phase-p4 .s9-wall-name--1,
.s9.phase-p5 .s9-wall-name--1 {
  opacity: 1;
  transform: scale(1) translateY(0);
}
.s9.phase-p1 .s9-wall-name--1 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s9.phase-p2 .s9-wall-name--2,
.s9.phase-p3 .s9-wall-name--2,
.s9.phase-p4 .s9-wall-name--2,
.s9.phase-p5 .s9-wall-name--2 {
  opacity: 1;
  transform: scale(1) translateY(0);
}
.s9.phase-p2 .s9-wall-name--2 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s9.phase-p3 .s9-wall-name--3,
.s9.phase-p4 .s9-wall-name--3,
.s9.phase-p5 .s9-wall-name--3 {
  opacity: 1;
  transform: scale(1) translateY(0);
}
.s9.phase-p3 .s9-wall-name--3 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s9.phase-p4 .s9-wall-name--4,
.s9.phase-p5 .s9-wall-name--4 {
  opacity: 1;
  transform: scale(1) translateY(0);
}
.s9.phase-p4 .s9-wall-name--4 {
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s9.phase-p5 .s9-wall-name--5 {
  opacity: 1;
  transform: scale(1) translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}

/* Reduced Motion: die Eyebrow und alle fünf Namen stehen sofort voll
   lesbar — der generische Dirigent aktiviert unter reduced motion nur die
   letzte Phase (phase-p5, siehe pitch.js runPhases), darum hier zusätzlich
   der harte Override (Muster wie .s4-line/.s11-item). */
@media (prefers-reduced-motion: reduce) {
  .s9-wall-name, .s9-wall-sep { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* Staffel-Verzögerungen der Welle-3-Szenen (dasselbe Reassert-Muster wie
   Welle 2: ID-spezifisch, 1,4,0, schlägt die generische .dN-Staffel weiterhin
   zuverlässig, auch falls ein Nachbar-Selektor je Szene an Spezifität zulegt). */
#s7.scene.entered .fx-rise.d3 { transition: opacity var(--motion-reveal) var(--ease-out) .3s,  transform var(--motion-reveal) var(--ease-out) .3s; }
#s7.scene.entered .fx-rise.d5 { transition: opacity var(--motion-reveal) var(--ease-out) .6s,  transform var(--motion-reveal) var(--ease-out) .6s; }
#s8.scene.entered .fx-rise.d2 { transition: opacity var(--motion-reveal) var(--ease-out) .15s, transform var(--motion-reveal) var(--ease-out) .15s; }
#s9.scene.entered .fx-rise.d3 { transition: opacity var(--motion-reveal) var(--ease-out) .3s,  transform var(--motion-reveal) var(--ease-out) .3s; }
#s9.scene.entered .fx-rise.d5 { transition: opacity var(--motion-reveal) var(--ease-out) .6s,  transform var(--motion-reveal) var(--ease-out) .6s; }

/* ============================================================================
   WELLE 2 · Task 7 + Task 6 — Szenen-Layouts (Szene 10 Der Ausbilder,
   11 Stell Dir vor). Nur Layout + Timing. Bewegung stammt komplett aus dem
   .fx-*-Vokabular oben (.fx-depth-Porträt/-Headline, .fx-rise-Optik) plus dem
   generischen Beat-Dirigenten (data-phases → .phase-p1…pN, Muster wie
   #s3/#s4/#s5/#s8). Keine Szene erfindet eigene Keyframes. Animiert wird
   ausschließlich transform/opacity (feste Layout-Boxen; das Porträt hat
   width/height-Attribute + feste CSS-Breite, kein Layout-Shift). Farben/Fonts
   nur über var(--…)-Tokens. Reduced Motion: der generische Dirigent
   aktiviert nur die letzte Phase — für die kumulativen Phasen-Klassen unten
   zusätzlich eigene !important-Overrides (dieselbe Begründung wie bei
   Szene 4/5/8).
   ============================================================================ */

/* ---------- Szene 10: Der Ausbilder (dritter Video-Platz) ----------
   video-stage-Hülle wie Szene 1/8 (Inhaltsebene später durch <video>
   ersetzbar). Porträt + Eyebrow laufen über das generische
   .fx-depth/.fx-rise-Vokabular (Beat 1, kein Phasen-Gate nötig, Muster wie
   Szene 8 Beat 1). Die vier Beat-Zeilen (Task W-C: neue vierte
   Dogfooding-Zeile) und der Schmunzler sind eine ruhige .fx-fade-Folge
   (reiner Opacity-Übergang, KEIN Push-In) und akkumulieren kumulativ über
   data-phases → .phase-p2…p6 (Muster wie .s8-vorher/-nachher). */
.s10-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 5vw, 72px);
  /* HUD-Safe-Area-Reassert (Feedback F1), siehe .s1-beat weiter oben. */
  padding: 0 clamp(16px, 6vw, 96px) var(--hud-safe);
}
.s10-portrait {
  display: block;
  flex: none;
  width: clamp(180px, 24vw, 320px);
  height: auto;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line-on-dark-default);
  box-shadow: var(--shadow-xl);
}
.s10-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  max-width: 44ch;
  text-align: left;
}
.s10-eyebrow { margin: 0; }
.s10-line, .s10-punch {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 500;
  font-size: clamp(18px, 1.9vw, 27px);
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--fg-strong-muted);
  text-wrap: pretty;
  opacity: 0;
  transition: none;
}
.s10.phase-p2 .s10-line--1,
.s10.phase-p3 .s10-line--1,
.s10.phase-p4 .s10-line--1,
.s10.phase-p5 .s10-line--1,
.s10.phase-p6 .s10-line--1 {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}
.s10.phase-p3 .s10-line--2,
.s10.phase-p4 .s10-line--2,
.s10.phase-p5 .s10-line--2,
.s10.phase-p6 .s10-line--2 {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}
.s10.phase-p4 .s10-line--3,
.s10.phase-p5 .s10-line--3,
.s10.phase-p6 .s10-line--3 {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}
/* Dogfooding-Zeile (Task W-C, Phase 5): gleiches .fx-fade-Muster wie
   Zeile 1–3, normaler Schlusspunkt, kein eigener Akzent. */
.s10.phase-p5 .s10-line--4,
.s10.phase-p6 .s10-line--4 {
  opacity: 1;
  transition: opacity var(--motion-base) var(--ease-out);
}
/* Schmunzler (Phase 6): gewichtiger und in der kräftigsten fg-Stufe der
   Staffel (Akzent-Regel: EIN Akzent pro Zeile, hier der Gold-Punkt, also
   keine zusätzliche Teal-Färbung); Gold-Punkt setzt mit eigenem Delay
   (~1,5 s) nach der Landung. */
.s10-punch {
  font-weight: 600;
  color: var(--fg-default);
}
.s10.phase-p6 .s10-punch {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}
.s10-punch .gold-dot { opacity: 0; }
.s10.phase-p6 .s10-punch .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1.5s;
}
@media (max-width: 820px) {
  .s10-wrap { flex-direction: column; text-align: center; gap: var(--space-xl); }
  .s10-portrait { width: clamp(140px, 34vw, 220px); }
  .s10-text { text-align: center; align-items: center; }
}
@media (prefers-reduced-motion: reduce) {
  .s10-line, .s10-punch { opacity: 1 !important; transition: none !important; }
  .s10-punch .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* ---------- Szene 11: Stell Dir vor (Promised Land) ----------
   Headline aus der Tiefe (Beat 1, generisches .fx-depth/.scene.entered,
   kein Phasen-Gate nötig, Muster wie Szene 2). Die drei Miniaturen (Links-
   Block wie Szene 3, Teal-Kante je Beat, rein dekorativ) sind eine
   .fx-rise-Optik-Staffel mit großzügigen Dwells, gesteuert über
   data-phases → .phase-p2…p4 (kumulativ, Muster wie .s4-line). Beat 5
   (Doppelschlag) ist EIN Phasen-Schritt (.phase-p5) mit zwei knapp versetzt
   (0/.15s) landenden Satzteilen im selben Absatz. Der Abschluss (Beat 6,
   .phase-p6) ist wie die Headline .fx-depth-groß, eigener
   Gold-Punkt-Delay. */
.s11-wrap {
  display: flex;
  flex-direction: column;
  /* Gaps zusätzlich vh-gedeckelt (Feedback W8, Muster wie .s4-wrap): bei
     flachen Fenstern schrumpft die Szene mit, statt in die HUD-Safe-Area
     zu wachsen. */
  gap: clamp(18px, 4.2vh, 32px);
  /* Feedback LF-5: war width:100% bis zur max-width-Kante — die Box selbst
     wurde vom Scene-Flex (justify-content:center) zwar schon zentriert,
     war aber breiter als ihr längster Inhalt (Abschlusszeile/Headline),
     wodurch der linksbündige Text sichtbar links hing und rechts Leerraum
     blieb. width:fit-content zieht die Box auf die längste Zeile zusammen,
     max-width bleibt als Wachstums-Deckel (Zeilenlänge), margin-inline
     zentriert die geschrumpfte Box unabhängig vom Eltern-Flex. Kinder
     bleiben unangetastet linksbündig (text-align:left unverändert). */
  width: fit-content;
  /* Breiter gezogen (Feedback W8, war min(720px, 88vw)), damit die Headline
     Raum für zwei ausgewogene Zeilen statt drei bekommt. */
  max-width: min(880px, 88vw);
  margin-inline: auto;
  text-align: left;
}
.s11-head {
  margin: 0;
  /* Deutlich erhöht (Feedback W8, war 18ch) — bricht die Headline bei
     üblichen Desktop-Breiten in zwei statt drei Zeilen. */
  max-width: 30ch;
  /* vh-gedeckelt (Muster .s4-punch-line), damit die Headline bei flachen
     Fenstern mitschrumpft statt die HUD-Safe-Area zu verletzen. */
  font-size: clamp(26px, min(3.6vw, 5.2vh), 48px);
  text-wrap: balance;
}
.s11-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* vh-gedeckelt (Feedback W8, Muster wie .s4-file). */
  gap: clamp(12px, 2.6vh, 24px);
}
.s11-item {
  margin: 0;
  padding-left: var(--space-lg);
  border-left: 2px solid var(--color-brand-teal);
  /* Icon vor der Zeile (Feedback WD, Baustein 5): der Teal-Strich bleibt,
     das Icon verschmilzt optisch mit ihm (beide Teal). Flexbox nur für
     Icon+Text, animiert wird weiterhin die ganze Zeile (.s11-item selbst),
     Icon und Text landen also zusammen in derselben Phase. */
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-family: var(--font-headline);
  font-weight: 600;
  /* vh-gedeckelt (Feedback W8, Muster wie .s4-line). */
  font-size: clamp(18px, min(2.2vw, 3vh), 30px);
  line-height: 1.26;
  letter-spacing: -0.02em;
  color: var(--fg-default);
  text-wrap: balance;
  opacity: 0;
  transform: translateY(var(--reveal-distance));
  transition: none;
}
/* Dezentes Deko-Icon (Lucide-Stil, Muster .s1-search-ico/.s1-folder): Größe
   relativ zur Zeilenschrift (~1.2em), Farbe Teal wie der Strich daneben. */
.s11-ico {
  flex: none;
  width: 1.2em;
  height: 1.2em;
  color: var(--color-brand-teal);
}
.s11.phase-p2 .s11-item--1,
.s11.phase-p3 .s11-item--1,
.s11.phase-p4 .s11-item--1,
.s11.phase-p5 .s11-item--1,
.s11.phase-p6 .s11-item--1 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s11.phase-p3 .s11-item--2,
.s11.phase-p4 .s11-item--2,
.s11.phase-p5 .s11-item--2,
.s11.phase-p6 .s11-item--2 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
.s11.phase-p4 .s11-item--3,
.s11.phase-p5 .s11-item--3,
.s11.phase-p6 .s11-item--3 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-reveal) var(--ease-out), transform var(--motion-reveal) var(--ease-out);
}
/* Beat 5 (Phase 5): Doppelschlag — zwei kurze Sätze im selben Absatz, knapp
   versetzt (0/.15s), bleiben danach kumulativ stehen (reiner
   Opacity-Übergang, kein Layout-Shift). */
.s11-doppel {
  margin: 0;
  font-family: var(--font-headline);
  font-weight: 600;
  /* vh-gedeckelt (Feedback W8, Muster wie .s4-line). */
  font-size: clamp(18px, min(2vw, 2.8vh), 28px);
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--fg-default);
}
.s11-doppel-a, .s11-doppel-b {
  opacity: 0;
  transition: none;
}
.s11.phase-p5 .s11-doppel-a,
.s11.phase-p6 .s11-doppel-a {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out);
}
.s11.phase-p5 .s11-doppel-b,
.s11.phase-p6 .s11-doppel-b {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) .15s;
}
.s11-close {
  /* vh-gedeckelt (Feedback W8, Muster wie .s4-file-Gap). */
  margin: clamp(16px, 3.4vh, 24px) 0 0;
  max-width: none;
  /* Etwas zurückgenommen und vh-gedeckelt (Feedback W8, war clamp(24px, 3vw,
     42px)) — bleibt der große Abgang, schrumpft aber mit der Fensterhöhe
     statt hinter die HUD zu laufen. */
  font-size: clamp(20px, min(2.6vw, 3.6vh), 36px);
  color: var(--color-brand-teal);
}

/* Szene 11: .headline-display.fx-depth braucht denselben Reassert wie
   s2/s5/s8/s12 (die .scene .headline-display-Basisregel würde die Ruhewerte
   von .fx-depth sonst per Spezifität schlagen) — hier für ZWEI Elemente mit
   unterschiedlichem Auftritt: die Headline landet sofort mit .scene.entered
   (Beat 1), der Abschluss erst mit seiner eigenen Phase (.phase-p6,
   Beat 6). Gold-Punkte je eigener Delay (Headline 1,3 s wie Szene 2,
   Abschluss 1 s nach seiner Phase wie die Punchlines aus Szene 3/4/5/8). */
#s11 .headline-display.fx-depth {
  opacity: 0;
  transform: translateZ(-360px) scale(.6);
  transition: none;
}
#s11.scene.entered .s11-head.fx-depth {
  opacity: 1;
  transform: translateZ(0) scale(1);
  transition: opacity var(--motion-draw) var(--ease-out), transform var(--motion-draw) var(--ease-out);
}
#s11.phase-p6 .s11-close.fx-depth {
  transform: translateZ(0) scale(1);
  transition: transform var(--motion-draw) var(--ease-out);
}
/* Nur der Abschluss (.s11-close) ist eine der vier Ziel-Punchlines
   (Baustein 7, Feedback W-A) — .s11-head bleibt beim generischen
   Tiefen-Auftritt oben unangetastet. Override auf gleicher Spezifität wie
   die geteilte Basisregel, aber später deklariert (gewinnt für s11-close):
   leichte Rest-Tiefe statt des großen Dive, Opacity konstant 1, der Wipe
   (.fx-reveal) trägt jetzt den Haupteindruck. */
#s11 .s11-close.fx-depth { opacity: 1; transform: translateZ(-40px) scale(.97); }
#s11 .s11-close.fx-reveal { clip-path: inset(-0.2em 100% -0.3em -0.1em); transition: none; }
#s11.phase-p6 .s11-close.fx-reveal {
  clip-path: inset(-0.2em -0.4em -0.3em -0.1em);
  transition: clip-path var(--motion-draw) var(--ease-out);
}
.s11-head .gold-dot { opacity: 0; }
#s11.scene.entered .s11-head .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1.3s;
}
.s11-close .gold-dot { opacity: 0; }
#s11.phase-p6 .s11-close .gold-dot {
  opacity: 1;
  transition: opacity var(--motion-reveal) var(--ease-out) 1s;
}

@media (prefers-reduced-motion: reduce) {
  .s11-item, .s11-doppel-a, .s11-doppel-b {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  #s11 .headline-display.fx-depth { opacity: 1 !important; transform: none !important; transition: none !important; }
  .s11-head .gold-dot, .s11-close .gold-dot { opacity: 1 !important; transition: none !important; }
}

/* ============================================================================
   WELLE 3 — Task 9: Druckfassung (A4 quer, eine Szene je Seite, 13 Seiten).
   Reines Zusatz-Layer — nichts hier verändert Bildschirm-Verhalten, alles
   lebt unter @media print bzw. @page.

   ---- Warum RM-Spiegel + !important (bitte NICHT wegvereinfachen) ----
   Der Szenen-Motor zeigt Bewegung über Phasen-Klassen, die pitch.js zur
   Laufzeit auf die Section setzt (data-phases → .phase-p1…pN bzw.
   .phase-b1…b6, immer nur eine zur Zeit) und über ID-gescopte Basisregeln
   wie #s6.phase-p4 .s6-oton.fx-fade oder #s3.phase-p7 .headline-display.
   fx-depth, die Sichtbarkeits-Eigenschaften (meist opacity, teils transform/
   clip-path) im Ruhezustand auf 0/verdeckt setzen. Im Druck steht keine
   Phasen-Klasse verlässlich zur Verfügung: eine nie besuchte Szene trägt
   weder .entered noch irgendeine phase-p*-Klasse (Grundzustand bei frischem
   Seiten-Load — genau der Pflicht-Testfall unten, "s9 nie besucht, direkt
   PDF"), die gerade aktive Szene wiederum trägt IRGENDEINEN Zwischenstand,
   je nachdem wann gedruckt wird. Eine generische Druckregel ohne !important
   wie `.fx-fade { opacity: 1 }` verliert darum gegen genau diese ID-gescopten
   Basisregeln (ID+Klasse schlägt Klasse allein) — Ergebnis wären leere
   Stellen an den inhaltlich wichtigsten Punkten (Szene 6 Warum-Beat, Szene
   10 Dogfooding-Zeile, Szene 5 Punchline, …). Die vorhandenen
   prefers-reduced-motion-Blöcke lösen dasselbe Grundproblem bereits korrekt
   (dort ist die Phasen-Klasse ebenso nicht verlässlich vorhanden bzw. wird
   von pitch.js direkt auf den Endzustand gesprungen), meist mit demselben
   !important-Muster. Diese Sektion überträgt sie je Szene 1:1 auf
   @media print: bare Klassen-/ID-Selektoren (kein Phasen-/.entered-Bezug),
   Sichtbarkeits-Eigenschaften mit !important. Wo eine Szene absichtlich
   gedimmt endet (Szene 5 Karte A, s. u.), übernimmt der Druck exakt diesen
   gedimmten RM-Wert statt einer Pauschal-Opacity — die RM-Blöcke sind die
   Quelle der Wahrheit. Einzige bewusste Abweichung von der reinen
   RM-Spiegelung: Szene 6 druckt ihre drei Stationen UNGEDIMMT (Story-Vorgabe
   aus dem Task-Brief), obwohl Bildschirm und RM Station 1/2 leicht
   abdunkeln — Begründung im Kommentar dort.
   ============================================================================ */

@page {
  size: A4 landscape;
  margin: 0;
}

/* ---------- Druck-Fußzeile (Task W-A, D1) — Basisregel AUSSERHALB @media print ----------
   pitch.js erzeugt dieses Element für s1–s12 (buildPrintFooters(), s0/Titelblatt
   bleibt ohne). display:none steht hier bewusst UNGESCHÜTZT von @media print,
   nicht nur innerhalb — deckt Druck-Emulation/Zwischenzustände ab, in denen
   Styles ausgewertet werden, ohne dass gerade ein echter Druckvorgang läuft
   (dieselbe Vorsichtsregel wie beim Bühnen-Kern selbst, nur umgekehrte
   Sichtbarkeits-Richtung: dort ist der Bildschirm-Zustand die Vermutung,
   hier der Druck-Zustand). @media print weiter unten hebt es für den
   Druckfall wieder auf. */
.print-footer {
  display: none;
}

/* ---------- Druck-QR-Karte Szene 12 (Task Druck-W-D) — Basisregel AUSSERHALB
   @media print ----------
   Gleiches Muster wie .print-footer oben: display:none steht hier bewusst
   ungeschützt, deckt auch Druck-Emulation/Zwischenzustände ab. @media print
   weiter unten hebt es fürs echte Blatt wieder auf. Das <img> darf im DOM
   stehen (aria-hidden im Markup) — am Screen ändert sich dadurch nichts. */
.s12-qr-card {
  display: none;
}

/* ============================================================================
   Kompakt-Schicht Handy-Querformat (Stefan 2026-07-24)
   Befund: Alle Schriftgrößen skalieren mit vw — im Handy-Querformat ist die
   Breite groß (852px), die Höhe winzig (300-430px), die Typo sprengt die
   Höhe (Gerätefotos + automatisierte Renders: s4 Fußnote auf der Punchline,
   s5/s6 oben+unten abgeschnitten, s9/s10 unterm Logo, s12-Gag raus).
   Prinzip dieser Schicht: font-sizes und Gaps hängen hier an vh (dem knappen
   Faktor), px-Untergrenzen sichern Lesbarkeit. NUR screen + orientation:
   landscape + max-height 520px — Desktop (ab 521px Höhe), Hochkant (der
   Vorhang regiert) und Druck (screen-Prefix; A4 quer misst 794px) bleiben
   unberührt. Steht bewusst NACH allen Szenen-Basisregeln und VOR @media
   print (bei gleicher Spezifität entscheidet die Reihenfolge — Doktrin).
   ========================================================================== */
@media screen and (orientation: landscape) and (max-height: 520px) {

  /* Logo: kleiner und enger in die Ecke — halbiert die Kollisionszone der
     kopfstarken Szenen (s9-Zahlen, s10-Porträt, s4-Karte). */
  .pitch-logo-link {
    width: 92px;
    top: calc(clamp(10px, 2.4vh, 16px) - 6px);
    left: calc(clamp(12px, 1.8vw, 20px) - 6px);
  }

  /* Szenen-Grundpadding: der 64px-Ring ist bei 300-430px Höhe zu fett. */
  .scene { padding: clamp(12px, 4vh, 24px) clamp(24px, 4vw, 48px) var(--hud-safe); }

  /* Passt-immer-Fundament (Stefans iPhone-Realprobe 2026-07-24): reicht die
     Höhe trotz aller Kompression nicht (reale ~300px bei doppelter
     Safari-Leiste im Querformat), richtet sich der Inhalt OBEN bündig aus
     und die Szene wird fingerscrollbar — statt wie ein zentrierter Flex
     beidseitig ins Unerreichbare zu clippen. margin-block:auto auf den
     Flow-Wraps ist der overflow-sichere Zentrier-Klassiker: solange Platz
     ist, exakt mittig wie bisher; bei Überlauf bleibt der Anfang oben
     erreichbar. Der Wisch-Handler stört nicht (Szenenwechsel verlangt
     horizontale Dominanz, vertikales Ziehen scrollt einfach). */
  .scene {
    align-items: flex-start;
    overflow-y: auto;
  }
  .s0-wrap, .s2-wrap, .s4-wrap, .s5-wrap, .s6-wrap, .s7-wrap, .s9-wrap, .s11-wrap, .s12-wrap {
    margin-block: auto;
  }
  /* Dieselbe Medizin für die zwei absolut gefüllten Wraps: s8 ist ein
     column-Flex (auto-Margen auf erstes/letztes Kind), s10 ein row-Flex
     (auto-Margen auf beide Spalten-Kinder). */
  .s8-wrap { justify-content: flex-start; overflow-y: auto; }
  .s8-wrap > :first-child { margin-top: auto; }
  .s8-wrap > :last-child { margin-bottom: auto; }

  /* --- s0 · Titel: Stapel unters Logo schieben und leicht verdichten
     (Wächter-Befund: Eyebrow-Box überlappte die Logo-Box um 5px). --- */
  #s0 .s0-wrap { padding-top: clamp(20px, 7vh, 32px); gap: clamp(8px, 1.8vh, 16px); }
  #s0 .s0-line.headline-display { font-size: clamp(26px, 7vh, 84px); }

  /* --- s4 · Boeing-Akte: Karte kompakt, Fußnote in den Fluss --- */
  .s4-wrap { gap: clamp(5px, 1.6vh, 14px); max-width: min(760px, 90vw); }
  .s4-eyebrow { font-size: 11px; }
  .s4-card { gap: clamp(6px, 1.8vh, 12px); padding: clamp(8px, 2vh, 14px) clamp(16px, 2.6vw, 28px); }
  .s4-line { font-size: clamp(13px, 3.4vh, 19px); line-height: 1.3; }
  .s4-punch-line { font-size: clamp(17px, 5.8vh, 30px); }
  .s4-footnote {
    position: static;
    transform: none;
    font-size: 11px;
  }

  /* --- s5 · Umbruch: Spalte und Pendel niedriger --- */
  .s5-wrap { gap: clamp(10px, 3vh, 22px); }
  .s5-line--1 { font-size: clamp(14px, 3.6vh, 20px); }
  .s5-line--2 { font-size: clamp(16px, 4.4vh, 24px); }
  .s5-pendulum { min-height: clamp(84px, 26vh, 130px); }
  .s5-card { width: min(560px, 76vw); padding: clamp(10px, 2.6vh, 16px) clamp(18px, 3vw, 28px); }
  .s5-punch-line { font-size: clamp(17px, 5.8vh, 30px); }

  /* --- s6 · Einarbeitung: drei Karten + zwei Schlusszeilen in die Höhe --- */
  .s6-wrap { gap: clamp(5px, 1.6vh, 12px); }
  .s6-headline { font-size: clamp(16px, 4.6vh, 24px); }
  .s6-stations { gap: clamp(8px, 1.4vw, 16px); }
  /* Größter Höhenfresser der Szene: das 32px-Innenpolster der drei Karten
     (Befund 300px-Render: Karten sprengen die Höhe, Kopfzeilen ganz raus). */
  .s6-station { padding: clamp(10px, 2.6vh, 18px) clamp(12px, 1.8vw, 20px); gap: clamp(4px, 1.2vh, 8px); }
  .s6-num { font-size: clamp(16px, 4.4vh, 24px); }
  .s6-station-h { font-size: clamp(13px, 3.4vh, 17px); }
  .s6-station-p { font-size: clamp(12px, 3vh, 14px); line-height: 1.35; }
  .s6-oton { font-size: clamp(11px, 2.8vh, 14px); }
  .s6-punch { font-size: clamp(14px, 3.8vh, 19px); }
  .s6-close { font-size: clamp(13px, 3.6vh, 18px); }

  /* --- s8 · Beweis: Typo-Stapel über dem Spot flacher. Größter Fresser
     (Wächter-Befund, Eyebrow bei top=-46): der Wandel-Block erzwingt in
     der Basis min-height 140px — hier höhengetrieben. --- */
  .s8-eyebrow { margin: 0; font-size: 11px; }
  .s8-src { margin: 0 0 clamp(3px, 1vh, 8px); font-size: 12px; }
  .s8-wandel { min-height: clamp(44px, 16vh, 84px); margin: clamp(2px, 0.6vh, 5px) 0; }
  .s8-vorher, .s8-nachher { font-size: clamp(11px, 3vh, 16px); line-height: 1.3; }
  .s8-after { font-size: clamp(18px, 6.2vh, 34px); }
  .s8-close { margin-top: clamp(4px, 1.2vh, 9px); font-size: clamp(11px, 3.2vh, 16px); }

  /* --- s9 · Zahlen: unters Logo geschoben statt dahinter --- */
  .s9-wrap { gap: clamp(12px, 3.6vh, 26px); padding-top: clamp(26px, 8vh, 40px); }
  .s9-stats { gap: clamp(14px, 2.4vw, 28px); }
  .s9-stat { gap: clamp(3px, 1vh, 8px); }
  .s9-stat-n { font-size: clamp(22px, 8vh, 40px); }

  /* --- s10 · Ausbilder: Porträt skaliert mit der Höhe --- */
  .s10-wrap { gap: clamp(16px, 3vw, 40px); padding-top: clamp(24px, 7vh, 36px); align-items: flex-start; overflow-y: auto; }
  .s10-wrap > * { margin-block: auto; }
  .s10-portrait { width: clamp(96px, 36vh, 180px); }
  .s10-line, .s10-punch { font-size: clamp(12px, 3.4vh, 17px); line-height: 1.35; }
  .s10-text { gap: clamp(6px, 2vh, 14px); }

  /* --- s12 · CTA: Kern (Button + Termin-URL) hat Vorrang --- */
  .s12-wrap { gap: clamp(6px, 1.8vh, 12px); }
  .s12-eyebrow { margin: 0; }
  .s12-head { font-size: clamp(20px, 7.6vh, 36px); }
  .s12-sub { font-size: clamp(12px, 3vh, 15px); }
  .s12-cta-block { margin-top: 0; }
  .s12-gag .px-explorer { width: min(240px, 46vw); }
}

/* Der Datei-Gag auf s12 ist der Enge-Treiber der CTA-Szene (Wächter-Befund:
   mit Gag ragt die Eyebrow selbst bei 393px noch 30px raus) — im
   Handy-Querformat weicht er dem Kern, er lebt auf Tablets quer (ab 421px
   Höhe) und am Desktop weiter. */
@media screen and (orientation: landscape) and (max-height: 420px) {
  .s12-gag { display: none; }
}

/* Extremstufe (~300px: Handy-Querformat MIT Safari-Leisten, ohne Vollbild):
   der Datei-Gag auf s12 ist ein Bonus-Charakterstück — unter 340px Höhe
   weicht er dem Kern (Headline, Button, Termin-URL, Transparenz-Zeile).
   Ebenso ruht der Skeleton-Kopf der Boeing-Akte (drei Deko-Balken). */
@media screen and (orientation: landscape) and (max-height: 340px) {
  .s4-card-head { display: none; }
  .s6-eyebrow { display: none; }
}

@media print {

  /* ---------- Grundgerüst: Farben erhalten, HUD weg, Bühne wird ein
     normaler Fluss aus 13 Seiten statt ein Fixed-Viewport-Stapel ---------- */
  html {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  html, body, .pitch-body, .stage {
    height: auto !important;
    overflow: visible !important;
  }
  .hud, #sr-status, .share-toast, .sound-ask {
    display: none !important;
  }
  /* Video-Welle Hosenträger (zusätzlich zur @media screen-Kapselung oben):
     der PDF-Export läuft ohne Reduced-Motion-Emulation, has-video könnte
     also gesetzt sein — hier hart aus, unabhängig vom Zustand. */
  .scene-video { display: none !important; }

  /* Härtung P5 (Gürtel-und-Hosenträger, Druck-W-B-MERKER): unqualifizierte
     .d*-transition-delay-Fenster (siehe .d1…d8 oben) könnten bei einem
     Live-Medienwechsel theoretisch in den Druck lecken — für den Chrome-
     Druckvorschau-Pfad nachweislich irrelevant (frischer Print-Render pro
     page.pdf()-Aufruf, kein laufender Übergang), aber die Absicherung ist
     billig. Pauschal jede Transition auf der Bühne kappen, gleiches
     !important-Spiegel-Muster wie die übrigen Druck-Reasserts in diesem
     Block — kein neuer Mechanismus. */
  .stage, .stage * {
    transition: none !important;
  }

  /* ---------- Print-Safe-Areas (Task W-A, D2) — Interface für Folge-Tasks ----------
     Zwei Custom Properties, NAMEN BEWUSST STABIL (Druck-W-B/C/D konsumieren
     sie): --print-safe-top reserviert die Logo-Zone oben (.pitch-logo druckt
     als position:fixed-Element auf jeder Seite, siehe weiter oben in dieser
     Datei), --print-safe-bottom die Fußzeilen-Zone unten (.print-footer,
     s. u.). Werte am gerenderten PDF kalibriert: Logo-Unterkante liegt bei
     ~13mm ab Seitenoberkante (top clamp(20,3vw,40px) + Logo-Höhe bei
     Breiten-Untergrenze 110px ≈ 15px, macht in Summe ~48.8px ≈ 12.9mm),
     16mm lässt ihm reichlich Luft; die einzeilige Fußzeile braucht deutlich
     weniger als die Logo-Zone, 12mm mit ~4mm Bodenabstand der Zeile selbst
     hat Reserve nach oben. WICHTIG: Szenen-Print-Layouts (auch die drei
     Folge-Kompositionen für Szene 6/9/10) dürfen diese Zonen NICHT bebauen —
     die Werte sind die verbindliche Absprache, kein Vorschlag. */
  :root {
    --print-safe-top: 16mm;
    --print-safe-bottom: 12mm;
  }

  /* Jede Szene verlässt den absoluten Stapel (Bühne zeigt auf dem Bildschirm
     per position:absolute + opacity immer nur EINE) und wird eine normale,
     exakt A4-quer-große Flussbox; box-sizing:border-box ist hier nötig, weil
     die Bühne global kein border-box-Reset hat — ohne die Umstellung würde
     das vorhandene Innen-Padding zur festen Breite/Höhe hinzuaddiert und die
     Seite liefe über. #s12 (letzte Szene) bekommt keinen Umbruch danach,
     sonst hinge eine leere 14. Seite dran. overflow:hidden entspricht der
     Screen-Philosophie der Bühne (Layout ist auf Passung gebaut, kein
     Scroll) — die Pflicht-Sichtprüfung deckt ab, ob wirklich nichts
     abgeschnitten wird (insbesondere Szene 6, siehe Brief).

     D7-Härtung (Task W-A): width/height standen vorher fest auf 297mm/210mm
     — ein separat hartcodierter Zwilling der @page-Größe zwei Regeln höher,
     der bei einer künftigen @page-Änderung stillschweigend hätte auseinander-
     laufen können. 100vw/100vh sind seitenbox-relativ: sie lösen gegen genau
     die Größe auf, die @page tatsächlich deklariert (bei margin:0 identisch
     zu 297mm/210mm, keine Änderung am bisher grünen Fall) — EINE Quelle der
     Wahrheit statt zwei. Empirisch geprüft (Playwright, Details + Messwerte
     im Report): der ursprünglich vermutete Mechanismus "Dialog-Rand ⇒ Box zu
     groß fürs Seiten-Budget ⇒ Zusatzblatt" ließ sich über 0–40mm Rand hinweg
     NICHT reproduzieren, die Seitenzahl blieb dabei durchgehend bei 13 — auch
     schon vor dieser Änderung. Tatsächlich reproduzierbar war ein anderer,
     randunabhängiger Effekt: sobald Playwright/Chromium NICHT die
     @page-Größe als maßgeblich behandelt (prefer_css_page_size=False), rutscht
     Szene 6 sichtbar unter das Logo (Eyebrow/Headline fehlen oben, Schluss-
     zeile unten) — bei jedem getesteten Rand identisch, also eine Eigenheit
     dieses Renderpfads selbst, nicht der Randbreite. Diese CSS-Zeile behebt
     das nicht (sie kann es nicht, der Effekt liegt unterhalb der CSS-Box-
     bemessung) — sie beseitigt aber die überflüssige Doppel-Quelle für die
     Seitengröße und bleibt im empfohlenen, nachweislich sauberen Export-Pfad
     (prefer_css_page_size=True) bit-identisch zum bisherigen Verhalten.
     padding-top/-bottom setzen die beiden Safe-Areas oben als generische
     Zonen durch, damit Inhalt nicht mehr unter dem Logo klebt bzw. später
     nicht mit der neuen Fußzeile kollidiert; links/rechts bleibt das
     ererbte --space-3xl-Padding der Bildschirm-Basisregel unangetastet. */
  .scene {
    box-sizing: border-box;
    position: relative;
    inset: auto;
    width: 100vw;
    height: 100vh;
    padding-top: var(--print-safe-top);
    padding-bottom: var(--print-safe-bottom);
    overflow: hidden;
    opacity: 1 !important;
    visibility: visible !important;
    break-after: page;
    page-break-after: always;
  }
  #s12 {
    break-after: auto;
    page-break-after: auto;
  }

  /* ---------- Druck-Fußzeile (Task W-A, D1) — Druck-Darstellung ----------
     Reine Meta-Information (Absender/Stand/Seitenzahl), kein Gestaltungs-
     element: kleine Inter-Schrift knapp über der 10px-Untergrenze,
     fg-on-dark-soft (68 %, nicht das blassere faint — die Fußzeile trägt
     Information, ist nicht rein dekorativ). Absolut positioniert IM
     jeweiligen .scene-Element (dessen padding gilt für sie als
     position:absolute-Kind NICHT — deshalb eigener, kleiner bottom-Wert
     statt sich auf --print-safe-bottom als Padding zu verlassen), sitzt
     damit vollständig innerhalb der oben reservierten Fußzeilen-Zone. left/
     right spiegeln den ererbten --space-3xl-Bühnenrand, damit die Fußzeile
     optisch mit dem Inhalt fluchtet. z-index über dem Beat-Layer (2, s. o.),
     damit sie nie unter einer Szenen-Ebene verschwindet. */
  .print-footer {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    position: absolute;
    left: var(--space-3xl);
    right: var(--space-3xl);
    bottom: 4mm;
    z-index: 3;
    font-family: var(--font-body);
    font-size: 10px;
    letter-spacing: 0.02em;
    color: var(--fg-soft);
  }

  /* Tipp-Cursor blinkt in keinem Druck-Endbild (Szene 1/3/12 teilen sich
     dieselben zwei Cursor-Klassen; die zugehörigen Beats sind ohnehin in
     jeder der drei Szenen ausgeblendet, siehe unten — hier zusätzlich
     hart abgesichert). */
  .s1-caret, .px-caret {
    display: none !important;
  }

  /* ---------- Generisches .fx-*-Vokabular eingefroren ----------
     Deckt Eyebrows/Headlines/Karten, die die Vokabular-Klassen direkt
     tragen, über alle Szenen hinweg ab (u. a. s0/s2/s6/s7/s8/s9/s10/s11/
     s12). Für Elemente in nicht-finalen Beats (Szene 1 Beat 1–5, Szene 3
     Diagnose/Doppelzeile/Callback) ist das folgenlos, weil deren
     Beat-Container weiter unten vollständig auf display:none gesetzt wird. */
  .fx-fade, .fx-rise, .fx-depth {
    opacity: 1 !important;
    transform: none !important;
  }
  .fx-reveal {
    clip-path: inset(-0.2em -0.4em -0.3em -0.1em) !important;
  }

  /* Gold-Punkte mit eigenem Opacity-Gate — vollständige Liste, deckungsgleich
     mit jeder "X .gold-dot { opacity: 0 }"-Basisregel im Bestand. Punkte ohne
     eigenes Gate (z. B. in .s6-close, .s6-headline) sind reguläre
     Inline-Elemente ohne Opacity-Bedingung und brauchen keinen Eintrag. */
  .s0-line--2 .gold-dot,
  .s1-punch-2 .gold-dot,
  .s2-claim .gold-dot,
  .s3-punch-line .gold-dot,
  .s4-punch-line .gold-dot,
  .s5-punch-line .gold-dot,
  .s6-punch .gold-dot,
  .s8-close .gold-dot,
  .s10-punch .gold-dot,
  .s11-head .gold-dot,
  .s11-close .gold-dot,
  .s12-head .gold-dot {
    opacity: 1 !important;
  }

  /* ---------- Szene 0: Titel ----------
     Eyebrow/Headline-Zeilen/Sender/Ecken-Label kommen aus dem generischen
     Vokabular oben; hier nur die zwei bespoke (nicht .fx-*-klassifizierten)
     Übergänge: die Signatur-Linie zieht per transform:scaleX auf, der
     Gold-Punkt der zweiten Headline-Zeile hat sein eigenes Opacity-Gate
     (oben in der gemeinsamen Liste). Start-Knopf + Hinweiszeile bleiben über
     die vorhandene .screen-only-Regel verdeckt (unverändert, s. o.). */
  #s0 .s0-sig {
    transform: scaleX(1) !important;
  }

  /* ---------- Szene 1: Der KI-Praktikant ----------
     Druck-Standbild = Beat 6 (Punchline, RM-Endzustand Z. 941 ff.). Die
     Beats sind exklusiv (immer nur einer über seine phase-bN-Klasse
     sichtbar) — ohne Klasse zeigt der Ruhezustand aller sechs Beats
     opacity:0 (unsichtbar), AUSSER die Szene steht beim Drucken zufällig auf
     einem der Beats 1–5 (aktive Szene = irgendein Zwischenstand, z. B. ein
     halb getipptes Suchfeld) — display:none deckt beide Fälle gleichermaßen
     ab. Zeile 1 der Punchline bleibt wie im RM-Endzustand gedimmt (.5
     Opacity, Positions-/Unschärfe-Verschiebung neutralisiert), Zeile 2 +
     ihr Gold-Punkt (oben in der gemeinsamen Liste) stehen voll da. Die
     Geister-Fenster sind zur Punchline weggeflogen (opacity 0, RM-Block
     Z. 969), das Teal-Glimmen ist auf seine Punchline-Intensität gezogen
     (sonst bliebe es beim blasseren Ruhewert .7). */
  #s1 .s1-b1, #s1 .s1-b2, #s1 .s1-b3, #s1 .s1-b4, #s1 .s1-b5,
  #s1 .s1-insert-a, #s1 .s1-insert-b, #s1 .s1-insert-kalk {
    display: none !important;
  }
  #s1 .s1-b6 {
    opacity: 1 !important;
  }
  #s1 .s1-glimmer {
    opacity: 1 !important;
  }
  #s1 .s1-ghost--a, #s1 .s1-ghost--b, #s1 .s1-ghost--c {
    opacity: 0 !important;
  }
  #s1 .s1-punch-1 {
    opacity: .5 !important;
    transform: none !important;
    filter: none !important;
  }
  #s1 .s1-punch-2 {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  /* ---------- Szene 3: Es liegt nicht an ihr ----------
     Druck-Standbild = Beat 5 (Punchline, .s3-punch). Diagnose/Doppelzeile/
     Callback sind exklusive Vorgänger-Beats, dieselbe Begründung wie
     Szene 1. Die Punchline selbst (headline-display fx-depth fx-reveal +
     Gold-Punkt) kommt komplett aus dem generischen Vokabular/der
     Gold-Punkt-Liste oben. */
  #s3 .s3-diagnose, #s3 .s3-double, #s3 .s3-callback {
    display: none !important;
  }
  #s3 .s3-punch {
    opacity: 1 !important;
  }

  /* ---------- Szene 4: Die Boeing-Akte ----------
     Kumulative Szene (kein exklusiver Beat-Wechsel), aber die drei
     Akten-Zeilen dimmen auf dem Bildschirm normal ab, sobald die jeweils
     nächste landet. Im RM-Endzustand (Z. 1662) stehen alle drei stattdessen
     gleich hell — genauso hier, keine Pauschal-Opacity nötig, weil das schon
     die vollständige Auflösung ist. */
  #s4 .s4-card, #s4 .s4-line, #s4 .s4-footnote {
    opacity: 1 !important;
  }

  /* ---------- Szene 5: Der Umbruch ----------
     Bewusst NICHT alles auf opacity 1: Karte A (der Wettbewerber, der seiner
     KI nichts zeigt) bleibt im RM-Endzustand (Z. 1878–1883) gedimmt und
     unscharf stehen, nur Karte B (die "beste Mitarbeiterin") kommt voll
     durch — exakter Spiegel der RM-Werte statt einer Pauschal-Opacity. */
  #s5 .s5-intro {
    transform: none !important;
  }
  #s5 .s5-line {
    opacity: 1 !important;
    transform: none !important;
  }
  #s5 .s5-card--a {
    opacity: .3 !important;
    transform: translate(-50%, -50%) scale(.86) !important;
    filter: blur(5px) !important;
  }
  #s5 .s5-card--b {
    opacity: 1 !important;
    transform: translate(-50%, -50%) scale(1) !important;
    filter: none !important;
  }
  #s5 .s5-card--b .s5-hl {
    color: var(--color-brand-teal) !important;
  }

  /* ---------- Szene 6: Die Einarbeitung ----------
     Kumulativ, nichts exklusiv. Explorer-Fenster + alle sechs Zeilen
     (RM Z. 2316–2317) sowie O-Ton/Punchline/Abschlusszeile (RM Z. 2318–2322)
     wie im RM-Endzustand. Bewusste Abweichung von der reinen RM-Spiegelung
     (Story-Vorgabe aus dem Brief, Stichwort "UNGEDIMMT"): auf dem Bildschirm
     UND unter RM bleiben Station 1/2 statisch leicht abgedunkelt (.8/.92,
     Z. 1987–1988 — von RM nicht aufgehoben), im Druck sollen alle drei
     Stationen gleich hell stehen, darum hier zusätzlich zurückgesetzt. Die
     Fokus-Dimmung beim Warum-Beat (.s6-mid auf .4) ist bereits
     @media screen-gekapselt (Z. 2260 ff.) und im Druck automatisch aus —
     nichts zu tun, per PDF-Sichtprüfung nur bestätigt.
     .s6-explorer-slot hat unter 1100px Fensterbreite ein eigenes
     display:none (Z. 2108 ff.): A4 quer liegt bei ca. 1122 CSS-Pixel Breite
     (96-dpi-Rechnung), das ist so knapp über der Schwelle, dass
     Rundung/Renderer-Unterschiede das Fenster verschwinden lassen könnten —
     deshalb hier hart erzwungen sichtbar statt sich auf die Breiten-Marge
     zu verlassen. */
  #s6 .s6-explorer-slot {
    display: flex !important;
  }
  #s6 .s6-explorer-slot .px-explorer {
    opacity: 1 !important;
  }
  #s6 .s6-explorer-row {
    opacity: 1 !important;
    transform: none !important;
  }
  #s6 .s6-oton, #s6 .s6-punch, #s6 .s6-close {
    opacity: 1 !important;
    transform: none !important;
  }
  #s6 .s6-station:nth-child(1),
  #s6 .s6-station:nth-child(2) {
    opacity: 1 !important;
  }

  /* ---------- Szene 6 Druck-Komposition (Task Druck-W-B) ----------
     Stefan hat den Vorgängerstand live abgelehnt: Eyebrow/Headline fehlten
     oben komplett, die Abschlusszeile fehlte unten, die drei Stationskarten
     dominierten ~70 % der Seite, der Explorer war winzig. Ursache: .s6-wrap
     ist eine zentrierte Bildschirm-Flex-Spalte (fürs 16:9-Bühnenbild
     gebaut) — in die A4-quer-Box mit Safe-Areas gepresst, wird ihre
     natürliche Höhe deutlich größer als die ~688px Nutzhöhe (1123×794-
     Viewport, 16/12mm Safe-Areas). Die zentrierende .scene-Box
     (align-items:center, overflow:hidden) schneidet den Überhang oben UND
     unten gleichermaßen ab — exakt Stefans Befund (Karte 01 klebt am
     Seitenanfang, weil der obere Überhang oben verschwindet).

     Lösung: NUR im Druck wird .s6-wrap zum CSS-Grid mit zwei Spalten und
     acht Zeilen (Kopfzone volle Breite, zwei Leerzeilen als Fugen —
     ursprünglich flexible 1fr, seit Task DR3 feste Token-Fugen, siehe
     Kommentar direkt am Grid —, Stationen/Explorer, ·/O-Ton, Punchline
     volle Breite, Abschluss volle Breite) — die Zweispaltigkeit aus dem
     Brief. .s6-mid und .s6-why
     sind reine Layout-Wrapper ohne eigene Optik
     (kein Hintergrund, kein Rahmen, siehe Regeln oben im Datei); hier NUR im
     Druck display:contents, das ihre Kinder auf die Grid-Ebene von .s6-wrap
     hebt (Stationen/Explorer-Slot bzw. O-Ton/Punchline werden direkte
     Grid-Items), ohne einen DOM-Knoten zu bewegen oder die Screen-Optik zu
     berühren (beide Regeln stehen ausschließlich hier unter @media print).

     .s6-stations wechselt von der Bildschirm-Dreierreihe (repeat(3,1fr)) auf
     eine Einerspalte: bei einer Dreierreihe in einer halben A4-Spalte
     (~150px je Karte) müssten die Sätze stark mehrzeilig umbrechen —
     gestapelt bei voller Spaltenbreite bleiben die drei kompakten Karten
     lesbar UND die Gruppe insgesamt niedriger (gemessen, siehe Report).
     „stations" spannt beide Mittelzeilen der Grid-Areas, damit ihre eigene
     (kürzere) Content-Höhe die rechte Spalte (Explorer+O-Ton, insgesamt
     höher) nicht über gemeinsames Row-Auto-Sizing streckt — align-items:
     start auf dem Grid hält beide Spalten oben bündig, der Rest ist stiller
     Weißraum.

     Punchline+Abschlusszeile bilden die Fußzone über der Fußzeilen-Zone,
     volle Breite, Punchline sichtbar größer als die Abschlusszeile
     (Hierarchie-Vorgabe aus dem Brief — bewusst NICHT die Bildschirm-
     Relation gespiegelt: dort ist .s6-close mit bis zu 34px sogar minimal
     größer als .s6-punch mit bis zu 32px, hier gelten print-eigene, feste
     Werte statt der vw/vh-Formeln). Alle Maße unten sind am gerenderten
     Ergebnis gemessen (Playwright, Viewport 1123×794), nicht nur gerechnet
     — siehe Report für die Bounding-Box-Tabelle. */
  #s6 .s6-mid,
  #s6 .s6-why {
    display: contents;
  }
  /* Vertikal-Balance (Task DR3, ersetzt das W-B-Konstrukt aus
     #s6 { align-items:stretch } + zwei 1fr-Leerzeilen): Stefans Befund am
     DR2-Render — der Kopf (Eyebrow+Headline) hing isoliert oben an der
     Safe-Top-Kante, danach ~20 % Leerband, und die Seite las sich als drei
     abgehängte Inseln statt EINER Komposition („Bitte hier den oberen Text
     mit anordnen"). Ursache war genau das Stretch-Konstrukt: es pinnte
     Kopf und Fuß an die Safe-Kanten und parkte den GESAMTEN Rest-Freiraum
     in den zwei 1fr-Fugen (je ~140px ≈ 20 %). Gleiches Heilmuster wie der
     eigene S9-Balance-Fix (ffc2189, dort ausführlich begründet): gedeckelte
     feste Fugen statt 1fr — var(--space-2xl) (48px, echtes Token, bewusst
     dieselbe Größenordnung wie das column-gap daneben), die vertikale
     Zentrierung der kompakt gewordenen Komposition übernimmt wieder die
     bestehende .scene-Flexbox (align-items:center der Bildschirm-
     Basisregel; die generischen .scene-Print-Paddings halten die
     Safe-Areas, der frühere #s6-Zusatz-Puffer entfällt ersatzlos — bei
     mittiger Komposition liegt der Inhalt weit von beiden Safe-Lines).
     Effektive Fuge Kopf→Mitte bzw. Mitte→Fuß = row-gap + 48px + row-gap =
     64px Box-Abstand (~10–11 % der Nutzhöhe als Ink-Band, gemessen am
     echten Export, siehe DR3-Nachtrag im Report) — alle vier Bänder der
     Seite (oben/Fuge/Fuge/unten) liegen damit nah beieinander, kein Band
     über 20 %, die drei Zonen lesen sich als EIN zusammenhängender Block
     in der Blattmitte. */
  #s6 .s6-wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "eyebrow  eyebrow"
      "headline headline"
      ".        ."
      "stations explorer"
      "stations oton"
      ".        ."
      "punch    punch"
      "close    close";
    grid-template-rows: auto auto var(--space-2xl) auto auto var(--space-2xl) auto auto;
    column-gap: var(--space-2xl);
    row-gap: var(--space-sm);
    align-items: start;
    max-width: none;
  }
  /* ---------- Szene 6 Feinschliff Runde 2 (Task DR2-1) ----------
     Stefan hat den W-B-Stand live gesichtet und drei Nachbesserungen verlangt
     (Zitat: „einige Textzeilen nicht richtig angeordnet, Textgröße muss
     überdacht und entsprechend ihrer Message angepasst werden"):

     1) Ausrichtungs-Mix im Kopf: Eyebrow und Headline erbten bislang
        `.s6-wrap`s Bildschirm-`text-align:center` (dort fürs 16:9-Bild
        gedacht) unverändert. Die Headline WIRKTE dabei zufällig linksbündig,
        weil ihr Screen-`max-width:22ch` die Box selbst schmal hält und ein
        nicht stretchendes Grid-Item ohne eigenes `justify-self` an die
        Start-Kante seiner Area rutscht (Box links bündig, Text darin aber
        weiterhin zentriert) — die Eyebrow dagegen hat kein `max-width`,
        ihre Box füllt die volle Zeile, ihr kurzer Text schwebt darin sichtbar
        mittig. Zwei verschiedene VISUELLE Ergebnisse aus derselben geerbten
        Regel, keins davon war eine bewusste Linksbündigkeit. Fix: beide
        Zeilen bekommen ihr eigenes `text-align:left` — beide Boxen beginnen
        ohnehin an derselben Grid-Spalten-Kante wie `stations` (Spalte 1 ab
        Grid-Nullpunkt), das macht sie jetzt auch TEXTUELL linksbündig auf
        exakt dieser Kante (Designsystem-Prinzip linksbündig, „Kopf gehört
        optisch zum Raster darunter").
     2) Abschlusszeile brach zweizeilig um: Screen-`max-width:46ch` (46
        Zeichen bei bislang 16px) reichte für den ~70-Zeichen-Satz nicht,
        die Box blieb dazu (wie die Headline oben) an der linken Kante
        schmal stehen, während der WEITERE Fließtext-Zeilenumbruch mittig in
        dieser schmalen Box zentriert wurde — sichtbar unter der Punchline
        „hängend", nicht auf deren Achse. Fix: `max-width:none` — die Box
        füllt jetzt wie `.s6-punch` die volle Zeile, beide behalten das
        ererbte Bildschirm-`text-align:center`, teilen sich also dieselbe
        Zentrierachse (Seitenmitte) als gemeinsame Fußzone. Bei der neuen
        Fußzone-Schriftgröße (siehe Treppe unten) passt der ganze Satz
        komfortabel in eine Zeile (am Render nachgemessen, siehe Report). Der
        Row-Gap zur Punchline bleibt der ererbte, bereits kleine
        `--space-sm` (8px, unverändert) — genau der „bewusste, kleine
        Abstand" aus dem Brief, kein neuer Wert nötig.
     3) Vertikale Löcher / gedrängte Fußzone: dieselben zwei `1fr`-Fugen aus
        W-B (Kopf→Mitte, Mitte→Fuß) waren zwar bereits gleich groß
        (Grid-Mechanik: gleicher Flex-Faktor), haben aber gemeinsam den
        Löwenanteil der 688px-Nutzhöhe geschluckt (vorher je ~138,6px ≈
        20,1 %, siehe W-B-Report), während Kopf/Fuß-Inhalt selbst schmal
        blieb (Headline erbte einen unkalibrierten Screen-Clamp, Abschluss
        war zweizeilig-schmal). Statt einer neuen Grid-Zeile: die Größen-
        Treppe unten (Punkt 4) gibt Kopf UND Fuß spürbar mehr eigene Höhe
        zurück — dieselbe Gesamthöhe verteilt sich dadurch automatisch neuer
        (weniger Rest für die zwei `1fr`-Fugen, mehr für die Zonen selbst),
        ohne die Grid-Struktur selbst anzufassen. Exakte Prozentwerte nach
        der Änderung: siehe Report (Pflicht-Messung unten).
     4) Größen-Treppe nach Botschafts-Gewicht (Brief-Vorgabe, ≥2px Stufe
        zwischen Punchline/Headline/Abschluss): die Headline hatte bislang
        GAR KEINEN eigenen Druck-Wert und erbte den Bildschirm-Clamp
        `clamp(30px,3.4vw,50px)` — bei A4-quer-Breite (~1123px) macht das
        ~38,2px und war damit GRÖSSER als die Punchline (28px fix) — exakt
        die falsche Reihenfolge (Seitentitel vor Kernbotschaft). Jetzt
        durchgängig print-eigene Fixwerte, streng absteigend: Punchline 34px
        > Headline 26px (neu, ersetzt den Clamp) > Abschlusszeile 19px
        (vorher 16px) > O-Ton 16px ≥ Stationen-/Explorer-Text 16px/13px ≥
        10px-Untergrenze. Die Stationen-Zahlen-Glyphe (`.s6-num`, 20px,
        unverändert) zählt NICHT zur Text-Treppe — sie ist ein dekoratives
        Akzent-Element (wie ein Kapitel-Ziffernblatt), keine Botschafts-Zeile
        aus dem Brief. */
  #s6 .s6-eyebrow { grid-area: eyebrow; text-align: left; }
  #s6 .s6-headline { grid-area: headline; text-align: left; font-size: 26px; }
  #s6 .s6-stations {
    grid-area: stations;
    grid-template-columns: 1fr;
    gap: var(--space-sm);
  }
  #s6 .s6-station { padding: var(--space-sm) var(--space-md); gap: var(--space-2xs); }
  #s6 .s6-num { font-size: 20px; }
  #s6 .s6-station-h { font-size: 16px; line-height: 1.2; }
  #s6 .s6-station-p { font-size: 13px; line-height: 1.45; }
  #s6 .s6-explorer-slot { grid-area: explorer; }
  #s6 .s6-explorer-slot .px-explorer { width: 100%; }
  #s6 .s6-explorer-slot .px-explorer-bar { padding: var(--space-sm) var(--space-md); }
  #s6 .s6-explorer-slot .px-folder { width: 24px; height: 24px; }
  #s6 .s6-explorer-slot .px-explorer-body { padding: var(--space-sm) var(--space-md); gap: var(--space-xs); }
  #s6 .s6-explorer-slot .px-filerow { padding: var(--space-2xs) var(--space-sm); }
  #s6 .s6-explorer-slot .px-file-ico { width: 18px; height: 20px; }
  #s6 .s6-file-name { font-size: 16px; }
  #s6 .s6-oton { grid-area: oton; font-size: 16px; }
  #s6 .s6-punch { grid-area: punch; font-size: 34px; }
  #s6 .s6-close { grid-area: close; font-size: 19px; max-width: none; }

  /* ---------- Szene 7: Der Ausbildungsplan (Task Druck-W-E) ----------
     Sichtbarkeit kommt komplett aus dem generischen .fx-*-Vokabular oben,
     Szene 7 braucht keine eigene Komposition — nur diesen einen Schutz:
     die unqualifizierte Bildschirm-Bremse @media (max-width:820px)
     { .s7-cards { grid-template-columns:1fr } } (Zeile ~2402) greift im
     Chromium-Print-Layout-Viewport der Export-Variante 1
     (prefer_css_page_size=True) nachweislich auch bei 1123px nominaler
     Seitenbreite — Blatt 8 druckte dort die drei Säulen einspaltig
     gestapelt, während Variante 2 (explizite Größe + Rand) dreispaltig
     druckt (Messbefund im Druck-W-C-Report). Controller-Entscheid:
     dreispaltig ist das Soll (Screen-Semantik der Säulen-Reihe, Muster
     wie die s9-Kennzahlen-Reihe), pfad-konsistent in BEIDEN Varianten.
     Gleiches Gegenmittel wie #s9 .s9-stats / #s10 .s10-text: ID-Präfix
     schlägt die Bremse per Spezifität, unabhängig davon ob sie matcht.
     Die Bremse setzt für s7 nur diese eine Eigenschaft (geprüft: kein
     weiteres s7-Vorkommen in den max-width-/max-height-Blöcken), darum
     genau eine Reassertion. */
  #s7 .s7-cards {
    grid-template-columns: repeat(3, 1fr);
  }

  /* ---------- Szene 8: Sie liefert ----------
     Kumulativ; RM-Endzustand (Z. 2620–2627) zeigt Vorher-Satz, den ganzen
     Wandel-Satz ("Aus mehreren Tagen werden wenige Stunden" — der zweite
     Teil kommt über das generische .fx-depth-Vokabular oben) und
     Nachher-Satz + Zitat-Zeile gemeinsam, nichts blendet weg. */
  #s8 .s8-vorher, #s8 .s8-nachher, #s8 .s8-close {
    opacity: 1 !important;
    transform: none !important;
  }
  #s8 .s8-before {
    opacity: 1 !important;
  }

  /* ---------- Szene 9: Was ich mitbringe ----------
     Referenz-Wand (fünf Namen + Trennpunkte) statisch, kein Lande-Scale
     (RM Z. 2801). Die Zähler selbst (.fx-count) sind reiner Text-Inhalt und
     laufen über den beforeprint-Handler in pitch.js, nicht über CSS. */
  #s9 .s9-wall-name, #s9 .s9-wall-sep {
    opacity: 1 !important;
    transform: none !important;
  }

  /* ---------- Szene 9 Druck-Komposition (Task Druck-W-C) ----------
     Stefan hat den Vorgängerstand live abgelehnt: Kennzahlen hingen als
     schmale linksbündige Spalte am linken Rand, rechte Seitenhälfte leer,
     darunter Wechsel auf zentriert (Label + Namens-Wand) — zwei
     Ausrichtungsprinzipien in einer Szene, dazu ein großes totes Feld
     unten. Ursache: .s9-wrap ist eine zentrierte Bildschirm-Flex-Spalte
     (max-width:min(1100px,94vw), align-items:center, text-align:center —
     fürs 16:9-Bild gebaut), die die Kennzahlen zwar bereits links ausrichtet
     (.s9-stat hat eigenes text-align:left), aber Label/Wand/Wand-Zeilen
     bleiben auf Bildschirm-Zentrierung stehen — genau die Mischung, die
     Stefan ablehnt. Zusätzlich presste der knappe Bildschirm-Gap
     (--space-2xl, 48px) beide Blöcke zu einem engen, mittig schwebenden
     Klumpen (~278px) zusammen, über und unter dem je ~200px toter Rand
     hing.

     Lösung (EIN Ausrichtungsprinzip, linksbündig, gemeinsames Raster):
     .s9-wrap bleibt die Bildschirm-Flex-Spalte, wird aber volle
     Seitenbreite (kein max-width-Deckel mehr) und komplett linksbündig —
     text-align:left kaskadiert auf Label (.s9-under) und Wand,
     align-items:flex-start hebt die Bildschirm-Zentrierung von
     .s9-refs/.s9-wall auf, justify-content:flex-start ebenso für die
     Wand-Zeilen selbst. Kennzahlen-Dreierreihe oben, Namens-Wand darunter.

     Vertikal-Balance (Review-Befund aus dem ersten W-C-Durchgang): die
     erste Fassung spannte .s9-wrap per auto/1fr/auto-Grid über die volle
     Nutzhöhe — bei nur zwei belegten Zonen riss die leere 1fr-Mittelzeile
     aber ein ~451px-Loch (66 % der Nutzhöhe) zwischen Kennzahlen und Wand:
     Stefans ursprüngliche Beschwerde (großes Leerfeld) nur von unten in
     die Mitte verschoben. Der #s6-Präzedenzfall trägt für so eine Szene
     nicht (dort trennt seit Task DR3 eine feste Token-Fuge --space-2xl
     zwei POPULIERTE Zonen, die vertikale Zentrierung kommt von der
     .scene-Flexbox — kein leeres 1fr-Loch mehr, siehe Kommentar dort).
     Statt dessen jetzt: gedeckelte Fuge gap:var(--space-4xl) (96px,
     echtes Token) zwischen den zwei Blöcken, und die vertikale
     Zentrierung übernimmt wieder die bestehende .scene-Flexbox
     (align-items:center der Bildschirm-Basisregel — dieselbe Mechanik,
     die auch das 16:9-Bild zentriert; Szene 10 löst dasselbe Problem mit
     align-content:center nur deshalb selbst, weil ihre video-stage-Hülle
     die .scene-Zentrierung umgeht). Rechnung an der A4-Nutzhöhe
     (688px zwischen den Safe-Areas): Komposition 106+96+124 ≈ 326px,
     Leerbänder ≈ 181px oben (26 %) / 96px Mitte (14 %) / 181px unten
     (26 %) — kein Band über der ~35-%-Grenze aus dem Review, Kennzahlen
     und Wand lesen sich als EIN zusammenhängender Block in der
     Blattmitte. Am echten page.pdf()-Render nachgemessen, nicht nur
     gerechnet (siehe Report, Fix-Nachtrag).

     Härtungs-Fund (Selbst-Review, echter PDF-Export statt nur DOM-Emulation):
     `grid-template-columns:repeat(3,1fr)` unten NICHT weglassen, obwohl
     `.s9-stats` das auf dem Bildschirm/in der DOM-Emulation (1123×794,
     emulate_media) bereits unverändert von der Basisregel erbt. Ein echter
     `page.pdf()`-Export (Chromium 145, Playwright) rendert `.s9-stats`
     NACHWEISLICH nach der `@media (max-width:820px) { .s9-stats {
     grid-template-columns:1fr } }`-Bildschirm-Bremse (Zeile ~2678) — alle
     drei Kennzahlen stapeln sich einspaltig statt eine Zeile zu teilen,
     OBWOHL dieselbe Seite per DOM-`getBoundingClientRect()` unter
     `emulate_media(media="print")` unmissverständlich eine Dreier-Zeile
     zeigt. `window.innerWidth` bleibt beim echten Druckdurchlauf auch im
     `beforeprint`-Handler auf der Live-Tab-Breite (hier 1280px) stehen —
     die eigentliche Druck-Layout-Passage von Chromium ist für JS nicht
     einsehbar und wertet die Breite dabei erkennbar anders (≤820px) als
     jede DOM-Messung nahelegt. Deshalb hier hart reassertiert, exakt das
     Muster von `#s6 .s6-stations` und `#s6 .s6-explorer-slot` (dort schon
     vorher entweder zufällig deckungsgleich mit der Bremse oder bereits per
     `!important` abgesichert). Nur mit dieser Zeile zeigt der ECHTE
     `page.pdf()`-Export (nicht nur die Bounding-Box-Emulation) die
     Dreier-Reihe — siehe Report für den Vorher/Nachher-Beleg. */
  #s9 .s9-wrap {
    gap: var(--space-4xl);
    max-width: none;
    text-align: left;
  }
  #s9 .s9-stats {
    grid-template-columns: repeat(3, 1fr);
  }
  /* Härtung P8: die frühere W-C-Trias (#s9 .s9-refs/.s9-wall/.s9-wall-row
     auf align-items/justify-content:flex-start) stand hier, wird aber von
     der DR2-2-Ausnahme direkt darunter unbedingt überschrieben — gleiche
     Selektoren, gleiche Spezifität (1,1,0), DR2-2 gewinnt allein durch
     spätere Quellreihenfolge (siehe Report für den Überschreibungs-Beweis).
     Tote Deklarationen gestrichen, DR2-2 unten bewusst unangetastet
     (Kommentar dort verbietet ausdrücklich ein „Zurückheilen"). */

  /* ---------- Szene 9 Namens-Wand mittig (Task DR2-2) ----------
     BEWUSSTE AUSNAHME von der Ein-Prinzip-Regel oben (W-C: „EIN
     Ausrichtungsprinzip, linksbündig, gemeinsames Raster") — kein
     Rückfall-/Zurückheil-Kandidat für einen späteren Review. Stefans
     expliziter Kunden-Entscheid (DR2-Brief): die Kennzahlen-Dreierreihe
     bleibt exakt wie von W-C gebaut (linksbündig, `.s9-stats`/`.s9-stat`
     oben unverändert), aber „DARUNTER:" + die beiden Namenszeilen sollen im
     Druck horizontal zentriert auf der Seite stehen — eine zulässige
     Banner-Ausnahme (zentrierte Namens-Parade) speziell für die Referenz-
     Wand, keine Rückkehr zur alten Bildschirm-Zentrierung der GANZEN Szene.
     Technisch: `.s9-refs` erbt sonst `.s9-wrap`s neues `text-align:left`
     (W-C) und hätte (ohne diesen Block) außerdem `align-items:flex-start`
     von der Zeile direkt oberhalb geerbt — hier lokal auf die Bildschirm-
     Werte zurückgesetzt (`center`), nur innerhalb dieses Unterbaums:
     `.s9-stats`/`.s9-stat` liegen als Geschwister AUSSERHALB von `.s9-refs`
     und bleiben unberührt. `text-align:center` auf `.s9-refs` zentriert das
     Label „Darunter:" (reiner Fließtext, keine eigene Flex-Box); die
     Namens-Wand selbst zentriert sich über `align-items:center` auf
     `.s9-wall` (jede `.s9-wall-row` ist dort ein nicht-stretchendes
     Flex-Item, sitzt also an ihrer Content-Breite zentriert statt
     linksbündig) — `justify-content:center` auf `.s9-wall-row` selbst bleibt
     zusätzlich reasserted (wie im W-C-Vorbild defensiv mitgeführt), auch wenn
     die Zeilen-Box hier bereits contentschmal ist. Kennzahlen-BBox bleibt
     dadurch nachweislich unverändert (Vorher/Nachher-Vergleich im Report). */
  #s9 .s9-refs {
    align-items: center;
    text-align: center;
  }
  #s9 .s9-wall { align-items: center; }
  #s9 .s9-wall-row { justify-content: center; }

  /* ---------- Szene 10: Der Ausbilder ----------
     Alle vier Beat-Zeilen (inkl. der Dogfooding-Zeile) + Schmunzler + dessen
     Gold-Punkt (oben in der gemeinsamen Liste), RM Z. 2925–2926. Porträt und
     Eyebrow kommen aus dem generischen Vokabular oben. */
  #s10 .s10-line, #s10 .s10-punch {
    opacity: 1 !important;
  }

  /* ---------- Szene 10 Druck-Komposition (Task Druck-W-C) ----------
     Stefan hat für den Druck explizit das Bildschirm-Nebeneinander verlangt
     (Porträt links, Text rechts), nicht den zentrierten Stapel, den der
     Vorgängerstand zeigte. Ursache: .video-stage (Hülle von Szene 1/3/8/10)
     ist position:absolute;inset:0 — für absolut positionierte Kinder ist die
     Padding-Box des nächsten positionierten Vorfahren (.scene) die
     Bezugsgröße, das Inset umgeht also .scene's eigenes Padding komplett
     (derselbe Mechanismus, der .s10-wrap auf dem Bildschirm zwingt, die
     --hud-safe-Zone selbst zu reassertieren, siehe Kommentar oben bei
     --hud-safe). Im Druck reasserted .s10-wrap darum die Safe-Areas hier
     erneut, mit den Druck-Werten statt der Bildschirm-hud-safe-Klammer und
     seitlich mit demselben --space-3xl-Rand wie jede andere Szene.

     .s10-wrap wechselt von Flex-Row (zentriert, bei ≤820px Bildschirm-Breite
     sogar auf Spalte) zu einem festen Zwei-Spalten-Grid: erste Spalte auto,
     sizt sich exakt an die feste Porträt-Breite (kein Kopplungs-Risiko
     zweier unabhängiger Maße wie bei einer Prozent-Spalte), zweite Spalte
     nimmt den Rest. Porträt fix 360px (Quellauflösung 1181×1326px laut
     width/height-Attribut — 360px ist deutlich im sicheren
     Downscale-Bereich, keine Hochskalierung, ~36 % der ca. 995px
     Nutzbreite, innerhalb der verlangten 35–40 %). #s10-Präfix schlägt die
     ≤820px-Bildschirm-Regel per Spezifität, unabhängig davon ob sie
     zusätzlich matcht (A4 quer liegt bei 1123px Breite, matcht ohnehin
     nicht, trotzdem hart abgesichert wie im Vorbild #s6/#s9).
     align-content:center zentriert die eine Grid-Zeile in der Nutzhöhe
     (ohne diese Regel bliebe die kürzere Zeile oben kleben, weil ein
     auto-Row eines Grids sich ohne align-content nicht in überschüssigem
     Raum verteilt); align-items:center (Bildschirm-Wert, hier nicht
     überschrieben) zentriert Porträt und Text zusätzlich zueinander auf der
     gemeinsamen Zeile.

     Härtungs-Fund (Selbst-Review, echter PDF-Export statt nur DOM-Emulation):
     Die ≤820px-Bremse setzt NICHT nur `.s10-text { text-align:center }`,
     sondern auch `align-items:center` (auf dem Flex-Container, Zeile ~2915).
     `text-align:left` allein (unten) schlägt zwar die erste Eigenschaft per
     ID-Spezifität, lässt `align-items:center` aber unangetastet — im echten
     `page.pdf()`-Export (nicht in der reinen Bounding-Box-Emulation)
     schrumpft `align-items:center` jede einzeilige `.s10-line` auf ihre
     Content-Breite und zentriert sie als Box, während zweizeilige Zeilen
     (Zeile 1/4, Schmunzler) zufällig die volle Spaltenbreite ausfüllen und
     dadurch flächig linksbündig WIRKEN — im Ergebnis dieselbe Mischung aus
     zwei Ausrichtungsprinzipien in einer Szene, die Stefan bei Szene 9
     bereits abgelehnt hat, hier nur pro Zeile statt pro Block. Pixelgenau
     nachgewiesen an der kurzen Zeile 2 „Ich saß auf Deiner Seite des
     Tisches.": ohne diese Zeile 51px eingerückt statt bündig mit Zeile 1
     (siehe Report). `align-items:flex-start` unten behebt das (identischer
     visueller Effekt wie der Bildschirm-Default `stretch` bei
     linksbündigem Text, hier zur Konsistenz mit `#s9 .s9-refs` gewählt). */
  #s10 .s10-wrap {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--space-2xl);
    align-content: center;
    padding: var(--print-safe-top) var(--space-3xl) var(--print-safe-bottom);
  }
  #s10 .s10-portrait {
    width: 360px;
  }
  #s10 .s10-text {
    text-align: left;
    align-items: flex-start;
  }

  /* ---------- Szene 11: Stell Dir vor ----------
     Drei Miniaturen + Doppelschlag, RM Z. 3118–3122. Headline/Abschluss
     kommen aus dem generischen .fx-depth/.fx-reveal-Vokabular oben. */
  #s11 .s11-item, #s11 .s11-doppel-a, #s11 .s11-doppel-b {
    opacity: 1 !important;
    transform: none !important;
  }

  /* ---------- Szene 12: Der erste Schritt ----------
     CTA-Block (Eyebrow/Headline/Subline) kommt komplett aus dem generischen
     Vokabular oben. Der Button-Gag "Gefunden" ist reine Bildschirm-Pointe
     (Feedback F8, aria-hidden) und druckt laut Story NICHT — der ganze Block
     verschwindet, das nimmt auch den Gag-Dateinamen aus dem PDF-Text
     (Negativ-Probe im Brief).

     ---------- Szene 12 Druck-QR-Karte (Task Druck-W-D) ----------
     Stefans Befund: der Button "Erstgespräch buchen" ergibt auf Papier
     keinen Sinn, ein QR-Code trägt dort die Conversion. Der Button wird
     direkt (nicht nur sein <p>-Wrapper) auf display:none gesetzt, damit
     auch der COMPUTED STYLE des Buttons selbst display:none zeigt (Brief-
     Vorgabe, Basiswert sonst inline-flex, siehe colors_and_type.css) — als
     Nebeneffekt fehlt der Button-TEXT dadurch komplett im PDF-Textlayer
     (display:none erzeugt keine Box, Chromiums Druck-Export legt für so ein
     Element keinen Text ab), nicht nur unsichtbar (siehe Report).

     An seiner Stelle steht eine helle QR-Karte: dasselbe wiederverwendete
     Asset wie /leistung/ (assets/img/qr-termin.svg, KEIN neues SVG), auf
     einer hellen Insel exakt nach dem .s7-card-Muster oben (kein
     [data-theme="light"]-Reset im Tokensystem, siehe Kommentar dort — hier
     lokal reassertiert, nur die zwei tatsächlich gebrauchten Tokens, kein
     Text in der Karte selbst nötig). Das SVG hat keinen eingebauten
     Quiet-Zone-Rand (roher 29×29-Modul-Pfad ab Koordinate 0, empirisch
     geprüft) — die Karten-Polsterung (--space-lg ≈ 6,35mm) liefert die
     verlangte umlaufend sichtbare helle Ruhezone, deutlich über der
     QR-Mindestmarge von 4 Modulen (≈ 4,7mm bei 34mm/29 Module). 34mm
     Kantenlänge liegt in der verlangten 30–40mm-Spanne und bleibt mit
     Puffer über der 110px-Mindestmarke (34mm × 3,7795px/mm ≈ 129px bei
     96dpi). Die bestehende URL-Zeile (.s12-secondary) bleibt unverändert
     darunter stehen und ist die einzige Beschriftung (Brief-Vorgabe: keine
     neue Beschriftung selbst texten). */
  #s12 .btn-primary {
    display: none !important;
  }
  /* ---------- Download-PDF-Sonderzustand (Task D9) ----------
     Genau EIN Unterschied zwischen Papier-Druck und Download-PDF: der
     CTA-Button ist im Download-PDF sichtbar + klickbar, zusätzlich zum
     QR-Block. tools/generate_pitch_pdf.py setzt dafür per page.evaluate()
     zur Laufzeit die Klasse body.pdf-export (NIE am Quell-HTML/-CSS
     persistiert, im Live-Betrieb auf lehnisch.de nie erreichbar — kein
     Nutzer-Pfad setzt diese Klasse) und biegt den href testweise auf die
     absolute Termin-URL um (relative hrefs erzeugen keine PDF-Link-
     Annotation). Selektor-Spezifität (Klasse+ID+Klasse) hebt die
     Basisregel darüber gezielt wieder auf; inline-flex ist der native
     Basiswert von .btn-primary (colors_and_type.css), keine neue
     Layout-Eigenart. */
  body.pdf-export #s12 .btn-primary {
    display: inline-flex !important;
  }
  #s12 .s12-qr-card {
    display: block;
    --color-surface-card: oklch(98.0% 0.004 80);
    --line-default: color-mix(in oklab, #18273A 12%, transparent);
    background: var(--color-surface-card);
    border: 1px solid var(--line-default);
    border-radius: var(--radius-lg);
    padding: var(--space-lg);
  }
  #s12 .s12-qr-img {
    display: block;
    width: 34mm;
    height: 34mm;
  }
  #s12 .s12-gag {
    display: none !important;
  }
}
