/* Einstiegs-Animation (kein Video: <img> im DOM + Audio je Beat).
   Siehe Skill intro-voiceover. Cache-Bruch ueber die Dateinummer (intro4) — die
   Nummer wird bei jeder Aenderung erhoeht, wie style9.css/script7.js im Rest
   des Projekts.

   NEU in intro4: eine Bedienung (Anhalten, Fortschritt, Springen) ganz unten in
   dieser Datei. Der Rest ist unveraendert aus intro3 uebernommen — Buehne,
   Geraeterahmen, Untertitel und die beiden Animationen bleiben, wie sie sind.

   Zwei Aenderungen gegenueber intro2:

   1. JEDER Screen steht in einem GERAET. Desktop-Ansichten im MacBook (Safari auf
      j.show, vor unscharfer Arena), mobile Ansichten im Telefon. Der Rahmen ist EIN
      Bild je Geraet — vorher war der Arena-Hintergrund in jeden mobilen Screen
      eingebrannt und lag damit ~150-mal auf dem Server. Masse kommen gemessen aus
      r/rahmen.js, nicht aus diesem Stylesheet: ein ausgetauschtes Mockup braucht
      dadurch keine CSS-Pflege.
   2. KEINE Kamerabewegung mehr. Kein Zoom, kein Schwenk, kein Scroll — die Screens
      stehen. Grund: im Geraeterahmen soll der ganze Screen zu sehen sein, und ein
      Scroll wuerde die fixe Kopfleiste und Fusszeile der Plattform mitziehen (die
      stecken im Screenshot). Rhythmus macht der Schnitt, nicht die Kamera. Die
      .bw-*-Klassen von intro2 sind deshalb weg. */

:root {
  --grund: #0b0b0d;
  --schrift: #f2f2f4;
}

/* Marken-Schrift. Der Player laeuft als eigenes Dokument im iframe, erbt also
   NICHTS von der Host-Seite — ohne diese Faces stehen Knoepfe und Untertitel im
   Browser-Default (Serife). Absolute Pfade, weil das Dokument unter /intro/
   liegt, die Fonts aber im Wurzelverzeichnis von j.show.
   Bewusst KEIN "roboto" als Rueckfall: die Familie ist projektweit nicht
   Roboto, sondern Roboto Condensed Light (siehe Memory
   reference_roboto_font_family_trap) und waere hier 168 kB fuer einen Notfall. */
@font-face {
  font-family: "Roobert";
  src: url("/Roobert-Light.woff2") format("woff2"),
       url("/Roobert-Light.woff") format("woff");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Roobert";
  src: url("/Roobert-Medium.otf") format("opentype");
  font-weight: 500; font-style: normal; font-display: swap;
}

/* Die CJK-Untertitel deckt Roobert nicht ab — der Systemfallback traegt sie. */
:root {
  --font: "Roobert", -apple-system, BlinkMacSystemFont, "Segoe UI",
          Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--grund);
  overflow: hidden;
  font-family: var(--font);
}

/* --- Vollflaechiges Overlay ------------------------------------------- */
.intro {
  position: fixed; inset: 0;
  background: var(--grund);
  color: var(--schrift);
  user-select: none;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}

/* Buehne auf 16:9 begrenzt. Der Geraeterahmen (16:9-Vollbild-Komposition) wird
   exakt auf Deckung skaliert und sitzt damit randlos; overflow:hidden faengt nur
   Rahmen ab, die vom Buehnenformat abweichen (ihr Ueberstand haengt dann
   symmetrisch ueber beide Kanten). */
.intro-buehne {
  position: relative;
  width: 100%; height: 100%;
  max-width: calc(177.78vh);
  max-height: calc(56.25vw);
  overflow: hidden;
}

/* Stapelreihenfolge der Buehne. Ohne sie malen die Bildlagen ueber Untertitel und
   Schlussbild — die Lagen haengt das JS an, sie stehen also im DOM HINTER dem
   Text. Genau daran waren die Untertitel bis 29.07.2026 unsichtbar. */
.intro-lage     { z-index: 1; }   /* JS hebt die einlaufende Lage auf 2 */
.intro-text     { z-index: 5; }
.intro-logo     { z-index: 6; }

/* --- Bildlage = ein Geraet mit einem Screen darin ---------------------- */
.intro-lage {
  position: absolute; inset: 0;
  opacity: 0;
  will-change: opacity;
}
.intro-lage.an { opacity: 1; }
.intro-lage.blende { transition: opacity 320ms ease; }

/* Kasten in der Groesse des Rahmenbildes. Position und Groesse setzt das JS:
   der Rahmen wird auf Buehnendeckung skaliert und mittig gelegt (masse() in
   intro4.js) - das Mockup-Bild ist das Filmbild. */
.intro-geraet {
  position: absolute;
  top: 0; left: 0;
  transform-origin: 0 0;
  z-index: 1;          /* ueber .intro-anim.im-geraet, siehe dort */
}
/* Der Rahmen liegt OBEN und bringt seinen Alphakanal mit (WebP): er IST die Maske
   des Displays. Was durchsichtig ist, zeigt den Screen darunter — jeder Pixel, und
   zwar in genau der Form, die im Mockup steht. Bis 02.08.2026 lag der Screen oben
   auf einem Rahmen-JPEG und die runden Ecken machte ein border-radius aus der
   Messung; der schnitt bis zu 8 px zu tief und legte in jede Displayecke einen
   schwarzen Keil (Befund Jonas, 02.08.2026). Der Alphakanal kostet dabei nichts:
   telefon.webp ist so gross wie das JPEG vorher. */
.intro-rahmen {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}
/* object-fit: cover, damit im Display nie ein schwarzer Balken steht; die
   Aufnahmeformate sind auf das Fensterverhaeltnis abgestimmt, der Beschnitt
   liegt deshalb unter einem Prozent (shoot.js rechnet die Fensterhoehe aus
   rahmen.json aus). Kein border-radius — das macht der Rahmen darueber. */
.intro-schirm {
  position: absolute;
  display: block;
  object-fit: cover;
  background: #000;
}

/* --- Kopf des Mail-Rahmens --------------------------------------------- */
/* Betreff und Empfaenger unter der Absenderzeile, die im Mockup schon steht. Sie
   liegen UEBER dem Rahmenbild (spaeter im DOM): der Kopfbereich des Mockups ist
   deckend, dort scheint kein Screenshot durch.

   Position, Breite, Schriftgrad und Zeilenabstand setzt intro4.js aus rahmen.json
   (mockup.py hat die Absenderzeile im Mockup ausgemessen) - hier steht nur, wie es
   aussieht. Die Farben sind bewusst fest und ziehen NICHT mit der hellen Fassung
   des Films mit: das Mockup zeigt ein dunkles Mailprogramm, ein heller Betreff
   darin waere ein Fremdkoerper. */
.intro-mailkopf {
  position: absolute;
  display: none;
  overflow: hidden;
  /* Dieselbe Schrift, in der das Mockup gesetzt ist. Auf Nicht-Apple-Systemen
     uebernimmt die naechste Grotesk - der Unterschied faellt in einer Zeile
     Betreff nicht auf, ein Serifenfall dagegen sofort. */
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
               Helvetica, Arial, sans-serif;
  letter-spacing: -0.01em;
  pointer-events: none;
}
.intro-mailkopf.an { display: block; }
/* Eine Zeile, notfalls mit Auslassungspunkten - genau wie ein Mailprogramm einen
   langen Betreff im Kopf abschneidet. Umbrechen duerfte er nicht: darunter steht
   schon der Empfaenger, und der Platz bis zum Lesebereich ist ausgemessen. */
.intro-mailkopf > div {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.intro-mail-betreff { color: #f0f0f0; }
.intro-mail-an {
  color: #98989e;                 /* Zweitrangig, wie die Empfaengerzeile im Mailprogramm */
  font-size: 0.88em;
}

/* --- Untertitel -------------------------------------------------------- */
/* Laufen IMMER mit, auch wenn der Ton spielt - sie sind Teil des Films, nicht
   der Ersatz fuer fehlenden Ton.
   Der Traeger ist ein Kasten NUR hinter den Textzeilen (Inline-Span, je Zeile
   umbrochen per box-decoration-break) - kein Vollbreiten-Verlauf mehr ueber
   dem unteren Bilddrittel, das Bild bleibt frei (Jonas, 31.07.2026). Der
   Kasten traegt den weissen Text auch ueber hellem Grund (Hallenboden,
   helle Animationen). */
.intro-text {
  position: absolute;
  left: 5%; right: 5%;
  /* Wie weit ueber der Buehnenunterkante der Untertitel sitzt, rechnet
     intro4.js (untertitelPlatz) - es haengt davon ab, wieviel die Bedienung
     von der Buehne wirklich verdeckt. Der Prozentwert hier ist nur der
     Rueckfall, falls das Skript noch nicht gelaufen ist. */
  bottom: var(--untertitel-unten, 10%);
  text-align: center;
  font-size: clamp(13px, 1.8vw, 28px);
  /* 1.55: Roobert-Zeilenkasten (~1.2em) + 2 x .14em Padding = ~1.48em -
     die Zeilen-Kaesten beruehren sich NICHT (sonst addieren sich die zwei
     62-%-Flaechen im Ueberlappungsstreifen zu einem dunkleren Band). Alles
     in em, die Luecke (~0.07em) bleibt also bei jeder Schriftgroesse. */
  line-height: 1.55;
  font-weight: 500;
  letter-spacing: .01em;
  color: #fff;
  opacity: 0; transition: opacity 260ms ease;
  pointer-events: none;
}
.intro-text.an { opacity: 1; }
.intro-text span {
  background: rgba(0, 0, 0, .62);
  padding: .14em .5em;
  border-radius: .22em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* --- Ueberspringen (oben rechts) ---------------------------------------- */
/* EIN Knopf statt zwei: Skip schliesst auch. Bis 01.08.2026 sass hier ein
   X (.intro-zu) und der Skip-Knopf lag unten mittig - direkt vor den
   Untertiteln (Befund Jonas). */
.intro-skip {
  position: fixed; top: clamp(14px, 2.2vw, 34px); right: clamp(14px, 2.2vw, 34px);
  z-index: 20;
  padding: clamp(12px, 1.3vh, 17px) clamp(22px, 2.4vw, 36px);
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.34);
  background: rgba(0,0,0,.42);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: #fff;
  font-family: var(--font);
  font-size: clamp(14px, 1.15vw, 18px);
  font-weight: 500; letter-spacing: .08em;
  cursor: pointer; white-space: nowrap;
  transition: background 180ms ease, border-color 180ms ease;
}
.intro-skip:hover { background: rgba(0,0,0,.7); border-color: rgba(255,255,255,.6); }

/* --- Untertitel aus ---------------------------------------------------- */
/* Der Player schreibt die Zeilen unveraendert weiter (er kennt den Schalter
   nicht) — versteckt wird hier, damit intro4.js frei von Bedien-Zustand
   bleibt. Der Schalter selbst sitzt im Menue der Bedienung, ganz unten in
   dieser Datei.

   ⛔ Hier stand bis 04.08.2026 die Auswahl-Leiste links OBEN (.intro-wahl als
   fixierte Spalte, zuletzt mit Verdunkelung und Telefon-Chevron). Sie ist
   komplett in die BEDIENUNG gewandert (Entscheid Jonas) — Sprache, Fassung,
   Wiedergabe und Untertitel liegen jetzt hinter den drei Punkten links neben
   dem Abspielknopf. Wer .intro-wahl sucht: im Abschnitt BEDIENUNG. */
body.ohne-untertitel .intro-text { display: none; }

/* --- Startschirm ------------------------------------------------------- */
/* Erscheint NUR, wenn der Browser den Ton von selbst verweigert. Dann ist
   es EIN Klick und der Film laeuft von vorn MIT Ton - kein stummer Vorlauf,
   den man nachtraeglich beschallt. Liegt unter den Knoepfen (z-index 20),
   damit Schliessen und Ueberspringen auch hier erreichbar bleiben. */
.intro-start {
  position: fixed; inset: 0; z-index: 15;
  width: 100%; height: 100%;
  margin: 0; padding: 0; border: 0;
  display: none; flex-direction: column;
  align-items: center; justify-content: center; gap: clamp(13px, 2vh, 22px);
  background: rgba(6,6,8,.5);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  color: #fff; font-family: var(--font);
  cursor: pointer;
}
.intro-start.an { display: flex; }
.intro-start-kreis {
  width: clamp(72px, 6.6vw, 108px); height: clamp(72px, 6.6vw, 108px);
  border-radius: 50%;
  background: rgba(255,255,255,.13);
  border: 1px solid rgba(255,255,255,.5);
  display: flex; align-items: center; justify-content: center;
  transition: background 200ms ease, transform 200ms ease;
}
.intro-start:hover .intro-start-kreis,
.intro-start:focus-visible .intro-start-kreis {
  background: rgba(255,255,255,.24); transform: scale(1.06);
}
/* KEIN Versatz. Das Dreieck (M8 5v14l11-7z, 24er-Feld) traegt seinen
   Flaechenschwerpunkt bei x=11,67 und ist damit von sich aus mittig - es sieht
   nur nach links versetzt aus, weil sein RAHMEN mit 8..19 rechtslastig ist. Ein
   margin-left rechnet ausserdem gegen die Kreisbreite, nicht gegen das SVG: die
   9 % von vorher waren ~10 px Schubs nach rechts. Wer das hier wieder
   "ausgleicht", verschiebt es erneut. */
.intro-start svg { width: 32%; height: 32%; fill: #fff; }
.intro-start-text {
  font-size: clamp(15px, 1.35vw, 21px);
  font-weight: 500; letter-spacing: .02em;
  text-shadow: 0 1px 14px rgba(0,0,0,.7);
}
/* Laenge des Films, eine Zeile darunter. Zurueckgenommen: sie beantwortet eine
   Frage, sie stellt keine. Leer bleibt der Kasten, wenn das Manifest keine
   Gesamtlaenge mitbringt — dann steht dort nichts statt "0:00". */
.intro-start-dauer {
  margin-top: calc(clamp(13px, 2vh, 22px) * -0.45);   /* dichter an den Text */
  font-size: clamp(12px, 1.05vw, 15px);
  font-weight: 300; letter-spacing: .04em;
  color: rgba(255,255,255,.72);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 12px rgba(0,0,0,.7);
}
.intro-start-dauer:empty { display: none; }

/* --- Schlussbild ------------------------------------------------------- */
.intro-logo {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 700ms ease;
  background: var(--grund);
  pointer-events: none;
}
.intro-logo.an { opacity: 1; }
.intro-logo svg { width: clamp(130px, 18vw, 240px); height: auto; fill: currentColor;
                  color: var(--schrift); }
.intro-logo svg path { fill: currentColor; }
.intro-logo span {
  font-size: clamp(30px, 5vw, 76px);
  font-weight: 300; letter-spacing: .15em;
}

@media (prefers-reduced-motion: reduce) {
  .intro-lage.blende { transition: opacity 200ms ease; }
}

/* =====================================================================
   ANIMATIONEN  (form: "animation" im Manifest)

   Zwei Stellen im Film bestehen NICHT aus Screenshots: die Advancing-Mail
   und das Schlussbild. Beide benutzen dieselbe abstrakte Bildsprache, die
   J.SHOW schon in seinen Spots hat — dunkler Grund, Sternenfeld, Glasflaeche,
   Magenta/Cyan-Verlauf. Sie ist deshalb Marken-Bestand und kein neuer Stil,
   und der Film wechselt zwischen genau ZWEI Ebenen: echte Oberflaeche und
   diese Abstraktion.

   Kein Geraeterahmen: eine Animation steht frei auf der Buehne. Der Rahmen
   wuerde behaupten, das hier sei ein Bildschirmfoto — ist es nicht.
   ===================================================================== */

.intro-anim {
  position: absolute; inset: 0;
  display: none;
  /* Die beiden Verlaufsfarben des Netzes und der Zahl.
     ABGENOMMEN 30.07.2026 (Jonas): VIOLETT — #A45EE5 nach #E39FF6. Das ist der
     eigene Akzent der Plattform (artist/css_farben.php), nicht der Magenta/Cyan-
     Verlauf des alten Advancing-Spots; den fand er in der Kombination zu unruhig.
     Die Variablen heissen bewusst --netz-a/--netz-b und nicht --magenta/--cyan:
     benannte Farbwerte, die dann etwas anderes enthalten, sind genau die Falle,
     ueber die spaeter jemand stolpert.
     Die verworfenen Kombinationen stehen unten und lassen sich ueber data-farbe
     am .intro-anim wieder einschalten. Zum Vergleichen:
     stuff/marketing-ads/landingpage-intro/animation_vorschau.html */
  --netz-a: #A45EE5;
  --netz-b: #E39FF6;
  /* Laufzeit-Faktor der Keyframes. 1 = wie entworfen; die Tempo-Wahl des
     Zuschauers setzt --film-zeit am Wurzelknoten auf den Kehrwert (2x Tempo =
     0.5), damit die Animationen mit dem Film mitziehen statt in Wanduhrzeit
     danebenzulaufen. Der Rueckfall 1 gilt, solange niemand etwas gewaehlt hat
     — und auch im Tutorial-Player, der keine Tempo-Wahl hat. */
  --tempo: var(--film-zeit, 1);
}

/* Verworfene Farbvarianten — nur zum Wiederansehen, nicht im Einsatz. */
.intro-anim[data-farbe="magenta_cyan"] { --netz-a: #e6007e; --netz-b: #00b9d7; }
.intro-anim[data-farbe="violett_warm"] { --netz-a: #A45EE5; --netz-b: #D16002; }
.intro-anim[data-farbe="warm"]         { --netz-a: #D16002; --netz-b: #E5C100; }
.intro-anim[data-farbe="neutral"]      { --netz-a: #9aa0a6; --netz-b: #e8eaed; }
.intro-anim[data-farbe="violett_solo"] { --netz-a: #8e46d0; --netz-b: #A45EE5; }
.intro-anim.an { display: block; }

/* Sternenfeld: ein wiederholtes Radialverlaufs-Muster statt hunderter Knoten.
   Kostet einen Malvorgang statt 300 DOM-Elementen und sieht bei dieser Groesse
   identisch aus. */
.anim-sterne {
  position: absolute; inset: 0;
  background-image:
    radial-gradient(1.2px 1.2px at 20% 30%, rgba(255,255,255,.55), transparent),
    radial-gradient(1px 1px at 70% 20%, rgba(255,255,255,.4), transparent),
    radial-gradient(1.4px 1.4px at 45% 75%, rgba(255,255,255,.5), transparent),
    radial-gradient(1px 1px at 85% 65%, rgba(255,255,255,.35), transparent),
    radial-gradient(1px 1px at 12% 85%, rgba(255,255,255,.3), transparent);
  background-size: 42% 38%, 55% 47%, 38% 44%, 61% 52%, 47% 41%;
  opacity: 0; animation: sterneAuf calc(1.4s * var(--tempo)) ease forwards;
}
@keyframes sterneAuf { to { opacity: .9; } }

/* --- Advancing-Mail --------------------------------------------------- */

.anim-mail {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(78%, 900px);
  background: rgba(24, 24, 28, .92);
  border: 1px solid rgba(255,255,255,.13);
  border-radius: 16px;
  box-shadow: 0 30px 90px rgba(0,0,0,.6);
  overflow: hidden;
  opacity: 0; transform: translate(-50%, -46%);
  animation: mailAuf calc(.7s * var(--tempo)) ease forwards;
}
@keyframes mailAuf { to { opacity: 1; transform: translate(-50%, -50%); } }

.anim-mail-kopf {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 16px;
  border-bottom: 1px solid rgba(255,255,255,.09);
}
.anim-mail-kopf i {
  width: 11px; height: 11px; border-radius: 50%;
  background: rgba(255,255,255,.22); display: block;
}
.anim-mail-kopf b {
  margin-left: 10px; font-weight: 500; font-size: 13px;
  letter-spacing: .08em; text-transform: uppercase;
  color: rgba(255,255,255,.55);
}
.anim-mail-leib { padding: 18px 22px 24px; }

.anim-zeile {
  display: flex; gap: 12px; padding: 7px 0;
  border-bottom: 1px solid rgba(255,255,255,.06);
  font-size: 16px; line-height: 1.4;
  opacity: 0; animation: zeileAuf calc(.45s * var(--tempo)) ease forwards;
}
.anim-zeile span { color: rgba(255,255,255,.42); min-width: 62px; }
.anim-zeile em { font-style: normal; color: var(--schrift); }
@keyframes zeileAuf { to { opacity: 1; } }

/* Der getippte Cursor: eine Kante, die blinkt. Das Tippen selbst macht JS
   (Zeichen fuer Zeichen), weil eine CSS-steps()-Animation die Breite und damit
   die Schriftmetrik raten muesste. */
.anim-tipp::after {
  content: ""; display: inline-block;
  width: 2px; height: 1.05em; margin-left: 2px;
  vertical-align: -.18em; background: var(--schrift);
  animation: blinken 1s steps(1) infinite;
}
@keyframes blinken { 50% { opacity: 0; } }

.anim-vorschlag {
  margin: 6px 0 0 74px;
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 10px; padding: 10px 14px;
  max-width: 340px;
  opacity: 0; transform: translateY(-6px);
  animation: vorschlagAuf calc(.35s * var(--tempo)) ease forwards;
}
@keyframes vorschlagAuf { to { opacity: 1; transform: none; } }
.anim-vorschlag b { display: block; font-weight: 500; font-size: 16px; }
.anim-vorschlag i {
  display: block; font-style: normal; font-size: 13px;
  color: rgba(255,255,255,.45); margin-top: 2px;
}

.anim-text {
  margin-top: 16px; font-size: 15.5px; line-height: 1.6;
  color: rgba(255,255,255,.82);
  opacity: 0; animation: zeileAuf calc(.5s * var(--tempo)) ease forwards;
}
.anim-zitat {
  margin-top: 12px; padding-left: 12px;
  border-left: 2px solid rgba(255,255,255,.18);
  font-size: 14.5px; line-height: 1.55;
  color: rgba(255,255,255,.42);
  opacity: 0; animation: zeileAuf calc(.5s * var(--tempo)) ease forwards;
}

/* --- Schlussbild: das Netz -------------------------------------------- */

.anim-netz {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
}
.anim-netz svg { width: 100%; height: 100%; }

/* Die Kanten zeichnen sich; --len kommt je Linie aus netz_bauen.py, weil eine
   feste dasharray bei 388 unterschiedlich langen Kanten entweder die kurzen
   sofort fertig haette oder die langen nie. */
.anim-netz .kante {
  stroke: url(#gnetz); stroke-width: .9; opacity: .5;
  stroke-dasharray: var(--len); stroke-dashoffset: var(--len);
  animation: kanteZieht calc(.9s * var(--tempo)) ease forwards;
}
@keyframes kanteZieht { to { stroke-dashoffset: 0; } }

.anim-netz .knoten {
  fill: var(--schrift); opacity: 0;
  animation: knotenAuf calc(.5s * var(--tempo)) ease forwards;
}
@keyframes knotenAuf { to { opacity: .95; } }

.anim-netz .puls {
  fill: var(--netz-b); opacity: 0;
  animation: pulsAuf calc(.6s * var(--tempo)) ease forwards;
}
@keyframes pulsAuf { to { opacity: .9; } }

.anim-schluss {
  position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  text-align: center; padding: 0 8%;
  z-index: 2;                       /* ueber dem Netz */
}
/* Traeger unter dem Schlusssatz. Ohne ihn laufen die Linien und Knoten des Netzes
   durch die Buchstaben und der Satz ist nicht mehr zu lesen — genau dort steht aber
   der einzige Satz des Films, der etwas verlangt. Kein Kasten und keine Kante: ein
   weicher Radialverlauf, der zur Mitte hin deckt und nach aussen verschwindet. Das
   Netz bleibt sichtbar, es tritt nur hinter den Text zurueck. */
.anim-schluss::before {
  content: ""; position: absolute; z-index: -1;
  left: -4%; right: -4%; top: -70%; bottom: -70%;
  background: radial-gradient(58% 52% at 50% 50%,
    rgba(11,11,13,.93) 0%, rgba(11,11,13,.86) 38%,
    rgba(11,11,13,.55) 66%, rgba(11,11,13,0) 100%);
  pointer-events: none;
}
/* Der Schlusssatz steht IM Bild — er ist das Schlussbild, nicht nur Untertitel.
   Deshalb je Satz eine Zeile und ruhige Groesse: er soll lesbar sein, nicht
   plakatieren. Das einzige grosse Wort des Films faellt hier. */
.anim-satz {
  font-size: clamp(19px, 3.1vw, 38px); font-weight: 300;
  line-height: 1.35; letter-spacing: -.005em;
  color: var(--schrift); margin: 0 auto 6px; max-width: 22em;
  text-shadow: 0 1px 14px rgba(0,0,0,.55);
  opacity: 0; animation: zeileAuf calc(.7s * var(--tempo)) ease forwards;
}
/* Die Zahl steht INNERHALB des Satzes und nicht daneben: allein gestellt wirkte
   sie wie eine Behauptung, im Satz ist sie ein Teil der Einladung. */
.anim-zahl {
  font-weight: 500;
  background: linear-gradient(90deg, var(--netz-a), var(--netz-b));
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.anim-wortmarke {
  margin: 26px auto 0; opacity: 0;
  animation: zeileAuf calc(.6s * var(--tempo)) ease forwards;
  color: var(--schrift);
}
/* Die echte Wortmarke ist ein SVG ohne fill-Angabe (Illustrator-Export) —
   currentColor holt sie aus der Schriftfarbe, damit sie hell auf dunkel steht. */
.anim-wortmarke svg { width: clamp(120px, 16vw, 210px); height: auto; display: inline-block;
                      fill: currentColor; }
.anim-wortmarke svg path { fill: currentColor; }
.anim-wortmarke span { font-size: clamp(18px, 2.6vw, 30px); font-weight: 500;
                       letter-spacing: .16em; }

@media (prefers-reduced-motion: reduce) {
  /* Wer Bewegung abbestellt hat, bekommt die Endzustaende sofort - nicht
     nichts. Ein leeres Schlussbild waere schlechter als ein statisches. */
  .intro-anim * { animation-duration: .01ms !important; animation-delay: 0s !important; }
}

/* --- Animationen im Hellmodus ------------------------------------------
   Die Buehne bleibt immer dunkel — sie ist der Kinorand um das Geraet. Die
   Animationen aber fuellen das ganze Bild, und dort muss das Schema zu den
   Screens ringsum passen: ein schwarzes Vollbild mitten in einem hellen Film
   waere ein Fremdkoerper — und ein weisses mitten in einem dunklen genauso.

   ⚠ Diese Regeln greifen NUR, wenn der Bildersatz wirklich hell ausgespielt
   ist. Seit 01.08.2026 wird nur noch dunkel geschossen, deshalb haengt
   intro4.js die Klasse .hell an dasselbe bildschema() wie die Bilder und nicht
   mehr an die Systemeinstellung des Betrachters. Der Block bleibt trotzdem
   stehen: liegt fuer einen Film ein light/-Satz daneben, greift er sofort
   wieder — Dark-only ist ein Standard, keine Einbahnstrasse.

   Der Untertitel bleibt weiss — sein Zeilen-Kasten (.intro-text span) traegt
   ihn auch ueber hellem Grund. */
.hell .intro-anim {
  background: #f4f4f6;
  --schrift-anim: #17171a;
}
.hell .intro-anim .anim-sterne {
  /* Sterne auf Weiss waeren unsichtbar: dieselbe Verteilung, nur dunkel und
     deutlich zurueckgenommen — es soll ein Rauschen sein, kein Punktmuster. */
  background-image:
    radial-gradient(1.2px 1.2px at 20% 30%, rgba(0,0,0,.20), transparent),
    radial-gradient(1px 1px at 70% 20%, rgba(0,0,0,.14), transparent),
    radial-gradient(1.4px 1.4px at 45% 75%, rgba(0,0,0,.18), transparent),
    radial-gradient(1px 1px at 85% 65%, rgba(0,0,0,.12), transparent),
    radial-gradient(1px 1px at 12% 85%, rgba(0,0,0,.10), transparent);
}
.hell .intro-anim .anim-mail {
  background: rgba(255,255,255,.96);
  border-color: rgba(0,0,0,.12);
  box-shadow: 0 24px 70px rgba(0,0,0,.18);
}
.hell .intro-anim .anim-mail-kopf { border-bottom-color: rgba(0,0,0,.10); }
.hell .intro-anim .anim-mail-kopf i { background: rgba(0,0,0,.16); }
.hell .intro-anim .anim-mail-kopf b { color: rgba(0,0,0,.48); }
.hell .intro-anim .anim-zeile { border-bottom-color: rgba(0,0,0,.07); }
.hell .intro-anim .anim-zeile span { color: rgba(0,0,0,.42); }
.hell .intro-anim .anim-zeile em { color: var(--schrift-anim); }
.hell .intro-anim .anim-tipp::after { background: var(--schrift-anim); }
.hell .intro-anim .anim-vorschlag {
  background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.13);
  color: var(--schrift-anim);
}
.hell .intro-anim .anim-vorschlag i { color: rgba(0,0,0,.45); }
.hell .intro-anim .anim-text  { color: rgba(0,0,0,.78); }
.hell .intro-anim .anim-zitat { color: rgba(0,0,0,.42); border-left-color: rgba(0,0,0,.18); }

/* Netz: die Kanten behalten den Markenverlauf (er traegt auf Hell wie auf Dunkel),
   die Knoten werden dunkel — helle Punkte waeren auf Weiss nicht zu sehen. */
.hell .intro-anim .anim-netz .knoten { fill: var(--schrift-anim); }
.hell .intro-anim .anim-netz .kante  { opacity: .62; }
.hell .intro-anim .anim-schluss::before {
  background: radial-gradient(58% 52% at 50% 50%,
    rgba(244,244,246,.94) 0%, rgba(244,244,246,.88) 38%,
    rgba(244,244,246,.58) 66%, rgba(244,244,246,0) 100%);
}
.hell .intro-anim .anim-satz {
  color: var(--schrift-anim);
  text-shadow: 0 1px 14px rgba(255,255,255,.75);
}
.hell .intro-anim .anim-wortmarke { color: var(--schrift-anim); }

/* ====================================================================== */
/* BEDIENUNG (neu ab intro4)                                              */
/*                                                                        */
/* Bis intro3 gab es keine: der Film lief von vorn bis hinten durch, weil  */
/* "ended" je MP3 die Uhr war und niemand wusste, wie lang das Ganze ist.  */
/* Seit die Zeit aus currentTime EINER durchgehenden Kapitelspur kommt,    */
/* sind Anhalten, Fortschritt und Springen ueberhaupt erst moeglich.       */
/*                                                                        */
/* Die Leiste zeigt die KAPITEL als eigene Abschnitte statt als einen      */
/* Balken - man sieht, wie lang ein Abschnitt ist, springt gezielt hinein  */
/* und liest beim Darueberfahren, worum es dort geht (der Titel kommt aus  */
/* dem gesprochenen Text, ist also in jeder Sprache vorhanden, ohne dass   */
/* dafuer etwas uebersetzt werden muesste).                               */
/* ====================================================================== */

.intro-bedienung {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 22;
  display: flex; align-items: center;
  gap: clamp(12px, 1.6vw, 22px);
  padding: clamp(30px, 5vh, 64px) clamp(16px, 3vw, 40px) clamp(14px, 2.4vh, 26px);
  /* Traeger fuer die Leiste: ohne ihn verschwinden duenne weisse Linien auf
     einem hellen Screenshot. Liegt UNTER dem Untertitel-Schleier, damit sich
     die beiden Verlaeufe nicht zu einem schwarzen Balken addieren. */
  background: linear-gradient(to top,
    rgba(0,0,0,.78) 0%, rgba(0,0,0,.45) 55%, rgba(0,0,0,0) 100%);
  opacity: 0; pointer-events: none;
  transition: opacity 240ms ease;
}
.intro-bedienung.an { opacity: 1; pointer-events: auto; }

/* Anhalten/Weiter und Menue ------------------------------------------------ */
/* Die beiden runden Knoepfe teilen sich EINE Regel (Entscheid Jonas
   04.08.2026: „gleiche Groesse wie der Play-Knopf"). Zweimal dieselben
   clamp()-Werte zu schreiben hiesse, dass sie beim naechsten Nachjustieren
   still auseinanderlaufen — und genau nebeneinander faellt jeder Pixel auf. */
.intro-spiel,
.intro-menue-knopf {
  flex: none;
  width: clamp(40px, 3.4vw, 54px); height: clamp(40px, 3.4vw, 54px);
  border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  background: rgba(255,255,255,.14);
  color: var(--schrift);
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background 160ms ease, transform 160ms ease;
}
.intro-spiel:hover,
.intro-menue-knopf:hover { background: rgba(255,255,255,.26); }
.intro-spiel:active,
.intro-menue-knopf:active { transform: scale(.93); }
.intro-spiel svg,
.intro-menue-knopf svg { width: 44%; height: 44%; fill: currentColor; display: block; }
/* Zwei Glyphen im Knopf, umgeschaltet wird per Klasse - ein ausgetauschtes
   innerHTML liesse den Knopf bei jedem Druck kurz neu zeichnen. */
.intro-spiel .zeichen-pause { display: none; }
.intro-spiel.laeuft .zeichen-pause { display: block; }
.intro-spiel.laeuft .zeichen-play  { display: none; }

/* Menue (drei Punkte) und sein Overlay ------------------------------------- */
/* Hier sitzt seit 04.08.2026 die Auswahl, die bis dahin als eigene Leiste links
   OBEN im Bild stand (Entscheid Jonas). Zwei Dinge werden dadurch von selbst
   richtig: das Filmbild ist frei, und die Auswahl verschwindet zusammen mit der
   uebrigen Bedienung, sobald der Film laeuft und niemand die Maus bewegt — es
   braucht keine zweite Ausblend-Regel und kein Verdunkeln.

   Damit das Overlay dabei nicht unter den Fingern wegblendet, laesst intro4.js
   (bedienZeigen) die Leiste stehen, solange `.intro-menue.auf` gesetzt ist. */
.intro-menue { position: relative; flex: none; display: flex; }
.intro-menue-knopf svg circle { fill: currentColor; }
/* Offen bleibt der Knopf hell — er ist dann der Griff zum Zumachen. */
.intro-menue.auf .intro-menue-knopf { background: rgba(255,255,255,.26); }

/* Klappt nach OBEN auf: unter dem Knopf ist der Fensterrand, darueber Platz. */
.intro-wahl {
  position: absolute; bottom: calc(100% + 12px); left: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  gap: clamp(8px, 1.1vh, 12px);
  padding: clamp(12px, 1.6vh, 17px) clamp(14px, 1.2vw, 19px);
  border-radius: 14px;
  border: 1px solid rgba(255,255,255,.16);
  background: rgba(12,12,16,.88);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 14px 44px rgba(0,0,0,.55);
}
/* `mit-js` setzt das Skript in index.php. Ohne JavaScript steht die Auswahl
   offen da statt hinter einem Knopf, der nichts aufklappen kann — der
   <noscript>-Block dort holt dazu auch die Bedienleiste ins Sichtbare. */
.intro-menue.mit-js .intro-wahl { display: none; }
.intro-menue.mit-js.auf .intro-wahl {
  display: flex;
  animation: intro-menue-ein 150ms ease both;
}
@keyframes intro-menue-ein {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .intro-menue.mit-js.auf .intro-wahl { animation: none; }
}

/* Eine Zeile = Beschriftung links, Feld rechts. Die Beschriftung stand bis
   04.08.2026 nur im aria-label; wer „Pro" oder „1×" las, musste raten, worauf
   sich das bezieht. */
.intro-wahl-zeile {
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(14px, 1.6vw, 26px);
}
.intro-wahl-name {
  flex: none;
  color: rgba(242,242,244,.72);
  font-size: clamp(11px, .82vw, 13px);
  font-weight: 300; letter-spacing: .02em;
  white-space: nowrap;
  cursor: pointer;
}

/* Glas-Pille fuer die Felder im Overlay: <select> und der <noscript>-Knopf,
   der sonst als nackter Systemknopf darunter saesse.
   Heller Fond statt des frueheren schwarzen: die Pillen liegen jetzt IM
   dunklen Overlay, nicht mehr direkt auf dem Filmbild.

   ⛔ Das Untertitel-Kaestchen gehoert seit 04.08.2026 NICHT mehr dazu
   (Entscheid Jonas). Warum es raus musste, steht unten bei .intro-chip. */
.intro-wahl select,
.intro-wahl button {
  appearance: none; -webkit-appearance: none;
  flex: none;
  text-align: left;
  padding: clamp(5px, .6vh, 7px) clamp(20px, 1.7vw, 26px) clamp(5px, .6vh, 7px) clamp(9px, .9vw, 12px);
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.3);
  background-color: rgba(255,255,255,.09);
  color: var(--schrift);
  font-family: var(--font);
  font-size: clamp(11px, .8vw, 13px);
  font-weight: 500;
  cursor: pointer;
}
/* Alle Felder gleich breit: sonst endet die rechte Kante bei „Deutsch", „Pro"
   und „1×" dreimal woanders und die Spalte franst aus. */
.intro-wahl select {
  width: clamp(112px, 9vw, 148px);
  /* Pfeil als Data-URI: der Player laedt sonst nichts nach, und ein Zeichen aus
     der Schrift saesse je nach Schriftschnitt anders. */
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right clamp(5px, .55vw, 8px) center;
  background-size: clamp(12px, 1vw, 14px);
}
.intro-wahl select:hover,
.intro-wahl button:hover { background-color: rgba(255,255,255,.2); border-color: rgba(255,255,255,.55); }
.intro-wahl select:focus-visible,
.intro-wahl button:focus-visible { outline: 2px solid rgba(255,255,255,.8); outline-offset: 2px; }
/* Die Klappliste selbst zeichnet das System — dort gilt kein Glas, also dunkel
   setzen, sonst steht weisse Schrift auf weissem Grund. */
.intro-wahl option { background: #14141a; color: #fff; }

/* Untertitel an/aus. Ein Kaestchen, kein Auswahlmenue: ob Zeilen kommen, ist
   ja/nein, und ein Kaestchen sagt das auf einen Blick. Es steckt in einem
   <label>, damit Tastatur (Leertaste) und Vorlese-Name vom Browser kommen,
   ohne dass wir etwas nachbauen. Das Wort dazu steht links in der Zeile
   (zweites <label> ueber `for`).

   ⛔ NACKT, nicht in einer Glas-Pille, und LINKS statt rechts (Entscheid Jonas
   04.08.2026). Die Pille sah aus wie die <select> daneben und versprach damit
   eine Auswahl, die es nicht gibt — ein Kaestchen ist ja/nein und braucht kein
   Feld drumherum. Die Breite bleibt trotzdem die der <select>: dadurch steht
   das Kaestchen genau unter deren linker Textkante („Deutsch", „Pro", „1×")
   und die Spalte behaelt ihre Flucht. */
.intro-wahl .intro-chip {
  flex: none;
  width: clamp(112px, 9vw, 148px);
  display: flex; align-items: center; justify-content: flex-start;
  padding: clamp(5px, .6vh, 7px) clamp(9px, .9vw, 12px);
  cursor: pointer;
  -webkit-user-select: none; user-select: none;
}
.intro-wahl .intro-chip:focus-within input {
  outline: 2px solid rgba(255,255,255,.8); outline-offset: 2px;
}
.intro-wahl .intro-chip:hover input { border-color: rgba(255,255,255,.9); }
.intro-wahl .intro-chip input {
  appearance: none; -webkit-appearance: none;
  flex: 0 0 auto;
  width: 13px; height: 13px; margin: 0;
  border: 1px solid rgba(255,255,255,.55); border-radius: 3px;
  background: transparent;
  cursor: pointer;
}
.intro-wahl .intro-chip input:checked {
  border-color: #fff; background-color: #fff;
  /* Haken als Data-URI, dunkel auf Weiss — dieselbe Ueberlegung wie beim
     Klapp-Pfeil: nichts nachladen, nichts aus der Schrift borgen. */
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2314141a' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 10px;
}

/* Fortschritt, Kapitel fuer Kapitel --------------------------------------- */
.intro-leiste {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 4px;
  height: 26px;                      /* Greiffläche, nicht die sichtbare Höhe */
  cursor: pointer;
  touch-action: none;                /* sonst scrollt das Ziehen die Seite */
}
.intro-kap {
  position: relative;
  height: 5px; border-radius: 3px;
  background: rgba(255,255,255,.26);
  transition: height 140ms ease, background 140ms ease;
}
.intro-leiste:hover .intro-kap,
.intro-leiste.zieht .intro-kap { height: 8px; }
.intro-kap:hover, .intro-kap.hier { background: rgba(255,255,255,.42); }
.intro-kap > i {
  position: absolute; inset: 0;
  border-radius: inherit;
  background: var(--schrift);
  transform: scaleX(0); transform-origin: left center;
}
/* Der Griff sitzt im laufenden Kapitel, nicht auf der Gesamtleiste: mit den
   Luecken zwischen den Abschnitten waere eine Prozentangabe ueber alles um
   ein paar Pixel daneben — und genau daneben, wo man hinschaut. */
.intro-kap > b {
  position: absolute; top: 50%; left: 0;
  width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px;
  border-radius: 50%; background: var(--schrift);
  box-shadow: 0 1px 5px rgba(0,0,0,.5);
  opacity: 0; transition: opacity 140ms ease;
  pointer-events: none;
}
.intro-leiste:hover .intro-kap > b,
.intro-leiste.zieht .intro-kap > b { opacity: 1; }

/* Beim Darueberfahren steht da, worum es im Kapitel geht — der erste
   gesprochene Satz. Deshalb ohne jede Uebersetzungsarbeit in allen Sprachen
   vorhanden. */
.intro-kap[data-titel]:hover::after {
  content: attr(data-titel);
  position: absolute; bottom: 18px; left: 50%;
  transform: translateX(-50%);
  max-width: min(46vw, 380px); width: max-content;
  padding: 7px 11px; border-radius: 8px;
  background: rgba(12,12,14,.94);
  border: 1px solid rgba(255,255,255,.14);
  color: var(--schrift);
  font-size: clamp(11px, 1.05vw, 14px); line-height: 1.35;
  font-weight: 300; text-align: center;
  white-space: normal; pointer-events: none;
}

.intro-uhr {
  flex: none;
  font-size: clamp(11px, 1.05vw, 14px);
  font-weight: 300;
  color: rgba(242,242,244,.72);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* Vollbild (nur eingebettet) ---------------------------------------------- */
/* Steht ganz rechts, wie an jedem Abspielgeraet. Bewusst KLEINER als die
   beiden runden Knoepfe links: Abspielen und Einstellungen sind die Bedienung
   des Films, Vollbild ist die Bedienung des KASTENS — dieselbe Groesse haette
   die drei zu einer Reihe gleichrangiger Knoepfe gemacht, in der der
   Abspielknopf seinen Vorrang verliert. Ein Rahmen statt einer Fuellung sagt
   dasselbe noch einmal.

   Im Overlay rendert index.php ihn gar nicht erst; die Regel greift also nur
   dort, wo `?embed=1` steht. */
.intro-voll {
  flex: none;
  width: clamp(32px, 2.6vw, 40px); height: clamp(32px, 2.6vw, 40px);
  border-radius: 50%; padding: 0; cursor: pointer;
  border: 1px solid rgba(255,255,255,.24);
  background: rgba(255,255,255,.06);
  color: rgba(242,242,244,.82);
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background 160ms ease, border-color 160ms ease,
              color 160ms ease, transform 160ms ease;
}
.intro-voll:hover {
  background: rgba(255,255,255,.18);
  border-color: rgba(255,255,255,.5);
  color: var(--schrift);
}
.intro-voll:active { transform: scale(.93); }
.intro-voll:focus-visible { outline: 2px solid rgba(255,255,255,.8); outline-offset: 2px; }
.intro-voll svg { width: 52%; height: 52%; fill: currentColor; display: block; }
/* Zwei Glyphen im Knopf, umgeschaltet per Klasse am <body> (intro4.js setzt sie
   aus dem fullscreenchange-Ereignis, nicht aus der Annahme) — dieselbe Loesung
   wie beim Abspiel-/Anhalten-Knopf. */
.intro-voll .zeichen-voll-aus { display: none; }
body.voll .intro-voll .zeichen-voll-aus { display: block; }
body.voll .intro-voll .zeichen-voll { display: none; }

/* Angehaltene Animationen bleiben stehen. Ohne das liefe das Netz im
   Schlussbild weiter, waehrend der Ton pausiert — es sieht dann aus, als
   haette der Knopf nicht gegriffen. */
.intro.pausiert .intro-anim * { animation-play-state: paused !important; }

/* Platz fuer die Leiste ---------------------------------------------------- */
/* Der Untertitel stand bis intro3 dort, wo jetzt die Bedienung liegt. Er
   rueckt hoch, sobald sie eingeblendet ist — nicht dauerhaft, sonst saesse
   er auch im Vollbild ohne Bedienung zu hoch im Bild. (Der Skip-Knopf sass
   bis 01.08.2026 ebenfalls unten und rueckte mit; er liegt jetzt oben
   rechts und braucht keinen Ausweichplatz mehr.)

   ⛔ Hier steht bewusst KEINE Regel mehr. Bis 02.08.2026 stand hier
   `bottom: clamp(92px, 17%, 210px)` — und darin steckte ein
   Masseinheiten-Bruch: der Untertitel misst von der BUEHNE, die Bedienung
   klebt am FENSTER. Am Schreibtisch faellt das nicht auf, weil die Buehne
   fast bis zum Fensterrand reicht. Im Hochformat endet die 16:9-Buehne weit
   darueber (gemessen 390x844: Buehne bis y 532, Bedienung ab y 792) - die
   92 px Mindestabstand schoben den Untertitel dort ohne jeden Grund mitten
   ins Bild, waehrend darunter 312 px Schwarz leer blieben. Er deckte zwei
   Drittel des Films zu und ragte oben sogar aus ihm heraus.
   Den Abstand rechnet jetzt intro4.js (untertitelPlatz) aus der echten
   Geometrie: ausgewichen wird nur dem, was die Bedienung von der Buehne
   tatsaechlich verdeckt. Ergebnis steht in --untertitel-unten. */

@media (max-width: 640px) {
  .intro-bedienung { gap: 10px; padding-bottom: 12px; }
  .intro-uhr { display: none; }         /* auf dem Telefon zaehlt die Leiste */
  .intro-kap[data-titel]:hover::after { display: none; }
}

/* --- Eingebettet (?embed=1) ---------------------------------------------- */
/* Der Player steht dann in einem 16:9-Kasten mitten auf der Startseite statt
   als Vollbild-Overlay. Alle Masse hier rechnen in vh/vw — das sind im iframe
   die Masse des KASTENS, nicht des Browserfensters. Die Bedienung schrumpft
   damit von selbst mit und waechst im Vollbild wieder auf die volle Groesse,
   ohne dass es dafuer einen zweiten Satz Regeln braucht.

   Zwei Stellen rechnen sich trotzdem nicht von selbst zurecht: */

/* 0. Der Startschirm ist eingebettet nicht mehr die Ausnahme („der Browser hat
      den Ton verweigert"), sondern der REGELFALL: der Player steht bereit und
      wartet auf den Druck. Damit ist er das, was der Besucher der Startseite
      von diesem Kasten zuerst sieht — und dann darf er den Screenshot
      dahinter nicht wegweichzeichnen. Der Screenshot IST das Argument.

      Statt Schleier + Weichzeichner deshalb eine Verdunkelung, die in der
      MITTE am staerksten ist: genau dort liegen Kreis und Wort, zu den
      Raendern hin bleibt das Bild offen. Dieselbe Form wie beim Standbild der
      Startseite (.film-schleier in style.css) — die beiden loesen sich
      gegenseitig ab, ein sichtbarer Wechsel dabei waere ein Fehler. */
body.eingebettet .intro-start {
  background: radial-gradient(118% 92% at 50% 47%,
    rgba(4,4,7,.66) 0%, rgba(4,4,7,.42) 42%, rgba(4,4,7,.14) 100%);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}

/* 1. Das Einstellungs-Overlay klappt nach oben auf und ist mit vier Zeilen
      rund 190 px hoch. Auf dem Telefon ist der Kasten 16:9 auf ~360 px Breite,
      also ~200 px HOCH — das Overlay waere hoeher als der Film und wuerde oben
      abgeschnitten (html/body stehen auf overflow:hidden). Eine Deckelung mit
      Bildlauf ist ehrlicher als ein stiller Beschnitt; im Vollbild greift sie
      nicht mehr, dort ist wieder Platz. */
body.eingebettet .intro-wahl {
  max-height: calc(100vh - clamp(58px, 11vh, 96px));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* 2. Der Traeger der Bedienung hat oben clamp(30px, …) Innenabstand fuer den
      Verlauf. In einem 200 px hohen Kasten sind das 15 % des Bildes fuer einen
      Schatten — im Fenster waren es 3 %. Ab hier also enger. Greift auch im
      Vollbild auf einem quer gehaltenen Telefon, und ist dort genauso richtig.

      Im selben Zug rueckt das Einstellungs-Overlay zusammen. Gerechnet auf
      einem 360x203-Kasten (Telefon, 16:9): mit den normalen Massen ist es
      ~148 px hoch und sitzt ~61 px ueber der Unterkante — zusammen 209 px in
      einem 203 px hohen Bild, also oben angeschnitten. Mit den engeren Massen
      hier sind es ~136 px und es passt. Die Deckelung oben bleibt trotzdem
      stehen: sie ist das Netz fuer alles, was noch schmaler kommt. */
@media (max-height: 400px) {
  body.eingebettet .intro-bedienung {
    padding-top: 16px; padding-bottom: 9px;
    gap: 9px;
  }
  body.eingebettet .intro-wahl {
    gap: 6px;
    padding: 9px 11px;
    border-radius: 12px;
  }
  body.eingebettet .intro-wahl-zeile { gap: 12px; }
}

/* ---------------------------------------------------------------------------
   Push-Benachrichtigung auf dem Sperrbildschirm (anim_push)
   ---------------------------------------------------------------------------
   Sitzt IM Telefon-Rahmen ("geraet": "telefon" am Bild in kapitel.json). Der
   Player legt .intro-anim dafuer genau auf die Displayflaeche, die sonst der
   Screenshot bekommt, und setzt dort font-size = 1 % der Displayhoehe. Alle
   Masse hier stehen deshalb in em und sind damit an das GERAET gebunden, nicht
   an das Browserfenster: vw/vh waeren die Masse der Buehne und die Schrift
   wanderte, sobald jemand das Fenster zieht.

   Warum ueberhaupt gebaut und nicht abfotografiert: einen Sperrbildschirm kann
   man nicht screenshotten, ohne ein echtes Geraet zu bedienen — und die
   Benachrichtigung soll in jeder Sprache dieselbe sein. Der TEXT ist deshalb
   nicht nachgetextet, sondern kommt aus artist/sprache_<lang>.php (r/push.js).

   Der Hintergrund ist bewusst kein Foto: ein Wallpaper waere ein fremdes Bild
   mehr im Film. Ein tiefer Verlauf reicht — wirken soll die Karte. */
/* z-index: 0 -> die Flaeche liegt UNTER .intro-geraet (z-index 1) und damit unter
   dem Rahmenbild. Der Alphakanal des Rahmens rundet die Displayecken; ein eigener
   border-radius auf dieser Flaeche waere wieder eine geratene Form. overflow bleibt,
   damit die Karte innerhalb der Displayflaeche bleibt. */
.intro-anim.im-geraet { position: absolute; overflow: hidden; z-index: 0; }

.push-schirm {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(164,94,229,.30) 0%, rgba(0,0,0,0) 60%),
    linear-gradient(180deg, #1b1430 0%, #0b0b12 55%, #06060a 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: -apple-system, "SF Pro Text", "Helvetica Neue", roboto, sans-serif;
  color: #fff;
}

/* Uhrzeit: gross, duenn, weit oben — die eine Stelle, an der ein Sperrbildschirm
   sofort als solcher zu erkennen ist. */
.push-uhr {
  margin-top: 13em;
  text-align: center;
  opacity: 0;
  animation: pushAuf .5s ease forwards;
}
.push-zeit {
  font-size: 9em;
  font-weight: 200;
  line-height: 1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

/* Die Karte faehrt von oben herein und setzt sich — dieselbe Bewegung, die iOS
   einer eintreffenden Mitteilung gibt. */
.push-karte {
  width: 88%;
  margin-top: 6em;
  display: flex;
  gap: 2.2em;
  align-items: flex-start;
  padding: 2.4em 2.6em;
  border-radius: 3.4em;
  background: rgba(48,48,54,.62);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: 0 .6em 2.6em rgba(0,0,0,.42);
  opacity: 0;
  transform: translateY(-2.4em) scale(.96);
  animation: pushRein .62s cubic-bezier(.22,1,.36,1) forwards;
}

/* Das App-Icon traegt die Wortmarke — dieselbe, die auch das Schlussbild zeigt
   (r/logo.js). Kein zweites, eigens gebautes Zeichen. */
.push-icon {
  flex: 0 0 auto;
  width: 5.6em; height: 5.6em;
  border-radius: 1.3em;
  background: #fff;
  color: #111;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.push-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }

.push-inhalt { flex: 1 1 auto; min-width: 0; }
/* Kopfzeile wie bei iOS: links die App, rechts wie lange es her ist. Klein,
   halbtransparent, GESPERRT — das ist die Zeile, an der man einen Sperrbildschirm
   auch ohne Text erkennt. */
.push-kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1em;
  font-size: 1.4em;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(255,255,255,.66);
}
.push-kopf .push-wann { flex: none; text-transform: none; letter-spacing: .02em; }
/* Der Bandname ist der BETREFF der Mitteilung, nicht die App — deshalb fett unter
   der Kopfzeile und nicht darin. */
.push-band {
  margin-top: .5em;
  font-size: 2em;
  font-weight: 600;
  line-height: 1.25;
  color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.push-text {
  margin-top: .2em;
  font-size: 2em;
  line-height: 1.32;
  color: rgba(255,255,255,.94);
}

@keyframes pushAuf  { to { opacity: 1; } }
@keyframes pushRein { to { opacity: 1; transform: translateY(0) scale(1); } }

/* Hell/Dunkel: der Sperrbildschirm bleibt dunkel. Ein Telefon, das eine
   Mitteilung zeigt, ist dunkel — auch wenn der Rest des Films hell laeuft. */
