/* css/intro.css
   Intro-Hero der Startseite (sections/intro-hero.html.twig). 1:1 aus dem freigegebenen Prototyp
   10_Intro-Film/index.html übernommen (Jelena, 12.10.2026) - Konstanten und Werte NICHT ändern:
   HOLD/ZT liegen in js/intro.js, hier nur das Aussehen. Schrift kommt aus dem Theme (css/main.css),
   deshalb keine @font-face-Regel hier (anders als im Prototyp).
   Nur auf der Startseite geladen (templates/partials/layout.html.twig, p.is_home). */
:root{--intro-nachtblau:#171d3a;--intro-violett:#57389c;--intro-papier:#f8f5f1;--intro-schiefer:#4e5069;--intro-nebel:#ece7ef;--intro-ease:cubic-bezier(.65,0,.35,1);--intro-pad:clamp(20px,4vw,56px)}
/* Höhe (Anmerkung Jelena 19.10.2026, "Intro stark abgeschnitten" bei flachem Fenster; zweite Runde
   19.10.2026: "Intro-Sektion inkl. Kopfleiste muss exakt 100svh sein, Video nie hoeher als der Bildschirm").
   --intro-header-h wird von js/intro.js per getBoundingClientRect() auf die wirkliche, gerenderte
   Kopfleistenhoehe gesetzt (misst zuverlaessiger als der feste --header-h-Wert, der bei umgebrochener
   Navigation nicht mehr stimmen muesste); der alte feste Wert (Topbar 38px + Hauptnav var(--header-h))
   bleibt nur als Fallback fuer den Moment vor der ersten Messung bzw. ohne JS (dann zeigt .intro-static-
   fallback das Standbild, das dieselbe Hoehe erbt). Der vorherige clamp(600px, ..., 920px) erzeugte auf
   sehr flachen Fenstern (z. B. Handy quer 844x390) eine Hoehe UEBER dem Bildschirm (600px Mindesthoehe bei
   nur 390px verfuegbarer Hoehe) - darum kein Mindest-/Hoechstwert mehr, die Summe aus Kopfleiste + Intro
   ergibt dadurch bei jeder Fenstergroesse exakt 100svh (Fallback 100vh fuer Browser ohne svh-Einheit). */
.c-intro-hero{position:relative;width:100%;height:calc(100vh - var(--intro-header-h, calc(var(--header-h,80px) + 38px)));height:calc(100svh - var(--intro-header-h, calc(var(--header-h,80px) + 38px)));overflow:hidden;background:var(--intro-papier);color:var(--intro-nachtblau);font-family:"Familjen Grotesk",system-ui,sans-serif;-webkit-font-smoothing:antialiased}
/* Ab 1200px blendet main.css die Topbar aus und setzt --header-h auf 72px (siehe dort) - gleiche Schwelle hier */
@media (max-width:1200px){.c-intro-hero{height:calc(100vh - var(--intro-header-h, var(--header-h,72px)));height:calc(100svh - var(--intro-header-h, var(--header-h,72px)))}}
.c-intro-hero .intro-stage{position:absolute;inset:0;opacity:0;transition:opacity .3s ease}
.c-intro-hero.is-ready .intro-stage{opacity:1}
.c-intro-hero .intro-lay{position:absolute;inset:0;will-change:clip-path}
/* Bildausschnitt: --intro-op-basis steht inline an der Ebene (.intro-lay, gesetzt in
   sections/intro-hero.html.twig aus image_position im Frontmatter), --intro-op ist der wirksame
   Wert und wird hier daraus abgeleitet. Die Ableitung ist noetig, damit die Mobil-Media-Query
   unten den Ausschnitt je Kapitel neu setzen kann: eine inline gesetzte Variable gewinnt gegen
   jedes Stylesheet, eine hier gesetzte nicht. Der freigegebene Desktop-Ausschnitt bleibt dadurch
   unveraendert. */
.c-intro-hero .intro-lay{--intro-op:var(--intro-op-basis,50% 50%)}
.c-intro-hero .intro-lay video,.c-intro-hero .intro-lay img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:var(--intro-op,50% 50%)}
/* ---------------------------------------------------------------------------------------------------
   Ken-Burns auf den Standbild-Kapiteln (Auftrag Jelena 19.10.2026: "bei den 3 Kapiteln, die jetzt
   Originalfotos als Standbild zeigen, wieder den langsamen Zoom einbauen").
   NEU GEBAUT, nicht aus einem alten Stand uebernommen: in keinem Stand von heute unter
   08_Backups/golive-2026-10-19/ (alle acht gesicherten intro.css) steht eine @keyframes-Regel -
   die frueher sichtbare Zoomfahrt kam dort aus der JS-Kamerafahrt (js/intro.js frame()/play(),
   clip-path + Formmorph beim KAPITELWECHSEL). Die bleibt unangetastet; das hier ist eine eigene,
   zusaetzliche Dauerbewegung INNERHALB eines Kapitels, allein in CSS.
   Entscheidungen:
   1) Reine transform-Animation am <img> selbst (nicht an .intro-lay - die traegt den clip-path der
      Kamerafahrt, eine zweite Transformation dort wuerde sich mit ihr verrechnen). scale() auf dem
      Bild laeuft auf der Compositor-Ebene, kostet also kein Layout und kein Neuzeichnen.
   2) "infinite alternate" statt eines Neustarts pro Kapitel: die Fahrt geht in 20s von 1 auf 1.09
      und in weiteren 20s zurueck. Ein Neustart pro Kapitel haette bei jedem Wechsel einen sichtbaren
      Sprung zurueck auf scale(1) bedeutet oder eine zusaetzliche Klassensteuerung in js/intro.js
      gebraucht; so atmet das Foto durchgehend und es gibt nie einen Sprung. Ein Kapitel dauert rund
      7,2s (ZT 2600 + HOLD 4600), in dieser Zeit wandert die Skalierung um rund 3 Prozent - auf einem
      1440px breiten Bild sind das rund 45px Drift, deutlich sichtbar, aber ohne wahrnehmbare
      Geschwindigkeit.
   3) Zoom-Ursprung ueber --intro-kb-origin steuerbar, Vorgabe Bildmitte. Mobil setzt die Media-Query
      unten ihn nach oben, damit die Gesichter beim Zoomen nicht nach unten unter den Textblock
      wandern (Auftrag 2, Punkt 2).
   Pause: der bestehende Pause-Knopf schaltet in js/intro.js (syncPlayBtn) die Klasse is-paused am
   Abschnitt um - die haengt hier nur noch das animation-play-state daran. Keine Aenderung an der
   Knopf-Logik noetig. */
@keyframes intro-kenburns{from{transform:scale(1)}to{transform:scale(var(--intro-kb-scale,1.09))}}
.c-intro-hero{--intro-kb-dur:20s;--intro-kb-scale:1.16;--intro-kb-origin:50% 50%}
.c-intro-hero .intro-lay[data-media="image"] img{transform-origin:var(--intro-kb-origin);will-change:transform;animation:intro-kenburns var(--intro-kb-dur) cubic-bezier(.45,0,.55,1) infinite alternate}
.c-intro-hero.is-paused .intro-lay[data-media="image"] img{animation-play-state:paused}
.c-intro-hero .intro-lay .intro-veil{position:absolute;inset:0}
.c-intro-hero .intro-slides img{opacity:0;transition:opacity .9s ease}
.c-intro-hero .intro-slides img.on{opacity:1}
.c-intro-hero .intro-scrim{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;transition:opacity .7s ease;background:linear-gradient(90deg,rgba(23,29,58,.78) 0%,rgba(23,29,58,.42) 38%,rgba(23,29,58,0) 66%),linear-gradient(0deg,rgba(23,29,58,.5) 0%,rgba(23,29,58,0) 38%)}
.c-intro-hero.is-dark .intro-scrim{opacity:1}
/* ---------------------------------------------------------------------------------------------------
   Neufassung der Textebene 19.10.2026 (Auftrag Jelena, Befunde auf echtem MacBook/Chrome 1440x750:
   Headline klebt am Menue, linke Textkante 78px gegen Logo/Navigation bei 180px, alles eng gestapelt).
   Drei Entscheidungen:
   1) Gleiche Satzkante wie die Kopfleiste. .l-container (css/main.css Zeile 372) ist
      width:100%; max-width:calc(var(--fv-content-max) + 2*var(--fv-page-margin)); margin-inline:auto;
      padding-inline:var(--fv-page-margin). Genau diese vier Werte stehen unten bei .intro-copy -
      nicht geschaetzt, nicht gerundet. Weil .c-header__logo links kein Padding hat
      (padding:… … … 0, css/main.css), liegt die linke Headline-Kante damit auf jeder Fensterbreite
      exakt auf der linken Logokante; die Fusszeile unten liegt auf derselben Kante, weil sie im
      selben Container steckt.
   2) .intro-copy deckt jetzt die ganze Intro-Flaeche ab (inset:0) und verteilt sie als Raster auf
      zwei Zeilen: 1fr fuer den Textblock (vertikal mittig) und auto fuer die Fusszeile unten. Luft
      entsteht dadurch durch Verteilung statt durch Stapeln mit gleich grossen Gaps.
   3) Fester Mindestabstand unter die Kopfleiste ueber --intro-top (mind. 48px, waechst mit Hoehe und
      Breite des Fensters). pointer-events:none auf der leeren Flaeche, damit die Ebene keine Klicks
      abfaengt; die beiden Zeilen schalten es wieder an.
   Tokens hier gebuendelt, damit die Hoehen-Media-Query unten nur sie ueberschreiben muss.
   --intro-cw-gap/--intro-launch-h spiegeln --cw-gap/--cw-launch-h des Chat-Launchers (css/main.css,
   .cw): dadurch sitzt die Wortreihe exakt auf der Hoehe des Knopfs "Fragen Sie uns". */
.c-intro-hero{--intro-top:clamp(48px,4.8vh + 1.2vw,120px);--intro-cw-gap:16px;--intro-launch-h:48px;--intro-gap-base:clamp(20px,3vh,40px);--intro-gap-tight:clamp(6px,1vh,12px);--intro-gap-cta:clamp(14px,2vh,22px)}
.c-intro-hero .intro-copy{position:absolute;inset:0;z-index:4;pointer-events:none;width:100%;max-width:calc(var(--fv-content-max,1200px) + 2 * var(--fv-page-margin,72px));margin-inline:auto;padding-inline:var(--fv-page-margin,72px);padding-top:var(--intro-top);padding-bottom:var(--intro-cw-gap);display:grid;grid-template-rows:1fr auto;row-gap:var(--intro-gap-base);transition:color .6s ease}
.c-intro-hero .intro-copy > *{pointer-events:auto}
/* Textblock: nur noch Headline, Subline, Button - kompakt beieinander, vertikal mittig im freien Raum
   zwischen Kopfleisten-Abstand und Fusszeile. Die Abstaende innerhalb des Blocks sind absichtlich
   ungleich (Subline dicht an der Headline, Button etwas weiter) statt ein gleicher Gap fuer alles. */
.c-intro-hero .intro-main{align-self:center;justify-self:start;width:min(40vw,620px);display:flex;flex-direction:column;align-items:flex-start}
/* Schriftgroesse an min(vw,vh) gekoppelt (Auftrag Jelena 19.10.2026, wortwoertlich "clamp() mit
   min(vw, vh) in der Formel"): auf flachen Fenstern (1440x750, 1920x950) zaehlt die Hoehe, auf hohen,
   schmalen die Breite - die Headline schrumpft also, statt den Rest zu quetschen. Mittelwert bei
   1440x750: 41px, bei 1920x1080: 50px (Deckel 3.1rem). Unter 861px gilt der frueher freigegebene
   vw+vh-Clamp weiter (siehe Mobil-Media-Query unten), damit sich der Handy-Stand nicht veraendert. */
.c-intro-hero .intro-hl{margin:0;font-weight:640;font-size:clamp(1.75rem,1rem + 3.4 * min(1vw,1vh),3.1rem);line-height:1.2;letter-spacing:-.025em;transition:opacity .35s var(--intro-ease),transform .35s var(--intro-ease)}
.c-intro-hero .intro-hl.out{opacity:0;transform:translateY(.18em)}
/* Markierung wie .fv-mark auf der Website: Box in Verbfarbe, Familjen Mark (symmetrische Metrik), gleiches Padding oben und unten */
.c-intro-hero .intro-mk{position:relative;white-space:nowrap;font-family:"Familjen Mark","Familjen Grotesk",sans-serif;padding:.04em .16em;margin-inline:.02em;color:var(--intro-mon,#171d3a);z-index:0}
.c-intro-hero .intro-mk::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:.16em;background:var(--intro-mbg,#d38acb);transform:scaleX(0);transform-origin:left center}
.c-intro-hero .intro-mk.draw::before{transform:scaleX(1);transition:transform .55s var(--intro-ease) .1s}
/* Subline dicht unter der Headline, Button etwas weiter darunter (Punkt 2 des Auftrags: "Subline
   naeher an die Headline, Button naeher an die Subline, kompakter Block"). Der frueher noetige
   negative margin-top gegen einen gemeinsamen 24px-Gap entfaellt, weil .intro-main keinen Gap mehr
   setzt und jeder Abstand einzeln steht. */
.c-intro-hero .intro-lead{margin:var(--intro-gap-tight) 0 0;font-size:clamp(1.02rem,1.25vw,1.2rem);line-height:1.5;color:var(--intro-schiefer);max-width:34em;transition:color .5s}
.c-intro-hero .intro-row{margin-top:var(--intro-gap-cta);display:flex;flex-wrap:wrap;align-items:center;gap:16px 26px}
.c-intro-hero .intro-btn{display:inline-flex;align-items:center;gap:10px;background:var(--intro-nachtblau);color:#fff;text-decoration:none;font-weight:600;font-size:1.05rem;padding:15px 24px;border-radius:12px;transition:background .5s,color .5s}
/* Untere Zeile: links die Fusszeile (Pause + Nachweis), mittig die Wortreihe. Drei Spalten
   minmax(0,1fr) auto minmax(0,1fr), die dritte bleibt leer - dadurch ist die Wortreihe in der
   Intro-Flaeche zentriert, unabhaengig davon, wie breit die Fusszeile links gerade ist, und die
   Fusszeile kann die Mitte nie verschieben (minmax(0,…) statt 1fr, damit die Spalte schrumpfen darf).
   align-items:end haelt beide Zeilenteile an der Unterkante: die Wortreihe steht damit immer in einer
   --intro-launch-h hohen Box, die --intro-cw-gap ueber dem Intro-Boden endet - genau die Box des
   Chat-Knopfs "Fragen Sie uns" (position:fixed; bottom:var(--cw-gap); min-height:var(--cw-launch-h)),
   also gleiche Mittelachse. Waechst die Fusszeile (zweizeilige Bildquelle, Badge), waechst sie nach
   oben und verschiebt die Wortreihe nicht. */
.c-intro-hero .intro-base{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:end;column-gap:var(--fv-space-24,24px)}
.c-intro-hero .intro-verbs{grid-column:2;justify-self:center;display:flex;flex-wrap:wrap;justify-content:center;align-items:center;min-height:var(--intro-launch-h);gap:6px 18px;list-style:none;padding:0;margin:0}
.c-intro-hero .intro-verbs button{all:unset;cursor:pointer;font-size:1.05rem;font-weight:560;color:var(--intro-schiefer);padding:4px 0;border-bottom:3px solid transparent;transition:color .3s,border-color .3s}
.c-intro-hero .intro-verbs button[aria-current="true"]{color:var(--intro-nachtblau);border-color:var(--intro-c)}
.c-intro-hero .intro-verbs button:focus-visible,.c-intro-hero .intro-btn:focus-visible{outline:2px solid var(--intro-violett);outline-offset:4px;border-radius:4px}
/* Bildquelle: immer genau EINE Zeile (Auftrag Jelena 19.10.2026, Punkt 4: "Bildquelle immer einzeilig,
   nie Umbruch") - darum white-space:nowrap und die frueher reservierte Mindesthoehe von zwei Zeilen
   (min-height:2.8em) ersatzlos weg: die zwei Zeilen waren genau der leere Platz, der ohne Badge oben
   stehen blieb (Punkt 5). Die Zeilenhoehe steht als Token, weil die Badge-Hoehe unten daraus
   gerechnet wird. Gekuerzt werden die Texte im Inhalt (user/pages/01.home/default.md, Feld caption/
   credit), NICHT per text-overflow - ein abgeschnittener Bildnachweis waere keine Pflichtangabe mehr. */
.c-intro-hero .intro-cap{margin:0;font-size:var(--intro-cap-fs);line-height:var(--intro-cap-lh);white-space:nowrap;color:var(--intro-schiefer);transition:color .5s}
.c-intro-hero .intro-cap b{font-weight:600}
.c-intro-hero.is-dark .intro-copy{color:#fff}
.c-intro-hero.is-dark .intro-lead,.c-intro-hero.is-dark .intro-cap,.c-intro-hero.is-dark .intro-verbs button{color:rgba(255,255,255,.85)}
.c-intro-hero.is-dark .intro-verbs button[aria-current="true"]{color:#fff}
.c-intro-hero.is-dark .intro-btn{background:#fff;color:var(--intro-nachtblau)}
/* Gleiche helle Schrift im statischen Zustand (kein JS oder prefers-reduced-motion). Gefunden
   19.10.2026 beim Abnahmetest zu prefers-reduced-motion: dort zeigt .intro-static-fallback das
   Verbinden-Standbild (heller, goldener Kaisersaal) mitsamt Verlauf, die Schrift blieb aber
   nachtblau, weil js/intro.js im reduce-Zweig nur is-static setzt und vor is-dark aussteigt - die
   Headline war auf dem hellen Bild praktisch nicht zu lesen. Nur die Schriftfarben hier, NICHT
   .intro-scrim: der Verlauf kommt im statischen Zustand aus .intro-static-fallback::after, beide
   zusammen wuerden doppelt abdunkeln. */
/* .intro-hl braucht die Farbe ausdruecklich: css/main.css Zeile 321 setzt h1 auf var(--text) und
   holt Weiss nur ueber :is(.is-dark, …) :is(h1, …) (Zeile 424) zurueck - .is-static steht in dieser
   Liste nicht, Erben von .intro-copy reicht daher nicht. */
.c-intro-hero.is-static .intro-copy,.c-intro-hero.is-static .intro-hl{color:#fff}
.c-intro-hero.is-static .intro-lead,.c-intro-hero.is-static .intro-cap,.c-intro-hero.is-static .intro-verbs button{color:rgba(255,255,255,.85)}
.c-intro-hero.is-static .intro-verbs button[aria-current="true"]{color:#fff}
.c-intro-hero.is-static .intro-btn{background:#fff;color:var(--intro-nachtblau)}
/* Markierung im statischen Zustand sofort ausgefahren statt animiert: die Klasse .draw kommt aus
   js/intro.js (setHeadline), das im reduce-Zweig nie laeuft - die Box hinter dem markierten Wort
   blieb damit auf scaleX(0), das Wort stand als einziges nachtblau ohne Hintergrund auf dem Bild.
   Farben kommen aus den Vorgabewerten von --intro-mbg/--intro-mon, die genau dem headline_color
   der Seite entsprechen (user/pages/01.home/default.md). */
.c-intro-hero.is-static .intro-mk::before{transform:scaleX(1)}
/* Fusszeile unten links, auf der Container-Kante (also buendig mit Logo und Headline). Anordnung
   woertlich nach dem Auftrag vom 19.10.2026 (dritte Runde, Punkte 1-5): Pause-Knopf aussen links,
   rechts daneben die Nachweis-Spalte, darin das KI-Badge direkt UEBER der Bildquelle und linksbuendig
   mit ihr; die Spalte ist genau so hoch wie der Pause-Knopf (Badge-Oberkante = Knopf-Oberkante,
   Bildquelle-Unterkante = Knopf-Unterkante).
   Statt der Spalte eine feste Hoehe zu geben, ergibt sich die 40px aus ihrem Inhalt:
     Bildquelle  = --intro-cap-fs * --intro-cap-lh   (genau eine Zeile, nie mehr)
     Badge-Block = --intro-badge-pill + --intro-badge-gap
   Dadurch loest sich Punkt 5 (Video ohne KI-Badge) von selbst: faellt das Badge weg (hidden, siehe
   js/intro.js syncKiBadge), ist die Spalte nur noch eine Zeile hoch und steht durch align-items:
   flex-end unten weiter auf der Knopf-Unterkante - kein reservierter Leerraum oben, nichts springt.
   min-height haelt die Fusszeile mindestens so hoch wie die Box des Chat-Knopfs, damit Fusszeile und
   Wortreihe auf einer ruhigen gemeinsamen Linie sitzen (unveraendert aus der zweiten Runde). */
/* Schriftgroesse der Bildquelle: ab 1200px steht die Fusszeile in der linken Spalte des Dreispalten-
   Rasters, und die ist bei 1280px Fensterbreite am knappsten (gemessen: 281px Platz fuer den Text,
   ab 1440px 305px) - weil die Zeile nicht umbrechen darf, haengt die Groesse hier an der Fensterbreite
   und erreicht die vollen 13px ab etwa 1530px. Unter 1200px steht die Fusszeile in einer eigenen Zeile
   ueber der Wortreihe und hat die ganze Breite, dort bleiben es 13px (siehe Media-Queries unten).
   --intro-cap-lh ist bewusst enger als die frueheren 1.4: die Zeilenhoehe ist hier eine Masseinheit
   (Punkt 2), kein Leseabstand - es ist ohnehin nur eine Zeile. */
/* --intro-badge-gap steht NICHT mehr hier: die Luecke zwischen Badge und Bildquelle ist seit dem
   Verkleinern des Badges (19.10.2026, siehe unten) keine gesetzte Zahl mehr, sondern genau der Rest,
   der nach Pille und Bildquelle bis zur 40px-Knopfhoehe noch frei ist. */
.c-intro-hero{--intro-play-h:40px;--intro-cap-fs:clamp(11.5px,0.85vw,13px);--intro-cap-lh:1.25}
.c-intro-hero .intro-foot{grid-column:1;justify-self:start;display:flex;align-items:flex-end;gap:var(--fv-space-16,16px);min-height:var(--intro-launch-h);max-width:100%}
.c-intro-hero .intro-credit{display:flex;flex-direction:column;align-items:flex-start;min-width:0}
/* KI-Badge (EU AI Act Art. 50) fuer das Header-Video: offizielle EU-Kennzeichnung (Download-Quelle und
   Entscheidung siehe Twig-Kommentar bei <img class="intro-ki-badge">). Datei, Farbe und Inhalt bleiben
   unveraendert (Entscheidung Jelena 19.10.2026: schwarze Fassung, keine weisse Variante).
   Die offizielle SVG-Datei hat rundherum durchsichtigen Rand: viewBox 1789.84x566.93, die sichtbare
   Pille liegt darin bei x=207.30 y=144.36 w=1384.24 h=266.41 (gemessen per getBBox, nicht geschaetzt).
   Die Datei wird deshalb NICHT beschnitten, sondern der durchsichtige Rand per negativem Rand
   herausgerechnet - sonst saesse die sichtbare Pille rund 10px unter der Knopf-Oberkante und rund 15px
   rechts der Textkante, die Punkte 2 und 3 waeren also nur rechnerisch, nicht sichtbar erfuellt:
     Elementhoehe      = Pille / (266.41/566.93)   = Pille * 2.12804
     Rand oben         = -144.36/566.93            = -0.254634 * Elementhoehe
     Rand unten        = Wunschabstand - 156.16/566.93 * Elementhoehe
     Rand links        = -207.30/1789.84 * Breite  = -0.365466 * Elementhoehe (Breite = 3.157 * Hoehe)
   GROESSE (Auftrag Jelena 19.10.2026, vierte Runde: "genau in der Mitte zwischen der ganz kleinen
   Version von heute Vormittag und der jetzigen"). Statt die Mitte als eine neue Zahl zu schaetzen,
   stehen beide Staende hier als eigene Formel, und die wirksame Pillenhoehe ist ihr Mittelwert -
   dadurch liegt sie an JEDER Fenstergroesse exakt mittig, nicht nur an den drei gemessenen Punkten:
     --intro-badge-pill-klein  Stand vom Vormittag. Damals war clamp(18px,.9vw+.9vh,26px) die Hoehe des
                               <img>, also der Datei MIT durchsichtigem Rand; sichtbar war davon nur
                               der Anteil der Pille (266.41/566.93 = 0.469915). Deshalb hier derselbe
                               clamp(), aber auf die sichtbare Pille umgerechnet - sonst wuerden zwei
                               verschiedene Dinge gemittelt.
     --intro-badge-pill-gross  Stand nach dem Fusszeilen-Umbau: der ganze Platz, der ueber der einen
                               Textzeile bis zur Knopf-Oberkante frei war (bei damals 4px Luecke).
   Gemessen (Playwright, getBoundingClientRect auf #intro-ki-badge, sichtbare Pille):
     1280x720   klein  8.46px   vorher 21.62px   jetzt 15.04px   (Mittelwert 15.04)
     1440x900   klein  9.90px   vorher 20.70px   jetzt 15.30px   (Mittelwert 15.30)
     1920x1080  klein 12.22px   vorher 19.74px   jetzt 15.98px   (Mittelwert 15.98)
   Die Pille ist jetzt also kleiner als vorher, aber immer noch rund 1.3x so gross wie am Vormittag -
   und mit 15-16px ueber die ganze Breite deutlich ruhiger als beide Ausgangsstaende (die einer mit
   der Breite wachsend, der andere mit der Breite schrumpfend; der Mittelwert hebt das fast auf).
   LUECKE: weil die Pille kleiner ist als der verfuegbare Platz, bleibt Rest ueber. Der bleibt nicht
   leer stehen, sondern ist die Luecke zwischen Badge und Bildquelle (--intro-badge-gap, jetzt 7.8 bis
   10.6px statt fest 4px). Dadurch ist "Badge + Luecke + Bildquelle = Knopfhoehe" keine nachgemessene
   Zahl mehr, sondern eine Identitaet:
     pill + gap + cap-Zeile = pill + (rest - pill) + cap-Zeile = rest + cap-Zeile = --intro-play-h. */
.c-intro-hero{--intro-badge-rest:calc(var(--intro-play-h) - var(--intro-cap-fs) * var(--intro-cap-lh));--intro-badge-pill-klein:calc(0.469915 * clamp(18px,0.9vw + 0.9vh,26px));--intro-badge-pill-gross:calc(var(--intro-badge-rest) - 4px);--intro-badge-pill:calc((var(--intro-badge-pill-klein) + var(--intro-badge-pill-gross)) / 2);--intro-badge-gap:calc(var(--intro-badge-rest) - var(--intro-badge-pill));--intro-badge-box:calc(var(--intro-badge-pill) * 2.12804)}
/* max-width:none ist Pflicht: die Grundregel img{max-width:100%} (css/main.css Zeile 332) hat das Badge
   bei kurzen Bildquelle-Texten (Kapitel "entwickeln", "Im Bild: Karrieretag 2026") auf die Textbreite
   gestaucht - die SVG wurde dann im Element zentriert und die sichtbare Pille rutschte knapp 2px nach
   links aus der Textkante (gemessen bei 1280px). Mit max-width:none folgt die Breite immer der Hoehe. */
.c-intro-hero .intro-ki-badge{display:block;flex:0 0 auto;width:auto;max-width:none;height:var(--intro-badge-box);margin:calc(-0.254634 * var(--intro-badge-box)) 0 calc(var(--intro-badge-gap) - 0.275451 * var(--intro-badge-box)) calc(-0.365466 * var(--intro-badge-box))}
/* Bugfix 19.10.2026 (Jelena, Badge lief bei "verbinden"/"werben" trotzdem mit): das display:block oben
   hat eine hoehere Spezifitaet als die [hidden]-Regel des Browsers (UA-Stylesheet) und hat das hidden-
   Attribut aus js/intro.js (syncKiBadge) dadurch wirkungslos gemacht - das Bild blieb immer sichtbar,
   egal welches Kapitel lief. Jetzt wieder explizit ausblenden, wenn hidden gesetzt ist. */
.c-intro-hero .intro-ki-badge[hidden]{display:none}
/* Pause/Play-Knopf: Klassen c-hero__play/c-hero__play-icon sind dieselben wie beim Story-Hero/Karrieretag
   (css/main.css, dort NICHT geändert) - deren Basis-Button-Stil (Größe, Form, Farbe, Hover/Fokus) ist
   generisch genug und greift hier automatisch. main.css scoped die Pausiert-Zustand-Ikone aber auf
   ".c-hero.is-paused", dieser Abschnitt heißt ".c-intro-hero" - darum hier dieselbe Umschaltung noch
   einmal, nur unter .c-intro-hero.is-paused (keine main.css-Änderung nötig). */
/* Bugfix 19.10.2026 (gleicher Fund wie oben beim KI-Badge, Zeile 172): main.css setzt auf
   .c-hero__play direkt "display:inline-grid" - bei gleicher Spezifitaet wie [hidden]{display:none}
   aus dem Browser-Standardstylesheet gewinnt die spaeter geladene main.css-Regel, das hidden-
   Attribut aus js/intro.js (syncPlayVisibility) blieb dadurch wirkungslos, der Knopf war bei
   Bild-Kapiteln sichtbar trotz hidden=true. Gleiche Loesung: explizit ausblenden. */
#intro-play[hidden]{display:none}
.c-intro-hero.is-paused .c-hero__play-icon i:last-child{display:none}
.c-intro-hero.is-paused .c-hero__play-icon i:first-child{width:12px;height:14px;margin-left:3px;border-radius:1px;clip-path:polygon(0 0,100% 50%,0 100%)}
.c-intro-hero .intro-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
/* Statischer Zustand: kein JS oder prefers-reduced-motion (js/intro.js schaltet is-static, siehe dort) */
.c-intro-hero.is-static .intro-stage{display:none}
.c-intro-hero.is-static .intro-static-fallback{display:block}
.c-intro-hero .intro-static-fallback{display:none;position:absolute;inset:0}
.c-intro-hero .intro-static-fallback img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.c-intro-hero .intro-static-fallback::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(23,29,58,.78) 0%,rgba(23,29,58,.42) 38%,rgba(23,29,58,0) 66%),linear-gradient(0deg,rgba(23,29,58,.5) 0%,rgba(23,29,58,0) 38%)}
/* intro-cap padding-right (132px) und die eigene Badge-Groesse hier entfielen: die Badge liegt jetzt IN der
   Spalte (unten links, nicht mehr absolut rechts ueber dem Bildvermerk), braucht also keine Platzreservierung
   mehr neben dem Text. */
/* Flache Fenster (Auftrag Jelena 19.10.2026, "unter 800px Fensterhoehe Abstaende proportional
   verkleinern, nichts darf sich beruehren"): nur die Tokens von oben werden kleiner, die Struktur
   bleibt. Der Mindestabstand von 48px unter der Kopfleiste bleibt auch hier bestehen, weil er der
   untere Rand des clamp() ist. Die Subline wird eine Spur kleiner, damit der linke Block kompakt
   bleibt, ohne Zeilen zu verlieren. */
@media (max-height:800px){
  .c-intro-hero{--intro-top:clamp(48px,6.4vh,64px);--intro-gap-base:clamp(16px,2.4vh,26px);--intro-gap-tight:6px;--intro-gap-cta:clamp(12px,1.8vh,18px)}
  .c-intro-hero .intro-lead{font-size:clamp(.95rem,1.05vw,1.06rem);line-height:1.45}
}
/* Schmale Fenster unter 1200px (dort blendet main.css auch die Topbar aus): nebeneinander wird es zu
   eng - die Bildquelle muesste sich in eine halbe Spalte neben der Wortreihe quetschen und lief im Test
   bei 900px Breite auf fuenf Zeilen. Darum hier untereinander: die Wortreihe bleibt die unterste Zeile
   (also weiter auf der Hoehe des Chat-Knopfs, align-items:end), die Fusszeile rueckt eine Zeile darueber
   und bekommt die ganze Breite. Nur dort, wo es die Wortreihe ueberhaupt gibt (ab 768px). */
@media (max-width:1199.98px) and (min-width:768px){
  /* Fusszeile hat hier die ganze Containerbreite - die Bildquelle braucht die Verkleinerung von oben
     nicht und bleibt bei den freigegebenen 13px. */
  .c-intro-hero{--intro-cap-fs:13px}
  .c-intro-hero .intro-base{grid-template-columns:minmax(0,1fr);row-gap:var(--fv-space-16,16px)}
  .c-intro-hero .intro-foot{grid-row:1;min-height:0}
  .c-intro-hero .intro-verbs{grid-column:1;grid-row:2}
}
/* Mobil/Tablet bis 860px: der linke Block nutzt die volle Containerbreite (Text liegt dort immer auf
   dem Video, siehe is-dark in js/intro.js). Headline-Mindesthoehe und Schriftgroesse bleiben genau die
   frueher freigegebenen Werte (vw+vh-Clamp statt des neuen min(vw,vh)-Clamps), damit sich der mobile
   Stand durch diese Neufassung nicht veraendert. */
@media (max-width:860px){
  .c-intro-hero{--intro-top:clamp(40px,5vh,64px)}
  /* Auf schmalen Geraeten bleibt der Textblock unten stehen statt mittig: der mobile Verlauf
     (.intro-scrim unten in dieser Media-Query) dunkelt nur die untere Haelfte ab, mittig stehender
     weisser Text wuerde dort auf hellen Videobereichen liegen. Reihenfolge und Lage entsprechen damit
     weiter dem freigegebenen mobilen Stand (Headline, Subline, Button, darunter die Fusszeile). */
  .c-intro-hero .intro-main{width:auto;align-self:end}
  .c-intro-hero .intro-hl{min-height:3.1em;font-size:clamp(1.75rem,1.15rem + 1.25vw + 1.25vh,3.1rem)}
  .c-intro-hero .intro-scrim,.c-intro-hero .intro-static-fallback::after{background:linear-gradient(0deg,rgba(23,29,58,.88) 0%,rgba(23,29,58,.6) 50%,rgba(23,29,58,0) 80%)}
}
/* Mobil-QA 19.10.2026 (Jelena): Wortreihe/Kapitel-Navigation (foerdern/verbinden/...) blendet unter
   768px komplett aus - zu eng. intro-btn (CTA) bleibt sichtbar. Weil die Wortreihe wegfaellt, braucht
   die untere Zeile kein Dreispalten-Raster mehr: die Fusszeile (Pause + Bildquelle + Badge) bekommt die
   ganze Breite, damit die Bildquelle nicht in eine halbe Spalte gequetscht wird. Der Chat-Knopf liegt
   mobil im ersten Bildschirm ohnehin im Ruhezustand (.cw--rest, js/chat-widget.js), ueberlappt also
   nicht mit der Fusszeile. */
@media (max-width:767.98px){
  /* Unterer Rand bleibt der bisherige mobile Wert (--intro-pad = 20px bei 390px Breite) statt des
     Chat-Launcher-Abstands: der Launcher ist hier ohnehin im Ruhezustand, die Wortreihe ausgeblendet. */
  /* Punkt 6 des Auftrags (Mobil 390x844): die Bildquelle darf kleiner werden, aber nicht umbrechen.
     Gemessen bleiben bei 390px Breite 294px fuer den Text (350px Container minus 40px Pause-Knopf
     minus 16px Luecke); bei 11.7px Schrift (3vw) ist die laengste vorgeschlagene Zeile rund 263px
     breit, also mit Reserve einzeilig. Ab etwa 433px Breite sind es wieder die vollen 13px. */
  .c-intro-hero{--intro-cw-gap:clamp(20px,4vw,56px);--intro-launch-h:40px;--intro-cap-fs:clamp(11px,3vw,13px)}
  /* Textblock hoeher setzen (Auftrag Jelena 19.10.2026, vierte Runde): zwischen dem Knopf
     "Mitglied werden" und der Fusszeile soll zusaetzlich etwa eine Knopfhoehe Luft stehen. Die
     Abstaende INNERHALB des Blocks (Headline/Subline/Button) bleiben unberuehrt - deshalb kein Eingriff
     in --intro-gap-tight/--intro-gap-cta und kein zusaetzlicher Gap im Block, sondern ein margin-bottom
     am ganzen Block: .intro-main haengt mobil per align-self:end an der Unterkante der oberen
     Rasterzeile, ein unterer Rand schiebt damit den kompletten Block als Ganzes nach oben und laesst
     Fusszeile und Wortreihe, wo sie sind.
     --intro-btn-h ist die Hoehe des Knopfs selbst, nicht geschaetzt, sondern aus seinem eigenen Rezept
     (.intro-btn: padding 15px oben und unten, font-size 1.05rem, Zeilenhoehe aus dem Theme) - gemessen
     56.03px bei 390x844, 375x667 und 430x932, die Formel ergibt 56.04px. Bewusst keine festen 56px,
     damit der Abstand mitwaechst, wenn jemand die Schriftgroesse im Browser hochsetzt (dann waechst
     auch der Knopf).
     Platz dafuer ist da: die obere Rasterzeile hatte vor der Aenderung 222px (375x667, engster Fall)
     bis 420px (430x932) Luft zwischen Blockoberkante und dem Mindestabstand unter der Kopfleiste;
     nach dem Hochschieben bleiben dort mindestens 166px. Oben kann daher nichts unter die Kopfleiste
     rutschen - der Mindestabstand --intro-top bleibt als Innenabstand der Ebene ohnehin bestehen. */
  .c-intro-hero{--intro-btn-h:calc(2 * 15px + 1.05rem * var(--fv-lh-body,1.55))}
  .c-intro-hero .intro-main{margin-bottom:var(--intro-btn-h)}
  .c-intro-hero .intro-verbs{display:none}
  .c-intro-hero .intro-base{grid-template-columns:minmax(0,1fr)}
  /* -------------------------------------------------------------------------------------------
     1) VERLAUF UND SCHRIFTFARBE (Auftrag Jelena 19.10.2026, fuenfte Runde: "die Schrift ist mobil
     dunkelblau auf bunten Fotos, das beisst sich - wieder den dunkelblauen Verlauf ueber das Bild
     legen, Schrift weiss, Kontrast mindestens 4.5:1").
     Ursache des Befunds war nicht ein fehlender Verlauf, sondern dass er verschwand: Verlauf und
     weisse Schrift haengen an der Klasse is-dark, und die setzt unter 768px nur die eine Zeile
     beim Start (js/intro.js, mobileNoIntro). reset() nimmt sie wieder weg - und reset() laeuft bei
     jedem resize, auf dem Handy also schon beim Ein- und Ausfahren der Adressleiste. Danach kann
     sie nichts mehr zurueckholen, weil der Weg dorthin (frame(), hero.classList.toggle('is-dark',
     t>.55)) unter 768px gar nicht laeuft (zoomIn() steigt vorher aus). Ergebnis: dunkelblaue
     Schrift auf dem Foto. js/intro.js setzt die Klasse in reset() jetzt wieder; damit die Lesbar-
     keit aber an keiner JS-Reihenfolge mehr haengt, gilt unter 768px beides ZUSAETZLICH fest -
     hier liegt der Text ohnehin immer auf dem Bild, nie auf hellem Papier.
     Die Verlaufsstufen sind keine runden Wunschwerte, sondern an den gemessenen Textkanten
     ausgerichtet (Playwright, Abstand von der Intro-Unterkante in Prozent der Intro-Hoehe, in den
     drei Testgroessen 375x667 / 390x844 / 430x932 - der jeweils hoechste Wert zaehlt):
       Bildquelle oben       2,6 - 4,5 %   -> Deckung rund .93
       Subline oben         34 - 44,8 %    -> Deckung rund .80
       Headline oben        47,8 - 62,3 %  -> Deckung rund .53
     Rechnung fuer den schlechtesten denkbaren Hintergrund (weisses Foto, z. B. die helle Decke im
     Kapitel "foerdern"): Subline und Bildquelle stehen in rgba(255,255,255,.85), gegen Nachtblau
     mit Deckung .80 ergibt das 6,5:1, mit .93 rund 9:1 - beide deutlich ueber den geforderten
     4.5:1. Die Headline ist reines Weiss und grosse Schrift (mind. 28px, fett), dort genuegen
     3:1; .53 Deckung ergeben 3,8:1. Oberhalb von 78 % faellt die Deckung schnell auf 0, damit die
     Gesichter im oberen Bilddrittel nicht unter einem Schleier liegen. */
  .c-intro-hero .intro-scrim,.c-intro-hero .intro-static-fallback::after{background:linear-gradient(0deg,rgba(23,29,58,.94) 0%,rgba(23,29,58,.82) 44%,rgba(23,29,58,.50) 64%,rgba(23,29,58,.14) 78%,rgba(23,29,58,0) 92%)}
  .c-intro-hero .intro-scrim{opacity:1}
  .c-intro-hero .intro-copy,.c-intro-hero .intro-hl{color:#fff}
  .c-intro-hero .intro-lead,.c-intro-hero .intro-cap{color:rgba(255,255,255,.85)}
  .c-intro-hero .intro-btn{background:#fff;color:var(--intro-nachtblau)}
  /* -------------------------------------------------------------------------------------------
     2) BILDAUSSCHNITT UND ZOOM-URSPRUNG JE KAPITEL (Auftrag Jelena, Punkt 2: "die Schrift darf
     nicht ueber Gesichtern liegen").
     Warum mobil ein ganz anderer Ausschnitt noetig ist: die Fotos sind 16:9 (1,78), die Intro-
     Flaeche auf dem Handy rund 0,5 - bei object-fit:cover bestimmt also die Hoehe die Skalierung,
     das Bild wird vollstaendig hoch, aber nur zu rund 28 bis 35 Prozent breit gezeigt. Der
     senkrechte Anteil von image_position hat mobil damit GAR KEINE Wirkung; welche Gesichter zu
     sehen sind und wie hoch sie stehen, entscheidet allein der waagerechte Anteil. Die Desktop-
     Werte aus dem Frontmatter bleiben deshalb unangetastet, hier steht nur der mobile Ausschnitt.
     Gewaehlt ist je Kapitel der Ausschnitt, dessen Gesichter im oberen Bilddrittel liegen, also
     oberhalb der gemessenen Headline-Oberkante (47,8 bis 62,3 % von unten):
       foerdern       80 %  Mann rechts im Bild, Gesicht auf rund 25 % der Hoehe. Der bisherige
                            Wert 20 % zeigte mobil nur die weisse Decke mit den roten Seilen und
                            am Rand die rothaarige Frau, deren Gesicht auf 70 % der Hoehe liegt -
                            genau hinter der Subline. Bei 70 % und 90 % steht der Kopf am
                            Bildrand (durchgefahren und angesehen), 80 % setzt ihn frei.
       unterstuetzen  50 %  unveraendert: der Preistraeger in der Mitte, Gesicht auf 28 % Hoehe,
                            steht bereits frei ueber dem Textblock.
       entwickeln     25 %  der Student im Gespraech, Gesicht auf 28 % Hoehe. Der bisherige Wert
                            50 % schnitt ihn am linken Rand an und zeigte sonst die unscharfe
                            Menge dahinter; bei 40 % und mehr ist er wieder angeschnitten.
       verbinden      50 %  unveraendert (Video, Tanzflaeche, keine Gesichter im Textbereich).
       werben         50 %  unveraendert (Bildfolge Karrieretag).
     Zoom-Ursprung auf 50% 35%: der Ken-Burns skaliert um diesen Punkt, Gesichter liegen also fast
     genau darauf und wandern beim Zoomen nicht nach unten in den Text (bei Ursprung Bildmitte
     waere der Weg nach oben zwar auch richtig herum, aber die Bildoberkante liefe 4 % aus dem
     Rahmen und bei "foerdern" waere der Scheitel des Mannes angeschnitten). */
  .c-intro-hero{--intro-kb-origin:50% 35%}
  .c-intro-hero .intro-lay[data-key="foerdern"]{--intro-op:80% 50%}
  .c-intro-hero .intro-lay[data-key="entwickeln"]{--intro-op:25% 50%}
}
/* Reduzierte Bewegung: keine Uebergaenge und kein Ken-Burns. js/intro.js steigt bei
   prefers-reduced-motion ohnehin frueh aus und schaltet is-static (Buehne aus, Standbild an) -
   die animation hier wird trotzdem ausdruecklich abgeschaltet, weil CSS-Animationen auch auf
   display:none-Elementen weiterlaufen und das Standbild sonst nach einem Wechsel der
   Systemeinstellung ohne Neuladen weiterzoomen wuerde. */
@media (prefers-reduced-motion:reduce){
  .c-intro-hero .intro-hl,.c-intro-hero .intro-mk.draw::before,.c-intro-hero .intro-lay,.c-intro-hero .intro-lay .intro-veil,.c-intro-hero .intro-slides img{transition:none!important}
  .c-intro-hero .intro-lay[data-media="image"] img{animation:none!important;transform:none!important}
}
