/* ============================================================================
   styles.css — Videobox Webversion
   Look angelehnt an die bestehende DocVideoBox: warm, hell, editorial.
   Palette & Schriften aus src/index.css der App übernommen.

   HINWEIS Schriften (F69): KEIN Google-Fonts-@import. Das Nachladen von
   fonts.googleapis.com überträgt die Besucher-IP an Google und ist in DE ohne
   Einwilligung unzulässig (LG München I, 20.01.2022, Az. 3 O 17493/20) — das
   passt nicht zu einer DE-gehosteten, datensparsamen Box. Zusätzlich blockierte
   der hängende Google-Request das Laden der App.
   ERLEDIGT am 27.07.2026: Fraunces und Manrope liegen jetzt als woff2 in
   fonts/ und werden über schriften.css eingebunden — die Wunsch-Typografie ist
   damit DSGVO-konform zurück, statt wie bisher auf System-Fallbacks zu laufen.
   ============================================================================ */

:root {
  --navy:    #0b2545;
  --cream:   #f3ece0;
  --cream-2: #fbf7ef;
  /* Koralle, am 31.07.2026 abgedunkelt (F123). Vorher #d95640: Damit kam die
     Knopfschrift `--cream` auf 3,34:1 und die Koralle als Text auf hellem Grund
     auf 3,34 bzw. 3,67:1 — gefordert sind 4,5:1. Gleicher Farbton (8,6°) und
     dieselbe Sättigung, nur dunkler; jetzt 4,94:1 auf `--cream` und 5,42:1 auf
     `--cream-2`. Ein Wert genügt, weil Kontrast symmetrisch ist: Dieselbe
     Änderung trägt den gefüllten Knopf UND die vier Stellen, an denen die
     Koralle selbst Schrift ist (.eyebrow, .step-label, .upload-status.err,
     Links in den Rechtstexten). Über Video gilt weiterhin die eigene Regel
     weiter unten. */
  --coral:   #b73924;
  --forest:  #1e5b3f;
  --ochre:   #c89641;

  --text:    var(--navy);
  --bg:      var(--cream);
  --card:    var(--cream-2);

  /* Eine Schrift für alles: Manrope, serifenlos, ruhig, gut lesbar.
     Bis zum 21.08.2026 standen die Überschriften in Fraunces — einer
     Serifenschrift mit deutlichem Charakter. Fabians Urteil beim Durchspielen:
     zu verspielt für eine Anwendung, in der Museumsgäste eine Frage schnell
     erfassen und dann sprechen sollen. Überschriften unterscheiden sich jetzt
     über Gewicht und Größe, nicht über eine zweite Schriftart.
     Beide Schnitte liegen weiterhin LOKAL in fonts/ (siehe schriften.css) —
     es wird nach wie vor nichts von fremden Servern geladen (F69). */
  --font-display: 'Manrope', system-ui, -apple-system, sans-serif;
  --font-body:    'Manrope', system-ui, -apple-system, sans-serif;

  --radius: 26px;
  --shadow: 0 18px 50px rgba(11,37,69,.14);
  --ease:   cubic-bezier(.16,1,.3,1);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* WICHTIG: hidden-Attribut muss IMMER gewinnen — sonst übersteuern Klassen wie
   .btn (display:inline-flex) das Verstecken und es erscheinen leere Flächen. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0; height: 100%;
  width: 100%; overflow-x: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  /* Verhindert, dass iOS beim Drehen Text/Seite automatisch herauszoomt */
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
}

/* Warmer Hintergrund mit weichen Farbfeldern + feinem Korn (wie AttractScreen) */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 55% at 18% 18%, rgba(200,150,65,.22), transparent 62%),
    radial-gradient(ellipse 60% 50% at 84% 82%, rgba(30,91,63,.15), transparent 62%),
    radial-gradient(ellipse 45% 35% at 88% 10%, rgba(183,57,36,.13), transparent 55%);
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: .045; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 100svh = kleinste sichtbare Höhe (Safari-Leiste eingerechnet) → nichts wird abgeschnitten;
   100dvh als moderner Fallback. So füllt der Inhalt immer die wirklich sichtbare Fläche. */
#app { position: relative; z-index: 1; height: 100vh; height: 100dvh; width: 100%; overflow: hidden; }

/* --- Screens --- */
.screen {
  position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
}
.screen.is-active { display: flex; animation: rise .55s var(--ease); }
@keyframes rise { from { opacity: 0; transform: translateY(12px);} to { opacity: 1; transform: none;} }

/* --- Card --- */
.card {
  position: relative; width: 100%; max-width: 480px;
  background: var(--card);
  border: 1px solid rgba(11,37,69,.06);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 34px 28px; text-align: center;
}
.eyebrow {
  font-family: var(--font-body);
  text-transform: uppercase; letter-spacing: .16em;
  font-size: 12px; color: var(--coral); font-weight: 700; margin-bottom: 14px;
}
h1 { font-family: var(--font-display); font-weight: 700; font-size: 30px; line-height: 1.18; margin: 0 0 14px; letter-spacing: -.01em; }
h2 { font-family: var(--font-display); font-weight: 700; font-size: 25px; line-height: 1.22; margin: 0 0 14px; }
p  { font-size: 16px; line-height: 1.55; color: rgba(11,37,69,.72); margin: 0 0 24px; }

/* --- Buttons --- */
.btn {
  appearance: none; border: none; cursor: pointer;
  font-family: var(--font-body); font-size: 17px; font-weight: 600;
  padding: 16px 22px; border-radius: 16px; width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  transition: transform .12s var(--ease), opacity .2s, background .2s, box-shadow .2s;
}
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--coral); color: var(--cream); box-shadow: 0 8px 22px rgba(183,57,36,.32); }
.btn-primary:disabled { opacity: .42; cursor: not-allowed; box-shadow: none; }
.btn-ghost { background: transparent; color: var(--navy); border: 1.6px solid rgba(11,37,69,.22); }
.btn-forest { background: var(--forest); color: var(--cream); box-shadow: 0 8px 22px rgba(30,91,63,.30); }
.btn .arrow { width: 16px; height: 16px; }
.row { display: flex; gap: 12px; }
.row .btn { width: auto; flex: 1; }

/* --- Choice-Optionen (Sprachwahl, Herkunft, Ja/Nein-Verzweigungen) --- */
.choice-sub { font-size: 15.5px; line-height: 1.5; color: rgba(11,37,69,.72); margin: 0 0 18px; white-space: pre-line; }
.choice-options { display: grid; gap: 12px; margin-top: 8px; }
.choice-options.choice-inline { grid-template-columns: 1fr 1fr; }
.pubbtn.is-selected {
  background: var(--forest); color: var(--cream);
  border-color: var(--forest); box-shadow: 0 8px 22px rgba(30,91,63,.28);
}

/* --- Einwilligung: Veröffentlichungs-Frage abgesetzt --- */
.consent-block {
  text-align: left; margin: 4px 0 22px; padding: 16px;
  background: rgba(200,150,65,.10); border-radius: 14px;
}
.consent-q { font-size: 15px; font-weight: 600; color: var(--navy); margin-bottom: 12px; line-height: 1.4; }
/* Zwei getrennte Zeilen fuer Museum und Online (21.08.). Jede Zeile nennt den
   Zweck und stellt Ja/Nein daneben — so ist auf einen Blick zu sehen, dass es
   sich wirklich um zwei Entscheidungen handelt und nicht um eine. */
.pub-zeile { margin-bottom: 14px; }
.pub-zeile:last-child { margin-bottom: 0; }
.pub-was {
  display: block; font-size: 14px; line-height: 1.4; font-weight: 500;
  color: rgba(11,37,69,.82); margin-bottom: 7px;
}
.pub-zeile .choice-options { margin-top: 0; }
.deletion-note {
  font-size: 13px; color: rgba(11,37,69,.7); text-align: left;
  margin: 0 0 8px; line-height: 1.5;
}
.consent-continue { margin-top: 4px; }
.consent-continue:disabled { opacity: .45; cursor: not-allowed; }
.accept-note { font-size: 12.5px; color: rgba(11,37,69,.7); line-height: 1.45; margin: 10px 0 14px; }

/* Was „Allem zustimmen" umfasst — drei kurze Punkte statt Fliesstext, die beim
   Klick sichtbar abgehakt werden (Testrunde 18.08.: „man sieht nicht, dass man
   allem zustimmt"). Bewusst kompakt: Der Bildschirm ist auf dem Handy knapp. */
.accept-liste { text-align: left; margin: 10px 0 14px; display: grid; gap: 6px; }
.accept-punkt {
  display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; line-height: 1.35; color: rgba(11,37,69,.7);
  transition: color .25s var(--ease);
}
.accept-punkt .haken {
  flex: none; width: 16px; height: 16px; border-radius: 50%;
  border: 1.6px solid rgba(11,37,69,.25); position: relative;
  transition: background .25s var(--ease), border-color .25s var(--ease), transform .25s var(--ease);
}
.accept-punkt .haken::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 4px; height: 8px; margin-top: 2px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0); transform-origin: center;
  transition: transform .2s var(--ease);
}
.accept-punkt.ist-gehakt { color: var(--forest); }
.accept-punkt.ist-gehakt .haken {
  background: var(--forest); border-color: var(--forest); transform: scale(1.1);
}
.accept-punkt.ist-gehakt .haken::after { transform: rotate(45deg) scale(1); }
#consentDetails { margin-top: 18px; text-align: left; }

/* --- Einwilligungs-Bildschirm kompakter (Testrunde 18.08.: „auf dem Handy
   schon zu hoch") -----------------------------------------------------------
   Kein Inhalt entfaellt — nur Abstaende und Schriftgroessen sind hier enger
   gefasst als im Rest der App. Das ist der einzige Bildschirm, auf dem alles
   gleichzeitig sichtbar sein muss, damit die Einwilligung als Ganzes erfasst
   werden kann. */
.screen[data-screen="consent"] .card { padding: 26px 22px; }
.screen[data-screen="consent"] h2 { font-size: 23px; margin-bottom: 10px; }
.screen[data-screen="consent"] #consentRecordText {
  font-size: 15px; line-height: 1.45; margin-bottom: 16px;
}
.screen[data-screen="consent"] .field { margin-bottom: 12px; }
.screen[data-screen="consent"] .field span { font-size: 13px; margin-bottom: 5px; }
.screen[data-screen="consent"] .field input { padding: 12px; }
.screen[data-screen="consent"] .deletion-note { font-size: 12.5px; margin-bottom: 6px; }
.screen[data-screen="consent"] .legal-link { margin-bottom: 0; }

/* --- Markenkopf auf dem Startbildschirm --- */
.brand-mark { display: flex; justify-content: center; margin: 4px 0 12px; }
.brand-mark svg { height: 40px; width: auto; }
.brand-title {
  font-family: var(--font-display); font-weight: 700; font-size: 36px;
  letter-spacing: -.015em; margin: 0 0 10px;
}
.question-text.as-caption {
  font-family: var(--font-body); font-size: 12.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .15em; color: rgba(11,37,69,.55);
  margin: 22px 0 4px;
}

/* --- Form fields --- */
.field { display: block; text-align: left; margin: 0 0 18px; }
.field span { display: block; font-size: 14px; color: rgba(11,37,69,.7); margin-bottom: 7px; font-weight: 500; }
.field input {
  width: 100%; padding: 14px; font-size: 16px; font-family: var(--font-body);
  background: #fff; border: 1.6px solid rgba(11,37,69,.16);
  border-radius: 12px; color: var(--navy);
}
.field input:focus { outline: none; border-color: var(--coral); }
.check {
  display: flex; gap: 12px; align-items: flex-start; text-align: left;
  font-size: 15px; color: rgba(11,37,69,.78); margin: 0 0 24px; cursor: pointer;
}
.check input { width: 22px; height: 22px; margin-top: 1px; accent-color: var(--forest); flex: none; }

/* --- Step indicator (3 Fragen) --- */
.steps { display: flex; align-items: center; justify-content: center; gap: 9px; margin: 0 0 18px; }
.steps .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(11,37,69,.18); transition: all .3s var(--ease);
}
.steps .dot.done { background: var(--forest); }
.steps .dot.active { background: var(--coral); transform: scale(1.5); }
.step-label { font-size: 13px; font-weight: 600; letter-spacing: .04em; color: var(--coral); margin-bottom: 14px; }

/* Intro: Vorschau der drei Fragen */
.q-preview { text-align: left; margin: 4px 0 26px; display: grid; gap: 10px; }
.q-preview .q-item {
  display: flex; gap: 12px; align-items: flex-start;
  font-size: 15px; color: rgba(11,37,69,.82); line-height: 1.4;
}
.q-preview .q-num {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  background: var(--navy); color: var(--cream);
  font-size: 13px; font-weight: 700; display: grid; place-items: center; margin-top: 1px;
}
.intro-meta { font-size: 14px; color: var(--forest); font-weight: 600; margin-bottom: 6px; }

/* --- Question screen --- */
.question-text { font-family: var(--font-display); font-weight: 600; font-size: 26px; line-height: 1.25; margin-bottom: 26px; }

/* --- Frage-Video-Anzeige: großflächig, eigene Steuerung statt nativer HTML5-
   Leiste (Fabians Vorgabe, 06.07.): kein Klick zum Einblenden — das Video
   erscheint sofort und versucht automatisch zu starten. Blutet bis an die
   Kartenränder (negative Seiten-Margen = Karten-Innenabstand), damit möglichst
   wenig Rand neben dem Video bleibt; die Höhe folgt dem Seitenverhältnis des
   Videos selbst (Hochformat-Handyvideo wird so hoch, Querformat-Rechnervideo
   entsprechend breiter/flacher) und ist nur nach oben durch max-height
   gedeckelt, damit darunter immer Platz für Text/Button bleibt. */
.question-video-wrap {
  position: relative; margin: 0 -28px 22px; overflow: hidden; background: #000; line-height: 0;
}
.question-video-wrap video {
  width: 100%; height: auto; max-height: 62vh; display: block; object-fit: contain; background: #000;
  /* Das Vorschaubild (poster) soll genauso sitzen wie das Video selbst,
     sonst springt das Bild im Moment des Starts. */
}

/* Dünne Fortschrittslinie ganz oben am Video */
.qv-progress { position: absolute; top: 0; left: 0; right: 0; height: 6px; background: rgba(255,255,255,.28); z-index: 2; }
.qv-progress i { display: block; height: 100%; width: 0%; background: var(--coral); }

/* Kleiner, dauerhafter Play/Pause-Knopf unten links im Video */
.qv-playpause {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%; border: none; cursor: pointer; padding: 0;
  background: rgba(11,37,69,.55); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
}
.qv-playpause svg { width: 13px; height: 13px; fill: #fff; }
.qv-playpause .qv-ico-play { margin-left: 2px; }

/* Laufzeit-Anzeige. Sie steht seit dem 24.08.2026 oben LINKS, auf demselben
   Platz wie der Play-Knopf — sichtbar ist immer nur eines von beidem: die Zeit,
   solange das Video läuft, sonst der Knopf. Oben rechts wurde dadurch frei für
   das Haus-Logo, das vorher darunter hing und halb im Bild wirkte (Fabians
   Vorgabe). Tabellenziffern, damit die Zahl beim Herunterzählen nicht zappelt. */
.qv-time {
  position: absolute; top: 14px; left: 12px; right: auto; z-index: 2;
  font-family: var(--font-body); font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; color: #fff;
  /* Ohne Hintergrund-Pille (Fabians Vorgabe, 16.08.) — die Lesbarkeit über
     hellen Videostellen trägt allein der Schlagschatten. */
  text-shadow: 0 1px 6px rgba(0,0,0,.75), 0 0 2px rgba(0,0,0,.5);
  pointer-events: none;
}

/* Großer, pulsierender Start-Knopf — nur sichtbar, wenn der Browser den
   Autoplay-Versuch blockiert hat (typischerweise beim allerersten Video ohne
   vorherige Interaktion) */
.qv-start {
  position: absolute; inset: 0; margin: auto; z-index: 3;
  width: 72px; height: 72px; border-radius: 50%; border: none; cursor: pointer; padding: 0;
  background: rgba(255,255,255,.94);
  display: flex; align-items: center; justify-content: center;
  animation: qv-pulse 1.7s ease-in-out infinite;
}
.qv-start svg { width: 28px; height: 28px; fill: var(--navy); margin-left: 4px; }

/* Fokusring für das Video. Er liegt bewusst NACH INNEN versetzt: Der Wrap hat
   `overflow: hidden` und das Video füllt ihn randgenau, also hätte ein Ring
   außerhalb der Kante — wo Browser ihn von Haus aus zeichnen — vollständig
   weggeschnitten werden können. Das Video ist seit dem 24.08.2026
   fokussierbar, damit sich das Frage-Video auch per Tastatur anhalten lässt;
   ohne sichtbaren Fokus wäre das fast so wenig wert wie gar kein Fokus
   (WCAG 2.4.7, Gate-1-Befund). Zwei Ringe, weil ein einzelner weißer über
   hellen und ein einzelner dunkler über dunklen Bildstellen verschwindet. */
.question-video-wrap video:focus-visible {
  outline: 3px solid #fff;
  outline-offset: -7px;
  box-shadow: inset 0 0 0 4px rgba(11,37,69,.85);
}
@keyframes qv-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,.55); }
  50%      { box-shadow: 0 0 0 18px rgba(255,255,255,0); }
}

/* --- Vollbild-Video-Modus (Fabians Vorgabe, 06.07.): Frage-/Verzweigungs-/
   Abschluss-Screens sehen aus wie der Aufnahme-Screen — Video füllt den
   ganzen Bildschirm, Text/Buttons schweben als Overlay mit Verlaufs-Scrim
   darüber, statt in einem kleinen gerahmten Kasten zu stecken. Wird per
   JS-Klasse "video-full" auf den jeweiligen .screen gesetzt (prepVideo() in
   app.js) — bewusst NICHT für den Sprachwahl-Screen (dort bleibt das normale
   Karten-Layout, siehe Fabians eigene Ausnahme "Intro-Fenster"). */
.screen.video-full { padding: 0; }
.screen.video-full .card {
  background: transparent; box-shadow: none; border: none;
  max-width: 100%; width: 100%; height: 100%; text-align: center;
  padding: 0 20px max(24px, env(safe-area-inset-bottom));
  display: flex; flex-direction: column; justify-content: flex-end;
}
/* Fabians Vorgabe (16.08.): das VIDEO füllt immer die ganze Fläche — am Handy
   hochkant (9:16), am Rechner quer (16:9), auch im iFrame. Früher war die
   Karte ab 700px auf 480px begrenzt; das ließ am Rechner breite leere Ränder
   stehen. Begrenzt wird jetzt nur noch die TEXT-/BUTTON-Spalte darüber, sonst
   gäbe es wieder bildschirmbreit gestreckte Buttons (Fabians Fund, 06.07.). */
.screen.video-full .card > :not(.question-video-wrap) {
  position: relative; z-index: 1;
  width: 100%; max-width: 520px; margin-left: auto; margin-right: auto;
}
/* z-index: auto (statt 0) ist Absicht: der Video-Bereich darf KEINEN eigenen
   Stapelkontext aufmachen, sonst bleiben seine Bedienelemente (Play/Pause,
   Laufzeit) unter der Text-/Button-Ebene gefangen und sind nicht anklickbar
   (Fabians Fund, 16.08.). Das <video> selbst ist unpositioniert und bleibt
   dadurch trotzdem hinter Text und Buttons. */
.screen.video-full .question-video-wrap {
  position: absolute; inset: 0; margin: 0; z-index: auto; border-radius: 0;
}
/* Bedienelemente über die Text-Ebene heben und in die freie obere Zeile legen.
   Beide sitzen seit dem 24.08.2026 LINKS auf demselben Platz: die Laufzeit,
   solange das Video läuft, sonst der Play-Knopf. Oben rechts steht das Logo. */
.screen.video-full .qv-playpause {
  top: max(12px, env(safe-area-inset-top)); bottom: auto; left: max(12px, env(safe-area-inset-left));
  z-index: 5; width: 36px; height: 36px;
}
.screen.video-full .qv-playpause svg { width: 15px; height: 15px; }
.screen.video-full .qv-time {
  top: max(15px, env(safe-area-inset-top)); left: max(14px, env(safe-area-inset-left));
  right: auto; z-index: 5;
}
.screen.video-full .qv-start { z-index: 6; }
/* Text und Buttons erscheinen erst kurz NACH dem Videostart (Fabians Vorgabe,
   16.08.): zuerst soll das Video wirken, dann kommt die Handlungsaufforderung
   sanft dazu. Solange sie unsichtbar sind, nehmen sie auch keine Klicks an. */
.screen.video-full .card > :not(.question-video-wrap) {
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.screen.video-full.qv-hold .card > :not(.question-video-wrap) {
  opacity: 0; transform: translateY(10px); pointer-events: none;
}
.screen.video-full .question-video-wrap video {
  width: 100%; height: 100%; max-height: none; object-fit: cover;
}
/* Lesbarkeits-Korrektur vom 28.07.2026 (F119).
   Ausgangslage: Der Verlauf lief `rgba(0,0,0,.78)` → `transparent` über die
   unteren 55 % und dünnte im Textbereich stark aus. Am gerenderten Recorder
   gemessen — mit einem Video, das in der UNTEREN Bildhälfte hell ist (weißes
   Hemd, helle Wand auf Brusthöhe, Außenaufnahme): Fragetext **4,19:1**,
   Schrittangabe **3,55:1**. Gefordert sind 4,5:1.
   (In einer früheren Fassung stand hier 1,09:1 — diese Zahl war gerechnet und
   beschrieb den Fall ganz OHNE Verlauf. Sie überzeichnete das Problem; der
   Text war schwer lesbar, nicht unsichtbar.)

   Der Verlauf hält jetzt bis 26 % über dem unteren Rand mindestens 55 % Deckung
   — dort endet der Textblock — und ist ab 46 % vollständig weg.
   DAS IST DER ENTSCHEIDENDE PUNKT: Ein erster Versuch spannte den Verlauf über
   den ganzen Schirm und verdunkelte auf Gesichtshöhe noch um 56 %. Das schützt
   zwar den Text, nimmt dem vollflächigen Video aber genau das, wofür es da ist
   (F118). Ein Scrim darf nur so weit reichen wie der Text, den er trägt. */
.screen.video-full .question-video-wrap::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
      rgba(0,0,0,.88) 0%,
      rgba(0,0,0,.72) 18%,
      rgba(0,0,0,.55) 26%,
      rgba(0,0,0,.28) 34%,
      rgba(0,0,0,0)   46%);
}
.screen.video-full .question-text,
.screen.video-full .choice-sub,
.screen.video-full h1, .screen.video-full h2, .screen.video-full p,
.screen.video-full .thanks-note, .screen.video-full .step-label {
  color: #fff; text-shadow: 0 1px 8px rgba(0,0,0,.45);
}
.screen.video-full .choice-sub { color: rgba(255,255,255,.85); }
.screen.video-full .btn-ghost {
  background: rgba(255,255,255,.14); color: #fff; border-color: rgba(255,255,255,.55);
  backdrop-filter: blur(4px);
}
/* F120 (28.07.): Über Video wurden erledigte und aktive Punkte BEIDE weiß und
   unterschieden sich nur noch durch `transform: scale(1.5)`. Größe allein trägt
   bei 9 px nicht — und in Graustufen gar nicht. Der aktive Punkt bekommt
   deshalb zusätzlich einen Ring; die erledigten bleiben gedeckt weiß. */
.screen.video-full .steps .dot { background: rgba(255,255,255,.35); }
.screen.video-full .steps .dot.done { background: rgba(255,255,255,.80); }
.screen.video-full .steps .dot.active {
  background: #fff; box-shadow: 0 0 0 3px rgba(255,255,255,.34);
}
.screen.video-full .legal-link { color: rgba(255,255,255,.8); }
.screen.video-full .upload-status { color: rgba(255,255,255,.85); }
/* Gate-1-Review-Fund (06.07.): die generische Regel oben hat höhere
   Spezifität (3 Klassen) als .upload-status.ok/.err (2 Klassen) und hätte
   Erfolgs-/Fehlerfarbe beim Upload sonst IMMER überschrieben, unabhängig von
   der Reihenfolge im Stylesheet — helle Varianten extra für dunklen
   Hintergrund ergänzt statt die Basisfarben unlesbar zu übernehmen. */
.screen.video-full .upload-status.ok  { color: #7fd9ab; }
.screen.video-full .upload-status.err { color: #ff9c85; }
/* Gate-1-Review-Fund (06.07.): .thanks-note hat einen fast durchsichtigen
   hellen Hintergrund — mit weißem Text über Video unlesbar. Eigener
   deckender dunkler Hintergrund im Vollbild-Modus. */
.screen.video-full .thanks-note { background: rgba(0,0,0,.55); }

/* --- Recording screen (fullscreen camera, Hochformat) --- */
.screen-record { padding: 0; background: #000; }
#previewCanvas, #preview { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; }
/* Kamera liefert ein anderes Seitenverhältnis als angefragt: dann das GANZE
   Kamerabild zeigen statt es formatfüllend zu beschneiden (Fabians Fund 16.08.,
   das sah aus wie ein starker Zoom). Die Vorschau entspricht so exakt der
   Aufnahme — lieber ein schwarzer Rand als ein heimlicher Ausschnitt. */
#previewCanvas.fit-contain { object-fit: contain; }
/* Die Vorschau ist gespiegelt — so kennt man sich selbst aus dem Spiegel.
   Die AUFNAHME ist es seit dem 17.08. NICHT mehr: Sie geht direkt von der
   Kamera in die Datei, ohne Zwischenschritt. Für ein Archiv ist das richtig,
   sonst stünde jede Schrift im Bild seitenverkehrt. */
#preview { display: none; transform: scaleX(-1); }
.rec-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
/* Kopfbereich oben: Status + Fragetext, mit Sicherheitsabstand zur Notch */
.rec-head {
  padding: max(16px, env(safe-area-inset-top)) 18px 22px;
  /* Dieselbe Korrektur wie unten (F119). Hier fiel sie beim Messen erst auf:
     Aufnahmezeit, „Frage 1/5" und der Fragetext standen über hellem Kamerabild
     bei gemessenen 3,55:1. Der Verlauf hält bis unter die Textzeilen und endet
     dann — er reicht nur so weit wie der Text. */
  background: linear-gradient(to bottom,
      rgba(0,0,0,.80) 0%,
      rgba(0,0,0,.68) 44%,
      rgba(0,0,0,.55) 62%,
      rgba(0,0,0,.20) 80%,
      rgba(0,0,0,0)   100%); color: #fff;
}
.rec-top { display: flex; align-items: center; gap: 10px; }
.rec-dot { width: 13px; height: 13px; border-radius: 50%; background: var(--coral); animation: pulse 1.1s infinite; flex: none; }
@keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:.25;} }
.rec-time { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 16px; }
.rec-step { margin-left: auto; font-size: 13px; font-weight: 600; color: #fff; opacity: .9; }
/* --- Zeit-Hinweis waehrend der Aufnahme (Fabians Vorgabe, 18.08.) ---------
   Sitzt unter der Frage, blendet weich ein und aus. Bewusst klein und ohne
   Blinken: Er soll informieren, nicht drängen. In den letzten Sekunden
   wechselt er auf Koralle, zusammen mit der Uhr oben. */
.rec-hint {
  margin-top: 8px; color: rgba(255,255,255,.82);
  font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
  text-shadow: 0 1px 6px rgba(0,0,0,.55);
  animation: hint-ein .4s var(--ease);
}
.rec-hint.is-knapp { color: #ffb59e; font-weight: 700; }
@keyframes hint-ein { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
/* Die Uhr faerbt sich in den letzten 30 Sekunden mit — ohne Groessensprung,
   damit die Zeile nicht umbricht. */
.rec-time.is-knapp { color: #ffb59e; }

.rec-question {
  margin-top: 10px; color: #fff;
  font-family: var(--font-display); font-weight: 600; font-size: 18px; line-height: 1.3;
  text-shadow: 0 1px 6px rgba(0,0,0,.55);
}
.rec-bottom { display: flex; justify-content: center; padding: 0 0 max(34px, env(safe-area-inset-bottom)); }
.btn-stop {
  pointer-events: auto; cursor: pointer; width: 78px; height: 78px; border-radius: 50%;
  background: rgba(255,255,255,.2); border: 4px solid #fff; display: grid; place-items: center;
}
.btn-stop::after { content: ""; width: 28px; height: 28px; border-radius: 6px; background: var(--coral); }
.btn-stop:active { transform: scale(.93); }

/* --- Review --- (Hochformat-Video zentriert, höhenbegrenzt) ---
   Eigener Player statt Browser-Standard-Steuerleiste: ein zentraler
   Abspiel-Button im Marken-Stil (analog zum Stop-Button der Aufnahme). --- */
.review-player { position: relative; margin: 0 auto 16px; display: inline-block; max-width: 100%; border-radius: 16px; overflow: hidden; background: #000; line-height: 0; }
.review-video { display: block; width: auto; max-width: 100%; max-height: 52vh; background: #000; }

/* --- Sichtung der eigenen Antwort: deutlich größer (Fabians Fund, 17.08.) ---
   Vorher steckte der Player in der 480px-Karte und war am Rechner winzig. Der
   Karten-Stil bleibt, aber diese eine Karte darf breiter werden, und das Video
   nutzt die Höhe wirklich aus. Auf dem Handy zählt die Gegenrichtung: Ein
   hochkantes Video darf NICHT so hoch werden, dass Fragetext und Buttons aus
   dem Bild rutschen — deshalb ist die Höhe an die sichtbare Fensterhöhe
   gekoppelt (dvh) und lässt Platz für Kopf und Buttons. */
/* Der Rahmen bekommt sein Format aus CSS, NICHT aus dem Video (Fabians Fund,
   17.08.: „erst 16:9, dann springt es auf 9:16"). Vorher richtete sich die
   Größe nach dem geladenen Video — bis dessen Maße bekannt waren, stand dort
   ein anderes Format, und der Sprung war sichtbar. Jetzt steht der Rahmen von
   Anfang an, das Video füllt ihn formatfüllend. Am Handy hochkant, am Rechner
   quer — genau wie die Aufnahme selbst aussah. */
.screen[data-screen="review"] .card { max-width: 760px; }
.screen[data-screen="review"] .review-player {
  /* Das Seitenverhaeltnis setzt app.js aus den Massen der Aufnahme; der Wert
     hier ist nur der Startwert, falls die Masse einmal fehlen. Die Hoehe ist
     gedeckelt, damit Fragetext und Buttons im Bild bleiben — der Rahmen wird
     dann schmaler statt das Video zu beschneiden. */
  /* Die BREITE gibt den Takt vor, die Hoehe folgt aus dem Seitenverhaeltnis.
     Das Hoehenbudget steckt in der Breitenformel: breiter als
     (verfuegbare Hoehe x Seitenverhaeltnis) darf der Rahmen nie werden, sonst
     liefe er unten aus dem Bild. So bleibt aspect-ratio IMMER erfuellt.

     Vorher stand hier eine feste `height` plus `max-width: 100%`. Sobald die
     Breitengrenze griff — am Rechner bei jedem queren Video —, waren beide
     Achsen festgelegt, das Seitenverhaeltnis wurde ueberstimmt, und aus dem
     Rahmen wurde ein hochkanter Kasten mit schwarzen Balken (Fabians
     Screenshot, 21.08.). */
  display: block;
  aspect-ratio: var(--vb-ar, 9 / 16);
  width: min(100%, calc((100dvh - 300px) * var(--vb-ar-num, 0.5625)));
  height: auto;
  margin-inline: auto;
}
.screen[data-screen="review"] .review-video {
  /* max-height ausdruecklich zurueckgesetzt (die Grundregel begrenzt auf 52vh).
     `contain` als Sicherheitsnetz: Sollte der Rahmen einmal nicht exakt zur
     Aufnahme passen, entstehen schwarze Raender statt eines Beschnitts — beim
     Pruefen der eigenen Antwort ist Vollstaendigkeit wichtiger als Fuellung. */
  width: 100%; height: 100%; max-height: none; object-fit: contain;
}
@media (min-width: 700px) {
  /* Am Rechner rund doppelt so gross wie bisher (Fabians Wunsch, 17.08.).
     Das Seitenverhaeltnis kommt auch hier aus der Aufnahme; nur das
     Hoehenbudget ist etwas grosszuegiger als am Handy. */
  .screen[data-screen="review"] .card { max-width: 1100px; }
  .screen[data-screen="review"] .review-player {
    width: min(100%, calc((100dvh - 260px) * var(--vb-ar-num, 0.5625)));
  }
}
/* Am Handy etwas Hoehe zurueckgewinnen, damit der Rahmen breiter werden kann */
@media (max-width: 699px) {
  .screen[data-screen="review"] .card { padding: 22px 20px; }
  .screen[data-screen="review"] .question-text { font-size: 21px; margin-bottom: 14px; }
  .screen[data-screen="review"] .step-label { margin-bottom: 8px; }
}
@media (max-height: 700px) {
  .screen[data-screen="review"] .question-text { font-size: 20px; margin-bottom: 14px; }
}
.review-play {
  position: absolute; inset: 0; margin: auto; width: 64px; height: 64px; border-radius: 50%;
  background: rgba(11,37,69,.55); border: 3px solid rgba(255,255,255,.85);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.review-play svg { width: 26px; height: 26px; fill: #fff; margin-left: 4px; }
.review-play:active { transform: scale(.94); }

/* Datei-Masse in der Sichtung, nur mit ?diag=1 */
.review-diag {
  font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; line-height: 1.5;
  color: rgba(11,37,69,.7); background: rgba(11,37,69,.06);
  border-radius: 8px; padding: 7px 10px; margin: 0 0 12px;
}

/* --- Upload status --- */
.upload-status { font-size: 14px; color: rgba(11,37,69,.7); margin: 0 0 16px; min-height: 20px; font-weight: 500; }
.upload-status.ok  { color: var(--forest); font-weight: 700; }
.upload-status.err { color: var(--coral);  font-weight: 700; }
.upload-status .spin {
  display: inline-block; width: 14px; height: 14px; margin-right: 7px; vertical-align: -2px;
  border: 2px solid rgba(11,37,69,.25); border-top-color: var(--coral); border-radius: 50%;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.bar { height: 7px; border-radius: 5px; background: rgba(11,37,69,.12); overflow: hidden; margin-top: 10px; }
.bar > i { display: block; height: 100%; width: 0; background: var(--forest); transition: width .25s var(--ease); }

/* --- Abschlussseite (Fabians Vorgabe, 17.08.) ------------------------------
   Kein Herz, keine große Überschrift — beides überlagerte die Person im
   Abschluss-Video. Es bleiben: Upload-Stand, ein kräftiger Balken und die
   Buttons. „Abschließen" steht zuerst, das ist der Normalfall. */
/* --- Ruhiger Ausklang, wenn das Abschluss-Video durch ist (18.08.) --------
   Das Standbild bleibt als Hintergrund, wird aber weichgezeichnet und
   abgedunkelt. So steht am Ende kein zufaellig eingefrorenes Gesicht, sondern
   eine ruhige Flaeche, auf der Upload-Stand und Buttons klar lesbar sind. */
.screen.video-full .question-video-wrap video { transition: filter 1.4s var(--ease), transform 1.4s var(--ease); }
.screen.video-full.qv-ende .question-video-wrap video { filter: blur(10px) brightness(.5) saturate(.8); transform: scale(1.06); }
.screen.video-full .question-video-wrap::after { transition: height 1.4s var(--ease), background 1.4s var(--ease); }
.screen.video-full.qv-ende .question-video-wrap::after {
  height: 100%;
  background: linear-gradient(to top, rgba(11,37,69,.85), rgba(11,37,69,.55));
}
/* Hinweis auf der Abschlussseite: klein, ruhig, nur waehrend des Uploads */
.thanks-hint {
  font-size: 13.5px; line-height: 1.5; color: rgba(255,255,255,.82);
  margin: -6px 0 14px; text-shadow: 0 1px 6px rgba(0,0,0,.5);
}
/* Dezenter Textknopf (Ausstieg in der Sichtung) — sieht aus wie ein Link,
   verhaelt sich wie ein Knopf, damit die Tastaturbedienung stimmt. */
.quiet-link {
  appearance: none; background: none; border: none; cursor: pointer;
  display: block; margin: 14px auto 0; padding: 6px 10px;
  font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
  color: rgba(11,37,69,.55); text-decoration: underline; text-underline-offset: 3px;
}
.quiet-link:hover { color: var(--navy); }
.screen.video-full .quiet-link { color: rgba(255,255,255,.75); }

.thanks-actions { margin: 4px 0 14px; gap: 10px; }
.thanks-actions .btn { padding: 13px 14px; font-size: 15.5px; white-space: nowrap; }
/* Gesperrter Button während des Uploads: sichtbar, aber erkennbar untätig —
   das Abschluss-Video verlangt einen Button, also steht immer einer da. */
.thanks-actions .btn:disabled { opacity: .55; cursor: default; box-shadow: none; }
/* Kräftigerer Fortschrittsbalken: er trägt jetzt die Hauptaussage der Seite */
.bar-lg { height: 12px; border-radius: 7px; background: rgba(255,255,255,.28); margin: 6px 0 16px; }
.screen.video-full .bar-lg > i { background: #7fd9ab; }
.screen.video-full .upload-status { font-size: 15.5px; font-weight: 600; }

/* Ruhiger Abschluss nach „Abschließen": legt sich über die Danke-Seite, damit
   die nächste Person nicht mitten in einer fremden Sitzung landet. */
/* Der Schleier trägt jetzt zwei Bereiche: die Mitte mit Dank und Knöpfen, und
   ganz unten die Herstellerzeile. `space-between` schiebt sie auseinander, die
   Mitte bleibt durch `margin: auto` wirklich mittig (Fabians Wunsch, 21.08.). */
.closed-veil {
  position: absolute; inset: 0; z-index: 10;
  display: flex; flex-direction: column; align-items: center;
  justify-content: space-between;
  padding: 32px 32px max(20px, env(safe-area-inset-bottom)); text-align: center;
  background: rgba(11,37,69,.96); backdrop-filter: blur(10px);
  animation: rise .5s var(--ease);
}
.closed-mitte {
  margin: auto 0; display: flex; flex-direction: column;
  align-items: center; gap: 14px; width: 100%;
}
.closed-text {
  font-family: var(--font-display); font-weight: 700; font-size: 26px; line-height: 1.25;
  color: var(--cream); margin: 0; max-width: 22ch;
}
.closed-btn {
  width: auto; min-width: 220px; max-width: 100%;
  text-decoration: none; margin-top: 4px;
}
/* Neustart-Knopf: bewusst dezent wie der Sprachknopf „English" auf der
   Startseite (Fabians Vorgabe, 21.08.) — der rote Knopf gehört dem Weg zum
   Haus, dieser hier ist die ruhige Nebenhandlung. Auf dunklem Grund braucht
   der Rahmen naturgemäß helle statt dunkler Linien. */
.closed-again {
  width: auto; min-width: 220px; max-width: 100%; margin-top: 10px;
  background: transparent; color: var(--cream);
  border: 1.6px solid rgba(243,236,224,.42);
}
.closed-again:hover { border-color: rgba(243,236,224,.7); }

/* Herstellerzeile ganz unten. GANZ in Weiß, auch der Text vor dem Link
   (Fabians Präzisierung, 21.08.) — Grau war auf dem dunklen Grund zu schwach.
   Unterschieden werden Text und Link allein durch die Unterstreichung. */
.closed-credit {
  font-family: var(--font-body); font-size: 12px; font-weight: 500;
  color: #fff; margin: 24px 0 0; max-width: 40ch;
}
.closed-credit a {
  color: #fff; text-decoration: underline; text-underline-offset: 2px;
}

/* Technisches Detail auf der Fehlerseite: klein, blass, ganz unten. Es soll
   auffindbar sein, wenn jemand danach fragt, und sonst nicht stören. */
.error-tech {
  font-family: var(--font-body); font-size: 11.5px; line-height: 1.45;
  color: rgba(11,37,69,.58); margin: 22px 0 0;
  word-break: break-word;
}

/* Logo des Hauses. Bewusst ohne eigenen Hintergrund: Die Datei bringt ihre
   Transparenz mit, und ein Kasten darum würde wie ein Fremdkörper wirken.
   Das Logo steht ganz oben rechts, dort wo bis zum 24.08.2026 die Laufzeit
   stand, und ist kleiner als vorher. Es erscheint NUR über den Video-Schirmen
   (siehe body.logo-sichtbar in app.js) — auf den hellen Karten-Seiten lag es
   über dem Text, auf dem Aufnahme-Schirm wird es nicht gebraucht. */
.haus-logo {
  position: fixed; z-index: 15; pointer-events: none;
  right: max(12px, env(safe-area-inset-right));
  top: max(13px, env(safe-area-inset-top));
  height: 22px; width: auto; max-width: 34vw;
  opacity: .95;
  display: none;
}
body.logo-sichtbar .haus-logo:not([hidden]) { display: block; }
@media (min-width: 700px) { .haus-logo { height: 28px; } }

/* Einzige verbliebene Ausweichregel: der Sprachwechsler sitzt auf dem ersten
   Schirm ebenfalls oben rechts. Die Abstände für Laufzeit und Aufnahme-Schirm
   sind entfallen — die Laufzeit steht jetzt links, und auf dem Aufnahme-Schirm
   ist gar kein Logo mehr (24.08.2026). */
body.has-langswitch .haus-logo { top: calc(max(13px, env(safe-area-inset-top)) + 44px); }

/* Über Video: weicher Schatten statt Kasten, damit der Schriftzug auch über
   hellen Bildstellen lesbar bleibt.
   Zusätzlich wird der Schriftzug hier WEISS eingefärbt. Das Logo liegt nur
   EINMAL vor, in der Hausfarbe (Magenta) für die hellen Schirme; auf Schwarz
   und über dem Kamerabild wäre die 4,2:1 zu schwach. `brightness(0)` legt alle
   Farbwerte auf Null, `invert(1)` hebt sie auf Weiß — der Alphakanal bleibt
   unberührt, auch an den weichen Kanten. Eine zweite Bilddatei und damit eine
   zweite Stelle, die beim nächsten Logo-Wechsel vergessen werden kann, spart
   das ganz (24.08.). */
body.video-vollbild .haus-logo {
  filter: brightness(0) invert(1) drop-shadow(0 1px 6px rgba(0,0,0,.6));
}

/* Sehr flache Fenster (Handy quer): kleiner, damit es nichts überdeckt. */
@media (max-height: 520px) { .haus-logo { height: 17px; } }

/* Die Regel, die die Laufzeit unter den Sprach-Wechsel-Link schob, ist am
   24.08.2026 entfallen: Beide sitzen nicht mehr oben rechts, die Laufzeit
   steht jetzt links. */


.thanks-note {
  margin-top: 14px; font-size: 13.5px; color: rgba(11,37,69,.6);
  background: rgba(200,150,65,.14); border-radius: 12px; padding: 12px 14px;
}

/* Aufnahme-Screen füllt randlos, kein Scrollen */
.screen-record { overflow: hidden; }

/* --- Countdown vor der Aufnahme (Fabians Wahl, 17.08.) ---------------------
   Liegt über der Kamera-Vorschau, während die Kamera startet. Die Aufnahme
   beginnt erst, wenn er durch ist — es landen also keine Vorlaufsekunden im
   Video. Zeigt „Kamera startet …", falls das Gerät länger braucht als 3 s. */
.rec-countdown {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  background: rgba(11,37,69,.45); backdrop-filter: blur(2px);
}
/* Ring statt nackter Zahl (Fabians Wunsch, 17.08.): Der Kreis leert sich im
   Sekundentakt, die Zahl sitzt mittig darin. Beides in Manrope — die Serifen
   von Fraunces wirkten an einer großen Ziffer zu verspielt. Beide Schriften
   liegen lokal (schriften.css), es wird nichts nachgeladen. */
.rec-countdown-ring {
  position: relative; width: 168px; height: 168px;
  display: grid; place-items: center;
}
.rec-countdown-ring svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  transform: rotate(-90deg);   /* Start oben statt rechts */
}
.rec-countdown-ring circle { fill: none; stroke-width: 5; stroke-linecap: round; }
.ring-bahn { stroke: rgba(255,255,255,.22); }
/* EIN durchgehender Ring über die ganze Zeit (Fabians Vorgabe, 17.08.) — vorher
   lief er je Sekunde einmal komplett herum, das wirkte hektisch. Jetzt leert er
   sich gleichmäßig über die volle Countdown-Dauer; nur die Zahl darin wechselt.
   Die Dauer kommt als Variable aus app.js, damit CSS und Zähler nie
   auseinanderlaufen. */
.ring-lauf {
  stroke: var(--coral);
  stroke-dasharray: 283;       /* Umfang bei r=45 */
  /* Angestoßen wird die Animation aus app.js (Web Animations). Die CSS-Regel
     bleibt als Rückfall für sehr alte Browser stehen und wird dort über die
     Variable --countdown-dauer gesteuert. */
  animation: ring-leeren var(--countdown-dauer, 0s) linear forwards;
  will-change: stroke-dashoffset;
}
@keyframes ring-leeren {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: 283; }
}
.rec-countdown span {
  position: relative; z-index: 1;
  font-family: var(--font-body); font-weight: 700; font-size: 62px; line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
  color: #fff; text-shadow: 0 2px 14px rgba(0,0,0,.45);
  animation: countdown-puls .8s var(--ease);
}
/* „Kamera startet …" ist ein Wort, keine Ziffer: kleiner, ohne Puls, und der
   Ring hört auf zu laufen — er würde sonst einen Takt vortäuschen. */
.rec-countdown span.is-wort {
  font-size: 15px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; animation: none; max-width: 130px; text-align: center;
}
.rec-countdown:has(span.is-wort) .ring-lauf { animation-duration: 1.6s; opacity: .5; }
@keyframes countdown-puls {
  from { opacity: 0; transform: scale(1.35); }
  55%  { opacity: 1; transform: scale(1); }
  to   { opacity: 1; transform: scale(1); }
}

/* Diagnose-Zeile, nur mit ?diag=1 (Kamera-Format auf echten Geräten klären) */
.rec-diag {
  position: absolute; left: 0; right: 0; z-index: 6;
  bottom: max(110px, env(safe-area-inset-bottom));
  max-height: 55vh; overflow-y: auto; text-align: left;
  padding: 8px 14px; text-align: center;
  font-family: ui-monospace, Menlo, monospace; font-size: 11px; line-height: 1.6;
  color: #fff; background: rgba(11,37,69,.75);
}

/* --- Wechsel-Link bei sprachfestem Link (F71) — nativer <select>, klappt
   beim Antippen direkt die anderen Sprachen auf (kein eigenes Popover nötig,
   funktioniert zuverlässig auch auf iOS/Android). --- */
.lang-switch {
  position: fixed; z-index: 20; cursor: pointer;
  top: max(14px, env(safe-area-inset-top)); right: max(14px, env(safe-area-inset-right));
  appearance: none; -webkit-appearance: none; border: 1px solid rgba(11,37,69,.16);
  background: rgba(251,247,239,.92) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%230b2545' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E") no-repeat right 8px center / 14px;
  backdrop-filter: blur(4px);
  color: var(--navy); font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
  padding: 7px 26px 7px 12px; border-radius: 999px; box-shadow: 0 4px 14px rgba(11,37,69,.10);
}
.lang-switch:active { transform: scale(.96); }

/* --- Datenschutz/Impressum als Overlay statt Seitenwechsel: Aufnahme-
   Sitzung bleibt beim kurzen Nachlesen komplett unberührt. --- */
.legal-modal {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(11,37,69,.55); backdrop-filter: blur(3px);
  display: flex; align-items: flex-end; justify-content: center;
}
@media (min-height: 560px) { .legal-modal { align-items: center; padding: 24px; } }
.legal-modal-inner {
  /* Großzügiger als vorher (Fabians Fund, 16.08.: „Pop-up-Bereich ist zu
     klein"): Rechtstexte sind lang, ein schmales Fenster zwingt zu ewigem
     Scrollen. Jetzt bis 860px breit und 92 % der Höhe. */
  position: relative; width: 100%; max-width: 860px; max-height: 92vh; max-height: 92dvh;
  background: var(--cream-2); border-radius: 22px 22px 0 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 30px 30px max(30px, env(safe-area-inset-bottom));
  box-shadow: 0 -12px 40px rgba(11,37,69,.25);
  /* Dezenter Scrollbalken statt der grauen System-Leiste (Fabians Fund, 16.08.) */
  scrollbar-width: thin;
  scrollbar-color: rgba(11,37,69,.22) transparent;
}
.legal-modal-inner::-webkit-scrollbar { width: 8px; }
.legal-modal-inner::-webkit-scrollbar-track { background: transparent; }
.legal-modal-inner::-webkit-scrollbar-thumb {
  background: rgba(11,37,69,.18); border-radius: 999px;
  border: 2px solid transparent; background-clip: content-box;
}
.legal-modal-inner::-webkit-scrollbar-thumb:hover { background: rgba(11,37,69,.30); background-clip: content-box; }
/* Im Overlay steht der Rechtstext bereits in einem eigenen Rahmen — die
   Seitenränder der Standalone-Seite würden ihn zusätzlich einschnüren. */
.legal-modal-body .legal-page { padding: 0; max-width: none; }
@media (min-height: 560px) { .legal-modal-inner { border-radius: 22px; } }
.legal-modal-close {
  position: sticky; top: 0; float: right; margin: -6px -4px 6px 10px;
  width: 34px; height: 34px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(11,37,69,.08); color: var(--navy); font-size: 15px; line-height: 1;
  z-index: 1;
}
.legal-modal-body .legal-back { display: none; } /* "Zurück"-Link der Standalone-Seite ist im Overlay überflüssig — X-Button übernimmt das */

/* --- Rechtsseite (Datenschutz + Impressum, E14) — eigene, scrollbare Seite
   statt der Screen-Choreografie oben; nutzt dieselbe Palette/Typografie. --- */
.legal-page {
  position: relative; z-index: 1; max-width: 720px; margin: 0 auto;
  padding: max(32px, env(safe-area-inset-top)) 24px max(48px, env(safe-area-inset-bottom));
}
.legal-page .eyebrow { text-align: left; }
.legal-page h1 { font-size: 32px; margin-bottom: 6px; }
.legal-page .legal-lead { font-size: 15px; color: rgba(11,37,69,.6); margin: 0 0 30px; }
.legal-page h2 { font-size: 22px; margin: 40px 0 4px; }
.legal-page h2:first-of-type { margin-top: 8px; }
.legal-page h3 { font-family: var(--font-body); font-size: 15.5px; font-weight: 700; margin: 22px 0 6px; }
.legal-page p, .legal-page li { font-size: 15px; line-height: 1.65; color: rgba(11,37,69,.82); }
.legal-page ul { margin: 0 0 16px; padding-left: 22px; }
.legal-page li { margin-bottom: 6px; }
.legal-page a { color: var(--coral); font-weight: 600; }
.legal-callout {
  background: rgba(30,91,63,.10); border: 1px solid rgba(30,91,63,.22);
  border-radius: 16px; padding: 18px 20px; margin: 8px 0 30px;
}
.legal-callout p { margin: 0; }
.legal-callout p + p { margin-top: 8px; }
.legal-nav { display: flex; gap: 14px; margin-bottom: 30px; font-size: 14px; font-weight: 700; }
.legal-back {
  display: inline-block; margin-top: 40px; font-size: 14px; font-weight: 700;
  color: var(--navy); text-decoration: none; border-bottom: 1.5px solid rgba(11,37,69,.3);
}

/* Kleiner Rechtstext-Link am Seitenende der App (Consent-/Danke-Screen) */
.legal-link {
  display: block; margin: 0 0 20px;
  font-size: 12.5px; color: rgba(11,37,69,.7); text-decoration: underline;
}

/* --- Small phones --- */
@media (max-height: 660px) {
  .card { padding: 26px 22px; }
  .question-video-wrap { margin-left: -22px; margin-right: -22px; }
  h1 { font-size: 26px; } .question-text { font-size: 22px; }
}

/* --- Handy im Querformat: kompakter, damit nichts winzig wirkt und alles in die
   reduzierte Höhe passt (die Aufnahme selbst bleibt randlos). --- */
@media (orientation: landscape) and (max-height: 520px) {
  .card { padding: 18px 24px; max-width: 620px; }
  .question-video-wrap { margin-left: -24px; margin-right: -24px; }
  .question-video-wrap video { max-height: 40vh; }
  h1 { font-size: 22px; margin-bottom: 8px; }
  h2 { font-size: 19px; margin-bottom: 8px; }
  p  { font-size: 14.5px; margin-bottom: 14px; }
  .question-text { font-size: 19px; margin-bottom: 16px; }
  .q-preview { gap: 6px; margin-bottom: 14px; }
  .q-preview .q-item { font-size: 14px; }
  .btn { padding: 12px 20px; font-size: 16px; }
  .review-video { max-height: 36vh; }
  .steps { margin-bottom: 12px; }
}


/* --- „Bewegung reduzieren" beachten (Advisory Review, 18.08.) --------------
   Wer das auf seinem Gerät eingeschaltet hat, bekam trotzdem dauerhaft
   pulsierende Elemente — mitten in einer ohnehin aufregenden Situation vor der
   Kamera. Der Aufnahme-Punkt bleibt SICHTBAR (er ist eine Statusanzeige), hört
   aber auf zu pulsieren; Übergänge werden auf ein Minimum verkürzt statt ganz
   abgeschaltet, damit Zustandswechsel weiterhin nachvollziehbar bleiben. */
@media (prefers-reduced-motion: reduce) {
  .qv-start { animation: none; }
  .rec-dot { animation: none; }
  .rec-countdown span { animation: none; }
  .rec-hint { animation: none; }
  .screen.is-active { animation: none; }
  .closed-veil { animation: none; }
  .accept-punkt, .accept-punkt .haken, .accept-punkt .haken::after { transition-duration: .01ms; }
  .ring-lauf { animation-duration: 0s; }
}
