/* Lokale Kopien der im Handoff festgelegten Familien. Die vier WOFF2-Dateien
 * sind variable Fonts; die Regeln geben ausschliesslich die bisher aus
 * Google Fonts angeforderten Schnitte frei. OFL-1.1 liegt neben den Dateien
 * unter public/fonts/{karla,rokkitt}/OFL.txt. */
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/karla/karla-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/karla/karla-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/karla/karla-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/karla/karla-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/karla/karla-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/karla/karla-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 800; font-display: swap; src: url('/fonts/karla/karla-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Karla'; font-style: normal; font-weight: 800; font-display: swap; src: url('/fonts/karla/karla-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 600; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 600; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 800; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rokkitt'; font-style: normal; font-weight: 800; font-display: swap; src: url('/fonts/rokkitt/rokkitt-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* Carspotter — Oberflaeche nach dem Produktions-Handoff.
 *
 * WOHER DIE ZAHLEN KOMMEN: aus dem Handoff, nicht aus einer Abschrift.
 * Die App-Palette (HANDOFF §11, `--cs-*`), die Schriften (§12), die Skala,
 * Rampen, Abstaende, Radien und Schatten stehen NICHT in dieser Datei — sie
 * werden von scripts/tokens-erzeugen.js aus design/HANDOFF.md und
 * design/_ds/ gelesen und liegen in public/css/tokens.css (Tabelle:
 * design/tokens.json). index.html laedt tokens.css VOR dieser Datei.
 *
 * SEIT WI-0091 IST DER APP-RAUM KEINE ABSCHRIFT MEHR. Bis dahin las der
 * Erzeuger das Sheet der TESTVERSION, und alles, was der Produktions-Handoff
 * darueber hinaus fuehrt — Grund, Flaechen, Textstufen, Zustandsfarben —
 * stand hier von Hand ausgeschrieben. Genau das war die Drift, gegen die
 * WI-0044 gebaut wurde. Jetzt verweist jeder dieser Werte auf sein Token aus
 * §11; was hier noch mit eigenem Wert steht, fuehrt der Handoff NICHT als
 * Token: die Kartenmasse (Designspec Kap. 6) und die Masse der Bildschirme
 * (Kap. 8/10).
 *
 * DIE REGEL DIESER DATEI: unterhalb des Token-Blocks steht KEIN roher Wert
 * mehr — keine Farbe, kein Abstand, kein Radius. Jedes Bauteil greift ueber
 * var() zu. Stimmt ein Wert nicht, wird das TOKEN korrigiert, nie das Bauteil.
 * tests/design.test.js prueft das am GERENDERTEN Bildschirm nach, nicht am
 * Dateitext.
 *
 * Die fuenf Seltenheitsfarben stehen bewusst NICHT hier, sondern in
 * public/js/design.js: sie werden je Karte gesetzt und duerfen deshalb nur an
 * einer einzigen Stelle existieren. Diese Datei kennt sie nur als
 * --r-c / --r-g / --r-glow und faellt ohne sie auf die neutrale Vorstufe
 * zurueck (Kap. 6: vor dem Aufdecken #cfc3ab).
 */

/* == TOKEN-BLOCK: ANFANG == */
:root {
  /* --- Schriften (Kap. 2) ---
     Familien, Skala, Zeilenhoehen und die beiden Laufweiten der Ueberschriften
     kommen aus public/css/tokens.css. Hier stehen nur die Groessen und
     Gewichte, die der Entwurf NICHT als Token fuehrt. */
  --schrift-klein: 12px;
  --schrift-winzig: 10px;
  --schrift-mini: 8.5px;
  /* „Body small" aus HANDOFF §12 (13–14,5 px). Der Entwurf setzt darauf die
     Warnzeile unter dem Sucher (13,5 px/700, Artboard 07). */
  --schrift-hinweis: 13.5px;
  /* Die obere Stufe von „Body small" (§12, 13–14,5 px). Der Entwurf setzt sie
     dort, wo eine Zeile eine Zahl traegt, die gelesen werden soll: „6 von 8
     gewählt" (Artboard 28), die drei Zeilen des Datenblocks (Artboard 27),
     die Handlung einer wartenden Partie (Artboard 22). */
  --schrift-zeile: 14px;
  /* „Section label" aus HANDOFF §12 — die kleine Versalzeile, mit der der
     Entwurf jeden Abschnitt anschreibt (§4.6: 11 px, 800, .08em, versal,
     --cs-text-dim). Sie ist NICHT der h6-Grad der Schriftskala (13 px): die
     Skala beschreibt eine Ueberschrift, dies hier ein Etikett ueber einer
     Gruppe. Bis WI-0096 gab es sie gar nicht, und der Merkmalsvergleich
     meldete auf 22/23/24/27 genau diese fehlende Stufe der Groessenleiter. */
  --schrift-abschnitt: 11px;
  /* „Screen title (tab)" aus HANDOFF §12 — 28 px, zwischen h2 und h3 der
     Skala. Der Entwurf setzt jeden Reiter-Bildschirm darauf (22, 23, 24, 42). */
  --schrift-titel-reiter: 28px;
  /* Die kleinere Stufe daneben: der Bandname der Wurflage (11,5 px/700,
     Handoff v2 §5.6) und ueberall dort, wo eine Zeile eine Auskunft traegt
     und keine Ueberschrift ist. */
  --schrift-hinweis-klein: 11.5px;
  /* Die Intervallzeile unter dem Bandnamen der Wurflage. HANDOFF §5.6
     schreibt sie ausdruecklich aus: `font-size: 10.5px`. Sie ist NICHT
     `--schrift-winzig` (10px) — auf dieser halben Stufe steht die Einheit
     eines Kartenwerts, und beides auf denselben Grad zu legen hat die
     Groessenleiter von 16 verschoben (WI-0129). */
  --schrift-wurf-intervall: 10.5px;
  /* „Board eyebrow" aus HANDOFF §12: 11 px/800/.08em in Versalien. Der
     Wert stand bis WI-0097 roh in `.abschnitt-label`. */
  --schrift-label: 11px;
  --gewicht-fett: 800;
  /* Das dritte Gewicht der Fliesstextfamilie (§12: „Button secondary",
     „Card value", „Tab item"). Es stand bis WI-0068 nicht als Token da,
     weshalb 700 im Fliesstext gar nicht vorkam — genau das meldete der
     Merkmalsvergleich auf `07-scan-viewfinder` als fehlendes Gewicht. */
  --gewicht-kraeftig: 700;
  --gewicht-halb: 500;
  --laufweite-serie: 0.16em;
  --laufweite-wurf: 0.22em;

  /* --- Dunkler App-Raum (HANDOFF §11) ---
     KEIN Wert steht hier mehr ausgeschrieben. Links der Name, unter dem die
     App ihn benutzt, rechts das Token des Handoffs — das ist der ganze
     Inhalt dieses Blocks. Aendert der Handoff einen Ton, aendert er ihn hier
     mit, ohne dass eine Zeile CSS angefasst wird. */
  --raum-bg: var(--cs-bg-top);
  --raum-verlauf: var(--cs-bg);
  --raum-text: var(--cs-text);
  --raum-text-gedaempft: var(--cs-text-mute);
  --raum-text-schwach: var(--cs-text-dim);
  /* DIE VERSAL-KLEINZEILE (WI-0340). Der eigene Ton der Etiketten — der
     Abschnittsmarken, der Feldbeschriftungen, der Einheit hinter einem Wert,
     des Laendercodes auf der Karte. Er liegt zwischen `gedaempft` und
     `schwach` und ist genau DESHALB jahrelang auf einen der beiden
     ausgewichen: §11 fuehrte ihn nicht, und §7 Punkt 12 verbietet einem
     Bauteil, sich einen eigenen Ton auszudenken. Seit HANDOFF §16.7
     (01.10.2026) steht er als `--cs-label` in §11 — die Luecke ist
     geschlossen, nicht umgangen. */
  --raum-text-etikett: var(--cs-label);
  /* Die Meta-Zeile (Fundzeit, Kartennummer) liegt zwischen gedaempft und
     schwach. Der Handoff fuehrt dafuer keine eigene Stufe — §12 nennt fuer
     Captions --cs-text-dim, fuer „Body small" --cs-text-mute. Genommen wird
     die hellere der beiden, weil die Zeile gelesen werden soll. */
  --raum-text-meta: var(--cs-text-mute);
  --raum-fliess: var(--cs-text-2);
  --karten-koerper: var(--cs-surface-card);
  --foto-flaeche: var(--cs-surface-photo);
  --blatt-flaeche: var(--cs-surface);
  /* Der Schleier ueber einem verdeckten Bildschirm, heute unter der
     Loeschabfrage (WI-0070, Artboard 17). */
  --schleier-flaeche: var(--cs-scrim);
  /* Wie weit ein Bildschirm hinter einem Schleier zuruecktritt — verwischt und
     abgedunkelt, aber sichtbar: man soll sehen, worueber man entscheidet. */
  --schleier-unschaerfe: 2px;
  --schleier-deckkraft: 0.4;
  /* Alle hellen Schleier auf dem dunklen Raum sind derselbe Ton in
     verschiedenen Staerken. Der Handoff fuehrt die Reihe als --cs-fill-*
     (Flaechen) und --cs-line-* (Haarlinien) und braucht dafuer keine
     Mischung mehr. */
  --blatt-rand: var(--cs-line-2);
  --feld-flaeche: var(--cs-fill-2);
  --feld-rand: var(--cs-line-3);
  --gruen-flaeche: var(--cs-good-tint);
  /* Den Rand der Erfolgsflaeche fuehrt §11 nicht — er wird aus derselben
     Farbe gemischt statt danebengeschrieben. */
  --gruen-rand: color-mix(in srgb, var(--cs-good) 30%, transparent);
  --gruen-text: var(--cs-good-soft);
  --gruen-icon: var(--cs-good);
  /* Die Eroberung. Sie ist KEINE Aktionsfarbe — Terracotta bleibt den
     Knoepfen —, sondern die Farbe EINER Auskunft: was auf dem Spiel steht,
     und welche Karte gewonnen statt gefunden ist. Der Ton ist derselbe wie
     die epische Seltenheit; §11 fuehrt ihn dort und hier. Flaeche und Rand
     stehen dort nicht und werden aus --cs-r-epic gemischt. */
  --erobert-flaeche: color-mix(in srgb, var(--cs-r-epic) 12%, transparent);
  --erobert-rand: color-mix(in srgb, var(--cs-r-epic) 45%, transparent);
  --erobert-text: var(--cs-epic-soft);
  --erobert-marke: var(--cs-conquered);
  --erobert-marke-text: var(--cs-conquered-ink);
  --warn-icon: var(--cs-warn);
  --warn-flaeche: var(--cs-warn-tint);
  /* Der aufgehellte Warnton der Verlustzeilen auf 45b (WI-0164). §11 fuehrt
     ihn nicht als eigene Stufe — der Entwurf setzt dort einen helleren Amber
     als beim Warnzeichen, damit vier Zeilen hintereinander lesbar bleiben
     und nicht wie vier Alarme wirken. Er wird deshalb GEMISCHT statt
     danebengeschrieben: bewegt der Handoff den Warnton, geht er mit.
     Dieselbe Bauart wie --gruen-rand und --erobert-flaeche darueber. */
  --verlust-text: color-mix(in srgb, var(--warn-icon) 55%, var(--cs-on-accent));
  /* --- Artboard 38b (WI-0183): die verlorene Eroberung ---
     Der Ring: 130px wie in der Niederlage, aber 2,5px Rand im Warnton auf
     einer leisen Warnflaeche — der Entwurf schreibt `rgba(232,154,94,.6)` und
     `rgba(232,154,94,.08)` aus, und das ist Zeichen fuer Zeichen --cs-warn.
     Also wird gemischt, nicht abgeschrieben.

     Die Marke `AN MIRA` ist dieselbe Bauart wie --erobert-marke an der
     eroberten Karte, nur im Warnton: gefuellte Pille bei 90 % Deckung, Schrift
     in einem sehr dunklen Warmton. §11 fuehrt fuer sie keine eigene Stufe —
     --cs-conquered/--cs-conquered-ink sind das Gegenstueck, und der Entwurf
     baut beide gleich. */
  --verlust-ring-rand: 2.5px;
  --verlust-ring-farbe: color-mix(in srgb, var(--warn-icon) 60%, transparent);
  --verlust-ring-flaeche: color-mix(in srgb, var(--warn-icon) 8%, transparent);
  --verlust-marke: color-mix(in srgb, var(--warn-icon) 90%, transparent);
  --verlust-marke-text: color-mix(in srgb, var(--warn-icon) 18%, black);
  --verlust-marke-schrift: 9.5px;
  --verlust-marke-polster: 3px 8px;
  /* Artboard 38b setzt die Groessenleiter der Zeile eigens: den Modellnamen
     auf 18px (eine Stufe ueber der halben Karte, weil hier kein zweiter Name
     danebensteht) und die Herkunftszeile auf 12,5px. Beides steht HIER und
     nicht an `.partie__halb-name`/`.meta` — die tragen ihre Groesse auf
     anderen Bildschirmen weiter. */
  --verlust-name-schrift: 18px;
  --verlust-herkunft-schrift: 12.5px;
  /* Der Bildschirm faengt HOEHER an als 38 und 39: der Entwurf setzt seinen
     ersten Block auf `padding: 28px 26px 138px`, wo die beiden anderen bei
     40 bzw. 48px beginnen. Der Grund ist die Liste — was oben zu viel steht,
     fehlt ihr unten. */
  --verlust-rand-oben: 4px;
  /* Die Miniatur der verlorenen Karte steht bei 55 % — sie ist ein Beleg,
     kein Angebot (Artboard 38b, HANDOFF §5 Zeile 38b). */
  --verlust-streifen-deckkraft: 0.55;
  /* Die hervorgehobene Stelle in einem leisen Satz — heller als der Satz,
     leiser als eine Ueberschrift. §12 fuehrt den Ton als --cs-text-3. */
  --raum-text-hell: var(--cs-text-3);

  /* --- Knoepfe (Kap. 4) --- */
  --btn-hoehe: 48px;
  --btn-hoehe-ghost: 44px;
  --btn-schrift: 16px;
  /* HANDOFF §12 fuehrt „Button secondary" mit 15px/700 — die App setzte bis
     WI-0097 auch den Ghost in 16px/800 und damit so schwer wie die
     Hauptaktion. Genau das soll er nicht: der Ghost tritt zurueck. */
  --btn-schrift-ghost: 15px;
  --btn-text: var(--cs-on-accent);
  --btn-glow: var(--cs-glow-btn);
  --ghost-rand: 1.5px solid var(--cs-line-4);
  --ghost-text: var(--cs-text-3);
  /* Der WARNENDE Ghost. Der Entwurf fuehrt ihn neben dem neutralen als
     eigene Form — dort, wo der Knopf etwas wegnimmt statt weiterzugehen
     („Ja, löschen", Artboard 17). Er bleibt ein Ghost: Terracotta gehoert der
     Hauptaktion, und die Hauptaktion dieser Abfrage ist „Behalten". */
  --ghost-warn-rand: 1.5px solid color-mix(in srgb, var(--warn-icon) 55%, transparent);
  --ghost-warn-text: var(--warn-icon);
  /* Die Pille `Weitere Kartendetails` (WI-0114, §17: 46px, Akzentfuellung,
     Rand `rgba(232,154,94,.7)` — also der Warnton auf 70 % —, Ikone 17px).
     Sie ist die einzige Form zwischen Hauptaktion und Ghost: gefuellt, aber
     nicht Terracotta. */
  --details-hoehe: 46px;
  --details-rand: color-mix(in srgb, var(--warn-icon) 70%, transparent);
  /* DER TON DER AKZENTGEFUELLTEN PILLE (WI-0129).
     Hier stand `--color-accent-200` (#ffe1d0) — eine Sprosse der Akzentrampe
     aus dem Organic-Sheet. Das Sheet ist laut HANDOFF §16 und Designspec
     Kap. 11 Punkt 4 NUR fuer `--color-accent` und die beiden Schriftfamilien
     Quelle; jede andere Farbe kommt aus §11 oder aus dem Entwurf selbst.
     Der Entwurf faerbt diese Form ueberall gleich und nennt sie zweimal
     ausdruecklich: die Pille auf 14/15 und den aktiven Klassen-Chip auf 18/19
     (§16: Fuellung `rgba(198,113,57,.16)`, Rand `rgba(232,154,94,.7)`, Text
     `#f0d9c2`). §11 fuehrt den Ton nicht als eigenes `--cs-*`-Token — deshalb
     steht er HIER, in dem Token, das die Form beschreibt, und nicht im
     Bauteil (Designspec Kap. 9). Gemessen war das eine der beiden fehlenden
     Textfarben auf 14 und 15. */
  --details-text: #f0d9c2;
  --details-ikone: 17px;
  /* DIE SCHRIFTGROESSE DES AKTIONSBLOCKS AUF 14/15 (WI-0129).
     Artboards 14 und 15 zeichnen die Pille und die Reihe darunter
     („Andere Seite" / „Korrigieren") auf 14,5px — eine halbe Stufe unter der
     allgemeinen Ghost-Groesse (§4.5 „Button secondary": 15px), und genau die
     Stufe, die §12 fuer eine „Quiet text action" (14–14,5px/700) fuehrt.
     Die App stand auf 15px; damit fehlte der Groessenleiter von 14 die
     Sprosse zwischen 13 und 15, und die 14px der Tableiste standen einen
     ganzen Punkt daneben. Der Wert gilt NUR fuer diesen Block — der Rest der
     App bleibt bei `--btn-schrift-ghost`. */
  --kd-aktion-schrift: 14.5px;
  /* DAS BESTAETIGUNGSFELD AUF `45c` (WI-0165, HANDOFF §5.5f).
     Der Entwurf zeichnet es als 52-px-Pille mit ambernem Rand und dem
     getippten Namen in der Ueberschriftenschrift auf 19px — hoeher, groesser
     und lauter als jedes andere Feld der App, weil es das einzige ist, dessen
     Inhalt eine ganze Sammlung kostet. Die drei Werte stehen hier zusammen,
     in dem Token, das die Form beschreibt; der Rand ist eine ABLEITUNG aus
     --warn-icon (derselbe Ton wie der zerstoerende Knopf darunter) und kein
     abgeschriebener Farbwert. */
  --bestaetigung-hoehe: 52px;
  --bestaetigung-rand: color-mix(in srgb, var(--warn-icon) 70%, transparent);
  --bestaetigung-schrift: 19px;
  /* --- Artboards 45d und 45f (WI-0166, HANDOFF §5.5f) ---
     Der Laufzustand zeichnet einen 150-px-Ring mit einem 3-px-Bogen darin und
     der Papierkorb-Glyphe auf 54 px; Ring und Bogen tragen den Warnton, der
     Ring auf 35 %, der Bogen voll. Die Zahlen stehen so im Entwurf; der
     Handoff fuehrt sie nicht als Token, deshalb stehen sie hier — dieselbe
     Bauart wie die Erkennungs-Buehne weiter unten.

     Die Farben sind ABLEITUNGEN aus --warn-icon und keine abgeschriebenen
     Werte: bewegt der Handoff den Warnton, gehen Ring, Bogen, Glyphe und der
     Fehlerblock von 45f gemeinsam mit. */
  --loeschlauf-ring: 150px;
  --loeschlauf-ring-rand: 2px;
  --loeschlauf-bogen: 3px;
  --loeschlauf-glyphe: 54px;
  --loeschlauf-strich: 2.4;
  --loeschlauf-ring-farbe: color-mix(in srgb, var(--warn-icon) 35%, transparent);
  --loeschlauf-dauer: 1.1s;
  /* Die drei Groessen von `45d`. Der Entwurf setzt die Aussage auf 30px —
     zwischen h2 (32) und dem Reiter-Titel (28) der Skala —, den Umfangssatz
     auf die obere Stufe von „Body small" (§12: 13–14,5px) und die Zeile
     „Abbrechen geht ab hier nicht mehr" auf die Caption-Stufe (12,5px, §12
     Zeile „helper"). Die Skala fuehrt weder 30 noch 12,5 als Sprosse; sie
     stehen deshalb hier, in den Token, die diese Formen beschreiben. */
  --loeschlauf-titel-schrift: 30px;
  --loeschlauf-umfang-schrift: 14.5px;
  --loeschlauf-bleib-schrift: 12.5px;
  /* Der Fehlerblock von `45f`: amberne Flaeche auf 10 %, Rand auf 40 %. Er ist
     LEISER als die Warnpille (--cs-warn-tint, 16 %) — was hier steht, ist eine
     Beruhigung und kein Alarm. */
  --loeschfehler-flaeche: color-mix(in srgb, var(--warn-icon) 10%, transparent);
  --loeschfehler-rand: color-mix(in srgb, var(--warn-icon) 40%, transparent);
  /* DER TON DER ZUSICHERUNGSZEILE (`45f`).
     Derselbe Fall wie --details-text darueber: §11 fuehrt diese Aufhellung des
     Warntons nicht als eigenes --cs-*-Token, und der Entwurf schreibt sie
     ausdruecklich aus (`#f0c79c`). Sie steht deshalb HIER, in dem Token, das
     die Form beschreibt, und nicht im Bauteil (Designspec Kap. 9). Eine
     Mischung aus --warn-icon traefe sie nur ungefaehr — und dies ist die Zeile,
     die eine ganze Sammlung fuer sicher erklaert. */
  --loeschfehler-zusicherung-text: #f0c79c;
  --loeschfehler-radius: 22px;
  --loeschfehler-weg-radius: 20px;
  /* ARTBOARD 44 — ADRESSKARTE UND DREI SCHRITTE (WI-0350). Die Werte stehen
     so auf dem Brett. Die Nummernkreise mischen sich aus --color-accent
     (.18 Flaeche, .55 Rand), die Ziffer traegt dieselbe ausgeschriebene
     Aufhellung wie die Zusicherungszeile von `45f` — §11 fuehrt sie nicht. */
  --geraetewechsel-adresse-radius: 22px;
  --geraetewechsel-adresse-schrift: 23px;
  /* Brett 45: dieselbe Karte, 21 px Schrift und 20 px Radius (WI-0351). */
  --abmelden-adresse-radius: 20px;
  --abmelden-adresse-schrift: 21px;
  --abmelden-adresse-polster: 14px;
  --abmelden-adresse-zeile: 25px;
  --abmelden-adresse-etikett-abstand: 6px;
  --geraetewechsel-schritt-hoehe: 44px;
  --geraetewechsel-nummer: 28px;
  --geraetewechsel-nummer-schrift: 13px;
  --geraetewechsel-nummer-flaeche: color-mix(in srgb, var(--color-accent) 18%, transparent);
  --geraetewechsel-nummer-rand: color-mix(in srgb, var(--color-accent) 55%, transparent);
  --geraetewechsel-nummer-text: #f0c79c;
  --geraetewechsel-schritt-schrift: 14.5px;
  /* Der Entwurf setzt die Zusicherung auf 14,5 px und den Satz darunter auf
     13,5 px — die beiden Stufen von „Body small" (§12), hier bewusst
     gegeneinander gesetzt: die erste Zeile ist die Nachricht. Der leise Block
     mit dem Weg von Hand steht eine halbe Stufe tiefer (13px, §12 „Body
     small" unten), die Ueberschrift auf 26px — eine Sprosse ueber h3 (25),
     die die Skala nicht fuehrt. */
  --loeschfehler-schrift-zusicherung: 14.5px;
  --loeschfehler-schrift-weg: 13px;
  --loeschfehler-titel-schrift: 26px;
  /* --- Artboard 45e (WI-0167, HANDOFF §5.5f, Umsetzungs-Handoff 13.5) ---
     Der Abschluss zeichnet einen 130-px-Kreis mit 2,5-px-Rand, darin der Haken
     auf 52 px. Ring, Flaeche und Glyphe tragen den GUT-Ton — dieselbe
     Ableitungsbauart wie 45d aus --warn-icon, nur eben aus --gruen-icon. Der
     Entwurf schreibt `rgba(164,199,107,…)` aus; das ist Zeichen fuer Zeichen
     --cs-good, also wird gemischt und nicht abgeschrieben.

     KEINE SELTENHEITSFARBE. --cs-r-uncommon traegt denselben Wert, gehoert
     aber ausschliesslich der Seltenheitstabelle (Designspec Kap. 9); ein
     Erfolgskreis, der sich daraus bediente, waere beim naechsten Stufenton
     stillschweigend mitgewandert. */
  --loeschfertig-ring: 130px;
  --loeschfertig-ring-rand: 2.5px;
  --loeschfertig-ring-farbe: color-mix(in srgb, var(--gruen-icon) 50%, transparent);
  --loeschfertig-ring-flaeche: color-mix(in srgb, var(--gruen-icon) 10%, transparent);
  --loeschfertig-glyphe: 52px;
  --loeschfertig-strich: 2.75;
  /* Die drei Groessen von `45e` — dieselbe Ueberlegung wie bei `45d`: die
     Aussage auf 32px (die h2-Sprosse aus §12, hier eine Stufe ueber `45d`,
     weil dieser Bildschirm keine Zahlen traegt), der Dank auf der oberen
     Stufe von „Body small" und die Zeile ueber die Weiterleitung auf der
     Caption-Stufe. */
  --loeschfertig-titel-schrift: 32px;
  --loeschfertig-dank-schrift: 14.5px;
  --loeschfertig-gleich-schrift: 12.5px;
  /* DER WEITERLEITUNGSBALKEN. 6px hoch, Spur wie beim Rundenauftakt, und der
     Lauf traegt die Aktionsfarbe — so zeichnet der Entwurf ihn
     (`background: var(--color-accent)`).

     DIE DAUER STEHT HIER EIN ZWEITES MAL. Massgeblich ist `LOESCHFERTIG_MS`
     in public/js/app.js: die Uhr traegt den Uebergang, der Balken malt ihn
     nur mit (bei abgeschalteter Bewegung malt er gar nichts und die Frist
     laeuft trotzdem). tests/screens.test.js haelt die beiden Zahlen
     gegeneinander, damit sie nicht auseinanderlaufen. */
  --loeschfertig-balken: 6px;
  --loeschfertig-balken-spur: color-mix(in srgb, var(--cs-text) 10%, transparent);
  --loeschfertig-balken-dauer: 4s;
  --deaktiviert-deckkraft: 0.4;
  /* DIE AUSGESCHALTETE HAUPTAKTION (WI-0112). HANDOFF §4.5, Zeile „Primary
     disabled": `background: rgba(198,113,57,.35); color: rgba(249,244,237,.55)`,
     kein Schein. §11 fuehrt die Flaeche als eigenes Token
     (--cs-accent-disabled) — es war eines der Token, die der Handoff
     ausschreibt und die App nirgends benutzte.
     Die App hat den Zustand stattdessen ueber die DECKKRAFT des ganzen
     Knopfes gemalt. Das sieht aehnlich aus und ist doch etwas anderes: es
     blasst auch den Schein und den Rand aus, es haengt am Grund darunter,
     und im Vergleich gegen den Entwurf taucht der Knopf mit VOLLER
     Terracotta-Farbe auf, weil eine Deckkraft die Farbe nicht aendert. Der
     Ton fuer die Schrift steht in §4.5 ohne eigenes Token und wird deshalb
     aus --cs-on-accent gemischt. */
  --btn-flaeche-aus: var(--cs-accent-disabled);
  --btn-text-aus: color-mix(in srgb, var(--cs-on-accent) 55%, transparent);

  /* --- Seltenheit: neutrale Vorstufe (Kap. 6) --- */
  --neutral-c: var(--color-neutral-800);
  --neutral-g: var(--cs-text-2);
  --neutral-glow: 207, 195, 171;
  --kante-neutral: 0 0 0 1.5px color-mix(in srgb, var(--cs-text) 18%, transparent);
  /* Die Seltenheitsfarbe selbst — hier steht sie auf der neutralen Vorstufe
     (#cfc3ab, Kap. 6). Sie ist damit UEBERALL belegt: eine Silhouette auf dem
     Auswahl-Bildschirm oder im Scan-Sucher steht ausserhalb jeder Karte, und
     ihr `stroke: var(--r-g)` darf dort nicht ins Leere zeigen. Die fuenf
     echten Toene kommen je Karte aus public/js/design.js und ueberschreiben
     diese drei Werte am seltenheitsgefuehrten Element. */
  --r-c: var(--neutral-c);
  --r-g: var(--neutral-g);
  --r-glow: var(--neutral-glow);

  /* --- Karte: Format (Kartenspec Kap. 2) --- */
  /* Das Format 59:91 gilt fuer JEDE Ansicht der Karte — Wurf, Detail, Vollbild. */
  --karte-format-b: 59;
  --karte-format-h: 91;

  /* --- Karte: Wurfansicht (Artboard 13) --- */
  /* WI-0097: der Entwurf zeichnet die Aufdeckkarte 305 px breit, nicht 256.
     Die 256x395 aus Designspec Kap. 6 waren die Testversion; `13-card-reveal`
     ist das, wogegen jetzt gemessen wird. Wie bei Detail und Vollbild ist
     JEDES Innenmass sein Mass aus dem Artboard, geteilt durch die
     Bezugsbreite und auf die tatsaechliche Breite hochgerechnet — damit
     schrumpft die Karte auf einem schmalen Geraet als Ganzes, statt ihre
     Beschriftungen zu sprengen. */
  --kw-bezug: 305;
  --kw-breite: min(
    calc(var(--kw-bezug) * 1px),
    calc(100vw - var(--space-4) * 2),
    calc((var(--sicher-hoehe) - var(--kw-umfeld)) * var(--karte-format-b) / var(--karte-format-h))
  );
  /* Was auf dem Aufdeckbildschirm ausser der Karte Hoehe braucht: die
     Augenbraue „NEUE KARTE" mit ihrem Polster, das Polster der Buehne und der
     untere Block aus Hauptknopf, Ghost, Verweiszeile und ihren Fugen. */
  --kw-umfeld: calc(
    var(--space-4) + var(--kd-zeile) + var(--space-3) * 2 + var(--btn-hoehe) + var(--btn-hoehe-ghost) +
      var(--kd-zeile) + var(--space-3) * 3
  );
  --kw-hoehe: calc(var(--kw-breite) * var(--karte-format-h) / var(--karte-format-b));
  --kw-radius: calc(var(--kw-breite) * 22 / var(--kw-bezug));
  --kw-polster-y: calc(var(--kw-breite) * 13 / var(--kw-bezug));
  --kw-polster-x: calc(var(--kw-breite) * 14 / var(--kw-bezug));
  --kw-kreis: calc(var(--kw-breite) * 42 / var(--kw-bezug));
  --kw-kopf: calc(var(--kw-breite) * 33 / var(--kw-bezug));
  --kw-flagge-b: calc(var(--kw-breite) * 25 / var(--kw-bezug));
  --kw-flagge-h: calc(var(--kw-breite) * 17 / var(--kw-bezug));
  /* Der Modellname steht seit dem 29.08.2026 im KOPF, wo bis dahin das
     Baujahr stand — und in dessen Groesse (23 px, Designspec Kap. 6). Der
     zweite Grad ist der, in dem der Name bis dahin unter dem Foto stand: ein
     langer Name (`Mercedes-Benz G-Klasse`) faellt darauf zurueck, statt
     abgeschnitten zu werden. Beide Werte sind aus Kap. 6, keiner ist neu. */
  /* Fotoband, 305 / 150 = 2,03. Es steht in `FOTOBAENDER`
     (public/js/filterchain.js) — wer es aendert, aendert den Zuschnitt der
     Filterkette mit; die Herleitung steht dort, die Begruendung an
     --km-foto-h. */
  --kw-foto-h: calc(var(--kw-breite) * 150 / var(--kw-bezug));
  --kw-modell: calc(var(--kw-breite) * 22 / var(--kw-bezug));
  --kw-modell-lang: calc(var(--kw-breite) * 16 / var(--kw-bezug));
  --kw-land: calc(var(--kw-breite) * 21 / var(--kw-bezug));
  --kw-label: calc(var(--kw-breite) * 104 / var(--kw-bezug));
  --kw-wert: calc(var(--kw-breite) * 66 / var(--kw-bezug));
  /* Die Beschriftung ist KLEINER als der Wert daneben (12,5 gegen 14) und
     steht in gemischter Schreibung — siehe .wertzeile__label. */
  --kw-label-schrift: calc(var(--kw-breite) * 12.5 / var(--kw-bezug));
  --kw-schrift-h5: calc(var(--kw-breite) * 14 / var(--kw-bezug));
  --kw-schrift-h6: calc(var(--kw-breite) * 12 / var(--kw-bezug));
  /* DER GRUPPENKREIS HAT SEINEN EIGENEN GRAD (WI-0129).
     §12 fuehrt „Card group circle" (display, 15–18px) und „Card series bar"
     (body, 10,5–12px) als ZWEI Zeilen; die App hat beide auf
     `--k-schrift-h6` gelegt und den Kreis damit in der Groesse des
     Serienbands gemalt. Gemessen war das der Grund, aus dem der obersten
     Sprosse der Groessenleiter auf 16 die Textmenge fehlte, um in die sechs
     haeufigsten zu kommen. Die Zahl je Kartengroesse steht im Entwurf:
     18px auf 13, 16px auf 14/15, 17px auf 16, 19px auf 15b. */
  --kw-gruppe-schrift: calc(var(--kw-breite) * 18 / var(--kw-bezug));
  --kw-schrift-winzig: calc(var(--kw-breite) * 11 / var(--kw-bezug));
  --kw-schrift-mini: calc(var(--kw-breite) * 10 / var(--kw-bezug));
  --kw-balken: calc(var(--kw-breite) * 8 / var(--kw-bezug));

  /* --- Karte: Detailansicht (Kap. 6) --- */
  /* Die Detailkarte hat seit WI-0038 keine feste Groesse mehr. Fest waren
     290x447 — auf 393x793 blieben darunter rund 140px ungenutzt liegen. Jetzt
     nimmt sie die Hoehe, die zwischen Buehnenkante und Tableiste frei ist, und
     rechnet daraus wie die maximierte Karte (WI-0035) ihre ganze Massreihe:
     JEDES Innenmass ist sein Mass aus Kap. 6, geteilt durch die Bezugsbreite
     --kd-bezug und auf die neue Breite hochgerechnet. Die Karte waechst damit
     als Ganzes, und Knoepfe, Datenblock und Hinweis ruecken einfach mit. */
  --kd-bezug: 290;
  /* Was auf der Kartenseite ausser der Karte Hoehe braucht — in derselben
     Reihenfolge, in der es dort steht: Polster der Buehne oben, die Kopfzeile
     mit dem Schliessen-Kreuz, die drei Abstaende der Stapelung, der
     Hinweistext (zwei Zeilen) und der zweistoeckige Aktionsblock (Pille plus
     Knopfreihe), dazu der Fussfreiraum ueber der Leiste.

     DIE METAZEILE STEHT SEIT v3 NICHT MEHR DARIN (§17): sie ist von 14 und 15
     in den Abschnitt `Eckdaten` der Detailansicht gewandert. An ihre Stelle
     tritt in dieser Rechnung die Pille `Weitere Kartendetails`, die es zu v2
     noch nicht gab — der Aktionsblock steht seit WI-0114 auf zwei Ebenen. */
  --kd-zeile: calc(var(--schrift-klein) * var(--zeilenhoehe-fliess));
  /* Die Kopfzeile des Notausgangs (WI-0055): die Trefferflaeche des Kreuzes
     plus die Fuge zur Karte. Sie ist der Grund, warum die Kartenseite oben
     mit einem knapperen Polster auskommt als die anderen Bildschirme — sonst
     stuenden Polster und Kopfzeile uebereinander und die Karte verloere ohne
     Not rund 26px Hoehe. So kostet der Notausgang die Karte nur die
     Differenz. */
  --kd-rand-oben: var(--space-2);
  --kd-kopfzeile: calc(var(--btn-hoehe-ghost) + var(--space-2));
  --kd-pille: calc(var(--details-hoehe) + var(--space-3));
  --kd-hinweis: calc(var(--kd-zeile) * 2);
  /* Der Fussfreiraum der KARTENSEITE: die schwebende Leiste plus eine Reserve
     darueber. Die Reserve ist fuer schmale Geraete, auf denen der Hinweis in
     eine dritte Zeile bricht — er rutscht dann in sie hinein statt unter die
     Leiste. Der allgemeine --buehne-unten ist absichtlich grosszuegiger; hier
     gehoert die Differenz der Karte, denn genau dieser ungenutzte Streifen
     ueber der Leiste war die Meldung.

     WI-0093 HAT DIE RESERVE UM EINE STUFE VERKLEINERT, von einer vollen
     Textzeile (--kd-zeile, 18.6px) auf --space-3 (13.2px). Der Grund ist eine
     Kollision zweier bindender Zusagen, und die aeltere gewinnt:

       - HANDOFF §4.3 macht die Leiste hoeher, als sie war — 44px
         Trefferflaeche statt 36px, 6px Polster statt 4.4px. Ihr Platzbedarf
         waechst dadurch von 63px auf 74px.
       - WI-0038 (Designspec Kap. 10.1, aus echtem Geraetegebrauch und
         ausdruecklich NEUER als der Entwurf) sagt zu, dass die Detailkarte
         GROESSER ist als die frueher feste 290x447 — dieselbe Groesse, die
         der Entwurf in §5.1 fuer `14-card-detail` zeichnet.

     Mit voller Reserve waere die Karte auf 393x793 auf 288x445 gefallen, also
     unter beide Masse. Die Reserve traegt die Differenz, weil sie das einzige
     Mass auf dieser Seite ist, das reine Luft ist und keinen Inhalt. Sie
     bleibt eine Reserve — nur eine Stufe knapper. */
  --karte-fuss: calc(var(--tableiste-unten) + var(--tableiste-hoehe) + var(--space-3));
  --kd-umfeld: calc(
    var(--kd-rand-oben) + var(--kd-kopfzeile) + var(--space-3) * 3 + var(--btn-hoehe-ghost) +
      var(--kd-pille) + var(--kd-hinweis) + var(--karte-fuss)
  );
  /* Unter dieses Mass geht die Karte nicht: auf einem sehr niedrigen Fenster
     blaettert die Seite lieber, als dass die Karte zur Briefmarke wird. */
  --kd-mindest: 180px;
  /* So gross, wie Hoehe UND Breite es zulassen — und kein Pixel groesser. */
  /* WI-0097 — DIE OBERGRENZE AUS DEM ENTWURF.
     `14-card-detail` zeichnet die Karte 290 px breit auf einem 393er Rahmen;
     die App liess sie bis hierher auf rund 358 px wachsen und schob damit
     Datenblock und Hinweis nach unten aus dem Bild. Das Item nennt die Karte
     ausdruecklich „deutlich kompakter, darunter bleibt Platz".

     WI-0038 (Designspec Kap. 10.1, aus echtem Geraetegebrauch und bindend)
     bleibt dabei UNANGETASTET: seine Forderung war „keine feste Hoehe, wo das
     Geraet Platz hat, und keine tote Flaeche unter der Karte". Beides gilt
     weiter — die Karte rechnet ihre Masse nach wie vor aus der freien Hoehe,
     und der Platz unter ihr ist nicht leer, sondern traegt seit diesem Item
     den dreispaltigen Datenblock UND den Satz zur Eroberungshistorie. Was
     dazukommt, ist nur eine Decke: sie waechst nicht mehr ueber das Mass
     hinaus, das der Entwurf zeichnet. */
  --kd-breite: max(
    var(--kd-mindest),
    min(
      calc(var(--kd-bezug) * 1px),
      calc(100vw - var(--space-4) * 2),
      calc(var(--buehne-max) - var(--space-4) * 2),
      calc((var(--sicher-hoehe) - var(--kd-umfeld)) * var(--karte-format-b) / var(--karte-format-h))
    )
  );
  --kd-hoehe: calc(var(--kd-breite) * var(--karte-format-h) / var(--karte-format-b));
  --kd-radius: calc(var(--kd-breite) * 20 / var(--kd-bezug));
  --kd-polster-y: calc(var(--kd-breite) * 13 / var(--kd-bezug));
  --kd-polster-x: calc(var(--kd-breite) * 14 / var(--kd-bezug));
  --kd-kreis: calc(var(--kd-breite) * 37 / var(--kd-bezug));
  --kd-kopf: calc(var(--kd-breite) * 29 / var(--kd-bezug));
  --kd-flagge-b: calc(var(--kd-breite) * 22 / var(--kd-bezug));
  --kd-flagge-h: calc(var(--kd-breite) * 15 / var(--kd-bezug));
  /* Fotoband, 290 / 140 = 2,07. Es steht in `FOTOBAENDER`
     (public/js/filterchain.js) — wer es aendert, aendert den Zuschnitt der
     Filterkette mit; Begruendung an --km-foto-h. */
  --kd-foto-h: calc(var(--kd-breite) * 140 / var(--kd-bezug));
  --kd-modell: calc(var(--kd-breite) * 26 / var(--kd-bezug));
  --kd-modell-lang: calc(var(--kd-breite) * 18 / var(--kd-bezug));
  --kd-land: calc(var(--kd-breite) * 18 / var(--kd-bezug));
  --kd-label: calc(var(--kd-breite) * 88 / var(--kd-bezug));
  --kd-wert: calc(var(--kd-breite) * 58 / var(--kd-bezug));
  --kd-label-schrift: calc(var(--kd-breite) * 11.5 / var(--kd-bezug));
  --kd-schrift-h5: calc(var(--kd-breite) * 13 / var(--kd-bezug));
  --kd-schrift-h6: calc(var(--kd-breite) * 11 / var(--kd-bezug));
  /* Artboards 14 und 15 zeichnen den Gruppenkreis auf 16px (WI-0129, siehe
     die Herleitung an --kw-gruppe-schrift). */
  --kd-gruppe-schrift: calc(var(--kd-breite) * 16 / var(--kd-bezug));
  --kd-schrift-winzig: calc(var(--kd-breite) * 11 / var(--kd-bezug));
  --kd-schrift-mini: calc(var(--kd-breite) * 10 / var(--kd-bezug));
  --kd-balken: calc(var(--kd-breite) * 7 / var(--kd-bezug));

  /* --- Karte: maximierte Ansicht (Artboard 16, Handoff v2 §5.6) --- */
  /* DIE VOLLBILDKARTE IST SEIT v2 EINE ANDERE KARTE ALS DETAIL UND WURF —
     nicht in ihrem Aussehen, aber in ihrem Aufbau. §5.6 nennt es „compact
     mode": das Fotoband waechst von 104 auf 132 px, und die sechs
     Wertezeilen verlieren ihre Balkenspuren und stehen als zwei Spalten reiner
     Zahlen. Beides zusammen ist es, was den Platz fuer den Abschnitt „Dein
     Wurf" und die Besitzerkette DARUNTER erst schafft.

     Deshalb gilt hier das Format 59:91 NICHT. Der Entwurf zeichnet 352 x 412 —
     eine breitere, flachere Karte —, und die Hoehe rechnet aus diesem
     Verhaeltnis, nicht aus dem Quartettformat. Wurf und Detail sind davon
     unberuehrt, sie bleiben 59:91 (Kartenspec Kap. 2).

     Wie ueberall gilt: JEDES Innenmass ist sein Mass aus dem Artboard,
     geteilt durch die Bezugsbreite und hochgerechnet. */
  --kv-bezug: 352;
  --kv-format-h: 412;
  /* Die Schliesszeile oben (v2 §17: `Schließen` unten ist ENTFALLEN, an seine
     Stelle tritt das 34px-Kreuz oben rechts) und der Rand zum Bildschirm. */
  --kv-rand: var(--space-3);
  --kv-kopfzeile: calc(var(--btn-hoehe-ghost) + var(--space-3) * 2);
  /* Die Karte nimmt hoechstens die Haelfte der Hoehe: darunter liegt die
     Leseregion, und die ist kein Rest, sondern der halbe Zweck dieses
     Bildschirms. Der Entwurf gibt ihr 416 von 793 px. */
  --kv-frei: calc((var(--sicher-hoehe) - var(--kv-kopfzeile)) * 416 / 693);
  --kv-breite: min(
    calc(var(--kv-bezug) * 1px),
    calc(100vw - var(--kv-rand) * 2),
    calc(var(--kv-frei) * var(--kv-bezug) / var(--kv-format-h))
  );
  --kv-hoehe: calc(var(--kv-breite) * var(--kv-format-h) / var(--kv-bezug));
  --kv-radius: calc(var(--kv-breite) * 24 / var(--kv-bezug));
  --kv-polster-y: calc(var(--kv-breite) * 15 / var(--kv-bezug));
  --kv-polster-x: calc(var(--kv-breite) * 16 / var(--kv-bezug));
  --kv-kreis: calc(var(--kv-breite) * 40 / var(--kv-bezug));
  --kv-kopf: calc(var(--kv-breite) * 31 / var(--kv-bezug));
  --kv-flagge-b: calc(var(--kv-breite) * 24 / var(--kv-bezug));
  --kv-flagge-h: calc(var(--kv-breite) * 16 / var(--kv-bezug));
  /* DAS BREITESTE FOTOBAND VON ALLEN, 352 / 132 = 2,667 — und damit das,
     das die GEGENPROBE des Zuschnitts setzt (WI-0125): hier ist das
     gespeicherte Foto schmaler als das Band, `cover` passt es auf die Breite
     ein und laesst von der Hoehe nur 1,522 / 2,667 = 57 % sehen. Deshalb darf
     der Fahrzeugkasten hoechstens 57 % der Zuschnitthoehe einnehmen.
     Wer diese Zahl aendert, aendert `SICHTBARER_HOEHENANTEIL` in
     public/js/filterchain.js mit. */
  --kv-foto-h: calc(var(--kv-breite) * 132 / var(--kv-bezug));
  --kv-modell: calc(var(--kv-breite) * 21 / var(--kv-bezug));
  --kv-modell-lang: calc(var(--kv-breite) * 16 / var(--kv-bezug));
  --kv-land: calc(var(--kv-breite) * 20 / var(--kv-bezug));
  /* Label- und Wertspalte gibt es im Kompaktmodus nicht mehr — die Zellen
     teilen sich zu zweit die Breite. Die beiden Masse bleiben trotzdem
     gesetzt, weil `.karte` sie fuer alle Varianten erwartet. */
  --kv-label: auto;
  --kv-wert: auto;
  --kv-label-schrift: calc(var(--kv-breite) * 11.5 / var(--kv-bezug));
  --kv-schrift-h5: calc(var(--kv-breite) * 17 / var(--kv-bezug));
  --kv-schrift-h6: calc(var(--kv-breite) * 11.5 / var(--kv-bezug));
  /* Artboard 16 zeichnet den Gruppenkreis auf 17px — dieselbe Sprosse wie die
     Wertespalte daneben (WI-0129, siehe --kw-gruppe-schrift). */
  --kv-gruppe-schrift: calc(var(--kv-breite) * 17 / var(--kv-bezug));
  --kv-schrift-winzig: calc(var(--kv-breite) * 11 / var(--kv-bezug));
  --kv-schrift-mini: calc(var(--kv-breite) * 10 / var(--kv-bezug));
  --kv-balken: calc(var(--kv-breite) * 7 / var(--kv-bezug));

  /* --- Karte: maximierte Ansicht (Artboard 15b, Handoff v3 §17) --- */
  /* DAS ZIEL DES DOPPELTIPPS SEIT v3. Nur die Karte, ganzflaechig — kein
     Wurf, keine Kette, kein Aktionsblock, keine Tableiste. Der Entwurf
     zeichnet 353 px breit und rund 632 px hoch: eine eigene Form, wie schon
     die Vollbildkarte, und wieder NICHT das Quartettformat 59:91 (Wurf und
     Detail bleiben davon unberuehrt, Kartenspec Kap. 2).

     WAS SIE VON DER VOLLBILDKARTE UNTERSCHEIDET, ist nicht die Groesse,
     sondern die Werteliste: hier stehen die sechs Zeilen MIT Balken (§17),
     dort ohne. Der Grund ist der Bildschirm darum — auf 16 sagt der Abschnitt
     „Dein Wurf" darunter dasselbe genauer, auf 15b steht darunter nichts.

     Wie ueberall: jedes Innenmass ist sein Mass aus dem Artboard, geteilt
     durch die Bezugsbreite und hochgerechnet. */
  --km-bezug: 353;
  --km-format-h: 632;
  --km-rand: var(--space-3);
  /* Kopfzeile (Stand links, 34px-Kreuz rechts) und Punktreihe unten. Was
     beide zusammen einnehmen, steht der Karte nicht zur Verfuegung. */
  --km-kopfzeile: calc(var(--btn-hoehe-ghost) + var(--space-3) * 2);
  --km-punktzeile: calc(var(--km-punkt-hoehe) + var(--space-4) * 2);
  --km-breite: min(
    calc(var(--km-bezug) * 1px),
    calc(100vw - var(--km-rand) * 2),
    calc(
      (var(--sicher-hoehe) - var(--km-kopfzeile) - var(--km-punktzeile)) * var(--km-bezug) /
        var(--km-format-h)
    )
  );
  --km-hoehe: calc(var(--km-breite) * var(--km-format-h) / var(--km-bezug));
  --km-radius: calc(var(--km-breite) * 26 / var(--km-bezug));
  --km-polster-y: calc(var(--km-breite) * 18 / var(--km-bezug));
  --km-polster-x: calc(var(--km-breite) * 18 / var(--km-bezug));
  --km-kreis: calc(var(--km-breite) * 46 / var(--km-bezug));
  --km-kopf: calc(var(--km-breite) * 36 / var(--km-bezug));
  --km-flagge-b: calc(var(--km-breite) * 27 / var(--km-bezug));
  --km-flagge-h: calc(var(--km-breite) * 18 / var(--km-bezug));
  /* DIESES BAND IST DAS SCHMALSTE VON ALLEN — und damit das, auf dessen
     Format die Filterkette jedes Foto zuschneidet (WI-0125).

     353 / 232 = 1,522. Die Fotoflaeche zeigt das gespeicherte Bild mit
     `object-fit: cover` (.karte__foto img); `cover` schneidet immer die Achse
     weg, von der zu viel da ist. Waere das Foto breiter als 1,522, naehme
     `cover` hier links und rechts weg — also genau die Laenge des Autos, und
     auf dem GROESSTEN Bildschirm am meisten. Genau das war der Fehler, den
     Rob am 31.08.2026 gemeldet hat.

     WER DIESE ZAHL AENDERT, AENDERT DEN ZUSCHNITT MIT: `FOTOBAENDER` und
     `ZUSCHNITT_FORMAT` in public/js/filterchain.js. Dort steht die ganze
     Herleitung, hier steht die Kopplung — dieselbe Doppelnotiz, die camera.js
     zwischen Sucher und Aufnahme fuehrt. Wird das Band schmaler, muss das
     Zielformat mitgehen, sonst schneidet `cover` wieder das Auto an.
     Bereits gespeicherte Fotos behalten ihren Zuschnitt: Karten sind
     unveraenderlich (Kartenspec Kap. 4/9). */
  --km-foto-h: calc(var(--km-breite) * 232 / var(--km-bezug));
  --km-modell: calc(var(--km-breite) * 26 / var(--km-bezug));
  --km-modell-lang: calc(var(--km-breite) * 19 / var(--km-bezug));
  --km-land: calc(var(--km-breite) * 22 / var(--km-bezug));
  /* Das Raster der Wertezeilen: `100px / 1fr / 92px` (§17). */
  --km-label: calc(var(--km-breite) * 100 / var(--km-bezug));
  --km-wert: calc(var(--km-breite) * 92 / var(--km-bezug));
  --km-label-schrift: calc(var(--km-breite) * 13 / var(--km-bezug));
  --km-schrift-h5: calc(var(--km-breite) * 18 / var(--km-bezug));
  --km-schrift-h6: calc(var(--km-breite) * 12.5 / var(--km-bezug));
  /* Artboard 15b zeichnet den Gruppenkreis auf 19px (WI-0129, siehe
     --kw-gruppe-schrift). */
  --km-gruppe-schrift: calc(var(--km-breite) * 19 / var(--km-bezug));
  --km-schrift-winzig: calc(var(--km-breite) * 11.5 / var(--km-bezug));
  --km-schrift-mini: calc(var(--km-breite) * 12 / var(--km-bezug));
  --km-balken: calc(var(--km-breite) * 8 / var(--km-bezug));
  /* Der Streifen der Nachbarkarte, der ueber den Rand hinausschaut (§17):
     18 px breit, 2 px Rand in IHRER Seltenheitsfarbe, halb durchsichtig. */
  --km-nachbar-b: 18px;
  --km-nachbar-versatz: -14px;
  --km-nachbar-rand: 2px;
  --km-nachbar-deckkraft: 0.5;
  /* Die Positionspunkte unten: fuenf, der aktive 16 x 5 in der Akzentfarbe. */
  --km-punkt-hoehe: 5px;
  --km-punkt-aktiv-b: 16px;
  --km-punkt-fuge: 7px;
  /* Der ruhende Punkt: der Entwurf setzt ihn auf `rgba(245,234,216,.24)` —
     das ist die Linienleiter aus §11, Stufe 3. Kein eigener Ton. */
  --km-punkt-ruhe: var(--cs-line-3);

  /* --- Die Leseregion unter der Vollbildkarte (v2 §5.6) --- */
  /* Sie ROLLT, und das ist eine Entscheidung des Entwurfs, kein Notventil:
     das Sichtfenster ist 219 px hoch, der fuenfzeilige Fall 299 px. Die
     Maskenkante von 12 px sagt an, dass unten noch etwas liegt. */
  /* `--wurflage-rand: 32px` ist mit WI-0329 (Befund 16-2) ENTFALLEN. Der
     seitliche Rand der Leseregion ist keine eigene Zahl mehr, sondern die
     linke Kante der Karte darueber — er wird in `.kartevoll__lesen` aus
     `--kv-breite` gerechnet. Zwei Zahlen fuer eine Kante waren der Versatz. */
  --wurflage-fuge: 12px;
  --wurflage-zeile: 30px;
  --wurflage-label: 92px;
  --wurflage-band: 104px;
  --wurflage-spur: 6px;
  --wurflage-marke-b: 4px;
  --wurflage-marke-h: 14px;
  /* Der Schein um den Marker (§5.6: `0 0 8px`). */
  --wurflage-marke-schein: 0 0 8px;
  --kette-label: 96px;

  /* --- Der Abschnitt `Eckdaten` (v3 §17, Artboard 16) ---
     Der erste Abschnitt der Leseregion. Er traegt die Kunde, die bis v2 als
     Metazeile UNTER der Karte auf 14 und 15 stand — dort ist sie ersatzlos
     entfallen und steht jetzt genau einmal hier.

     Das Raster ist `auto auto minmax(0,1fr)` (§5.5b): die beiden festen
     Zellen behalten ihre Breite, der Fundort nimmt den Rest und wird am ENDE
     beschnitten. Zweizeilig darf er nie werden — die Zeile wuechse und
     schoebe die Leseregion. */
  --eckdaten-schrift: 12.5px;
  /* Die Spaltenfuge: der Entwurf zeichnet 26 px, was auf der 4,4er-Leiter des
     Handoffs genau zwei Stufen 3 sind. Sie traegt seit v3 auch der Datenblock
     von Artboard 27 — er ist der letzte, der ihn noch benutzt. */
  --datenblock-fuge: calc(var(--space-3) * 2);
  /* DIE DREI ZEILEN VON ARTBOARD 27 ALS FLAECHE (WI-0188). Der Entwurf
     zeichnet sie mit `padding:12px 16px`, `border-radius:16px` und 10 px
     Abstand. 12, 16 und 10 stehen nicht auf der 4,4er-Abstandsleiter des
     Handoffs — sie sind gezeichnete Masse EINES Bauteils, wie die Geometrie
     der schwebenden Leiste weiter oben, und stehen deshalb hier benannt statt
     als rohe Zahl in der Regel. Die Rundung ist die Stufe `md` aus §13. */
  --datenblock-zeile-polster-oben: 12px;
  --datenblock-zeile-polster-seite: 16px;
  --datenblock-zeile-luecke: 10px;
  --datenblock-zeile-radius: var(--radius-md);
  /* Zweizeilige Auskuenfte stehen enger als Fliesstext (§5.6: line-height
     1.25 in der rechten Spalte der Wurflage). */
  --zeilenhoehe-eng: 1.25;
  /* Der Schein hinter dem Marker der Wurflage — je Band derselbe Ton wie der
     Marker selbst, auf .75 Deckkraft (§5.6). */
  --glow-gut: color-mix(in srgb, var(--cs-good) 75%, transparent);
  --glow-neutral: color-mix(in srgb, var(--cs-text-2) 75%, transparent);
  --glow-warn: color-mix(in srgb, var(--cs-warn) 75%, transparent);

  /* Die Flaeche unter dem Bild einer Kachel: das Artboard zeichnet
     rgba(245,234,216,.04), die Reihe des Handoffs beginnt bei .05
     (--cs-fill-1). Die naechste Stufe statt eines eigenen Wertes. Der Name
     stammt vom entfernten Blatt `Foto wechseln` (WI-0422); die Kacheln des
     gleichen Typs (13c) und der Garage nutzen ihn weiter. */
  --fotowahl-daten-flaeche: var(--cs-fill-1);

  /* --- Der gleiche Typ als eigene Karte (WI-0283, Artboard
         13c-card-duplicate im Oktober-Entwurf, HANDOFF §25) ---

     EIGENE TOKENS UND KEINE GELIEHENEN. Die Masse stimmen mit denen des alten
     Wiederfunds darunter ueberein — derselbe Platz, dieselbe Zeichnung —, aber
     der `doppelfund` wird abgerissen (eigenes Item), und mit ihm gehen seine
     Tokens. Ein Bildschirm, dessen Masse an einem Block haengen, der
     verschwindet, waere beim Abriss still kaputt.

     Alle Werte stehen am Artboard und fuehrt der Handoff nicht als globales
     Token; sie stehen deshalb hier mit ihrer Herkunft daneben. */

  /* Die Karte oben: 118 x 166 px, 16 px Rundung, 2,5 px Ring in der
     Seltenheitsfarbe. Der Ring ist ein Schatten und kein Rand — so waechst
     die Flaeche nicht, und der Zaehler sitzt an ihrer Ecke wie gezeichnet. */
  --duplikat-karte-breite: 118px;
  --duplikat-karte-hoehe: 166px;
  --duplikat-karte-radius: 16px;
  --duplikat-karte-ring: 2.5px;
  --duplikat-karte-unten: 20px;
  /* Der Zaehler an der Ecke: 44 px hoch (die Mindestgroesse dieses Produkts),
     12 px seitlich, 19 px in der Ueberschriftenschrift, 10 px ueber und 14 px
     neben den oberen rechten Rand gezogen.
     DIE FLAECHE IST DIE SALBEIFARBE DES HANDOFFS (§11 `--cs-good`). DIE TINTE
     DARIN IST EINE LUECKE: das Artboard zeichnet #1e2416, §11 fuehrt den Ton
     nicht. Genommen ist der dunkelste Grund des Handoffs statt einer eigens
     ausgeschriebenen Farbe — gemeldet, nicht gefuellt. */
  --duplikat-zaehler-hoehe: 44px;
  --duplikat-zaehler-seite: 12px;
  --duplikat-zaehler-schrift: 19px;
  --duplikat-zaehler-oben: -10px;
  --duplikat-zaehler-rechts: -14px;
  --duplikat-zaehler-flaeche: var(--cs-good);
  --duplikat-zaehler-text: var(--cs-bg-bottom);
  /* Der Satz unter dem Titel steht auf 13 px im schwaecheren Textton — leiser
     als die Nachricht darueber, weil er die Regel nennt. */
  --duplikat-werte-unten: 18px;
  /* Die beiden Kacheln: 10 px Fuge, Bildflaeche 96 px, Datenflaeche
     `padding: 8px 10px 10px`, 12 px fuer die Rolle, 11 px fuer die Zeile
     darunter. Die NEUE Kachel traegt den Akzentring (2,5 px) — sie ist die
     Karte, die eben entstanden ist. */
  --duplikat-fuge: 10px;
  --duplikat-bild-hoehe: 96px;
  --duplikat-ring: 2.5px;
  --duplikat-daten-oben: 8px;
  --duplikat-daten-seite: 10px;
  --duplikat-rolle-schrift: 12px;
  --duplikat-wann-schrift: var(--schrift-abschnitt);
  /* DER TON DER NEUEN ROLLE IST DIESELBE LUECKE WIE AUF 13d: das Artboard
     zeichnet #f0b98d, §11 fuehrt ihn nicht und hat --cs-accent-300 daneben.
     Die naechstliegende Stufe des Handoffs statt eines eigenen Wertes. */
  --duplikat-rolle-neu: var(--cs-accent-300);

  /* --- Der Wiederfund (WI-0212, Artboards 13c-card-duplicate und
         13d-card-duplicate-early, HANDOFF §8.1) ---

     Wie beim Blatt darueber stehen diese Masse auf dem Artboard und fuehrt
     der Handoff sie nicht als globales Token. Sie stehen deshalb HIER mit
     ihrer Herkunft daneben und nicht roh im Bauteil. */

  /* Die Karte oben: 118 x 166 px mit 16 px Rundung und einem 2,5 px breiten
     Ring in der Seltenheitsfarbe. Der Ring ist ein Schatten und kein Rand —
     so waechst die Flaeche nicht, und der Zaehler an ihrer Ecke sitzt an
     derselben Stelle wie im Entwurf. */
  --doppelfund-karte-breite: 118px;
  --doppelfund-karte-hoehe: 166px;
  --doppelfund-karte-ring: 2.5px;
  --doppelfund-karte-unten: 20px;
  /* Der Zaehler an der Ecke: 44 px hoch (die Mindestgroesse dieses Produkts),
     Innenmass 12 px seitlich, 19 px in der Ueberschriftenschrift, 10 px ueber
     und 14 px neben den oberen rechten Rand der Karte gezogen. */
  --doppelfund-zaehler-hoehe: 44px;
  --doppelfund-zaehler-seite: 12px;
  --doppelfund-zaehler-schrift: 19px;
  --doppelfund-zaehler-oben: -10px;
  --doppelfund-zaehler-rechts: -14px;
  /* DIE FLAECHE IST DIE SALBEIFARBE DES HANDOFFS (§11 `--cs-good`) — „a sage
     4x counter popping at its corner" (§8.1). DIE TINTE DARIN IST EINE LUECKE:
     das Artboard zeichnet #1e2416, §11 fuehrt diesen Ton nicht. Genommen ist
     der dunkelste Grund des Handoffs (--cs-bg-bottom, #171410) statt einer
     eigens ausgeschriebenen Farbe — gemeldet, nicht gefuellt. Dieselbe Regel
     wie beim Datum auf 14b darueber. */
  --doppelfund-zaehler-flaeche: var(--cs-good);
  --doppelfund-zaehler-text: var(--cs-bg-bottom);
  /* Die beiden Kacheln: 10 px Fuge, Bildflaeche 104 px auf 13c und 96 px auf
     13d (der gesperrte Zustand zeichnet sie flacher, weil der Hinweis darunter
     Platz braucht). Der Ring der gewaehlten Kachel ist 2,5 px, wie oben an der
     Karte. */
  --doppelfund-fuge: 10px;
  --doppelfund-bild-hoehe: 104px;
  --doppelfund-ring: 2.5px;
  /* Datum und Rolle unter der Bildflaeche: `padding: 8px 10px 10px`, 12 px
     fuer die Rolle, 11 px fuer die Zeile darunter — dieselben Sprossen wie auf
     14b. */
  --doppelfund-daten-oben: 8px;
  --doppelfund-daten-seite: 10px;
  --doppelfund-rolle-schrift: 12px;
  --doppelfund-wann-schrift: var(--schrift-abschnitt);
  /* DER TON DER GEWAEHLTEN ROLLE IST EINE LUECKE. Das Artboard zeichnet
     #f0b98d; §11 fuehrt ihn nicht und hat --cs-accent-300 (#f6a06b) daneben.
     Die naechstliegende Stufe des Handoffs statt eines eigenen Wertes. */
  --doppelfund-rolle-gewaehlt: var(--cs-accent-300);
  /* Der Haken auf der gewaehlten Kachel: 22 px Scheibe, 8 px vom oberen und
     rechten Rand, 12 px/800 in der Akzentschrift. */
  --doppelfund-haken-scheibe: 22px;
  --doppelfund-haken-rand: 8px;
  --doppelfund-haken-schrift: 12px;
  /* Der gesperrte Hinweis von 13d: gestrichelter Rahmen mit 18 px Rundung und
     `padding: 12px 14px`, 12 px unter den Kacheln. 18 px liegt zwischen den
     Stufen `md` (16) und `lg` (28) des Handoffs — es ist ein gezeichnetes Mass
     DIESES Bauteils und steht deshalb benannt hier. */
  --doppelfund-hinweis-radius: 18px;
  --doppelfund-hinweis-oben: 12px;
  --doppelfund-hinweis-polster-oben: 12px;
  --doppelfund-hinweis-polster-seite: 14px;
  --doppelfund-hinweis-rand: 1px dashed var(--cs-line-3);
  /* Das noch gesperrte neue Bild steht auf .45 Deckkraft (§8.1: „both tiles
     are still shown — the new one at 45%"). */
  --doppelfund-gesperrt-deckkraft: 0.45;

  /* Die Scheibe hinter dem Schliessen-Kreuz (Artboards 14/15/16). Der
     Entwurf zeichnet den Rand mit .18 Deckkraft; der Handoff fuehrt an dieser
     Stufe kein Token (§11 hat .14 und .22 daneben). Genommen wird die
     naechstliegende Stufe des Handoffs statt eines dritten, eigens
     ausgeschriebenen Wertes — Designspec Kap. 9: stimmt eine Farbe nicht,
     wird das TOKEN korrigiert, nie das Bauteil. */
  --kreuz-scheibe: 34px;
  --kreuz-flaeche: var(--cs-fill-2);
  --kreuz-rand: 1px solid var(--cs-line-2);

  --karte-rand: 1.5px;
  --karte-kopf-radius: 7px;
  /* Die Haarlinie unter jeder Zelle des Kompaktmodus (§5.6) — derselbe Ton
     wie die leere Balkenspur, weil es dieselbe Trennung ist. */
  --karte-hairline: 1px solid var(--cs-line-1);
  /* Die Pille hinter dem Fotovermerk. Sie ist bewusst KEIN Raumton, sondern
     Schwarz mit Deckkraft: sie liegt auf einem Foto, dessen Helligkeit
     niemand kennt, und muss auf einem weissen Autodach genauso tragen wie auf
     einem nachtblauen. */
  --foto-vermerk-flaeche: rgba(0, 0, 0, 0.45);
  /* Die Fundmarken auf dem Foto (WI-0283, HANDOFF §24.1: „24px circles bottom
     left in the photo (`rgba(19,17,16,.72)`), border `line-4`, symbol `text`
     13px, 4px gap"). Die Scheibe ist aus demselben Grund kein Raumton wie die
     Pille darueber: sie liegt auf einem Foto, dessen Helligkeit niemand kennt.
     §24.1 nennt genau diesen Wert — er ist der dunkelste Grund des Handoffs
     mit Deckkraft, und er steht hier als Token statt im Bauteil.
     KEINE SELTENHEITSFARBE: „Colour carries no meaning, so no rarity colour
     is taken." */
  --fundmarke-flaeche: rgba(19, 17, 16, 0.72);
  --fundmarke-rand: 1px solid var(--cs-line-4);
  --fundmarke-scheibe: 24px;
  --fundmarke-symbol: 13px;
  --fundmarke-strich: 2.75;
  --fundmarke-abstand: 4px;
  /* Dieselbe Marke im Abschnitt `Fundmarken` des Vollbilds: 28px-Scheibe,
     14px-Symbol, 10px zum Satz (Artboard `16-card-fullscreen-marks`). Sie ist
     groesser als die auf dem Foto, weil sie nicht auf einem Bild liegt,
     sondern in einer Textzeile steht. */
  --markenzeile-scheibe: 28px;
  --markenzeile-symbol: 14px;
  --markenzeile-fuge: 10px;
  --balken-hoehe: 7px;
  --balken-spur: color-mix(in srgb, var(--cs-text) 10%, transparent);
  --karte-abwaerts: var(--warn-icon);
  /* DER KARTENRUECKEN IST EIN VERLAUF, KEINE FLAECHE (WI-0112). HANDOFF §5.2
     zeichnet ihn als `linear-gradient(165deg,#c67139,#9d5527)`, und §11 fuehrt
     genau das als --cs-back. Die App hat stattdessen die flache Aktionsfarbe
     genommen — der dunkle zweite Ton (#9d5527) kam auf keinem Bildschirm vor,
     obwohl der Entwurf ihn auf jedem Duellbrett zeigt. */
  --rueckseite-flaeche: var(--cs-back);
  --rueckseite-rand: 5px;
  --rueckseite-kreis: 118px;

  /* --- Aufdecken (Kap. 7) --- */
  --karte-start-skalierung: 0.92;
  --perspektive: 1200px;
  --flip-start: 180deg;
  --flip-dauer: 0.6s;
  --flip-kurve: cubic-bezier(0.35, 0.1, 0.25, 1);
  --erscheinen-dauer: 0.25s;
  --zeile-dauer: 0.28s;
  --zeile-versatz: 5px;
  --halo-dauer: 2.6s;

  /* --- Blaettern (WI-0034/0035, seit WI-0051 in beiden Ansichten gleich) --- */
  /* Zurueckfedern unter der Schwelle. */
  --wisch-dauer: 0.18s;
  /* Weg und Dauer der Aus- und Einflugbewegung. Der Weg reicht ueber die
     Breite der Wischflaeche hinaus — die Karte ist wirklich aus dem Bild,
     bevor die naechste kommt. */
  --wisch-flug-weg: 120%;
  --wisch-flug-dauer: 0.18s;
  /* Wie weit der Kartenschein ueber die abschneidende Kante hinausdarf: der
     Schein misst 26 px (Kap. 5), --space-6 ist das Mass darueber. Ohne diesen
     Rand schnitte das waagerechte Abschneiden der Kartenseite ihn mit ab. */
  --wisch-schnitt-rand: var(--space-6);

  /* --- Der Rueckweg, Artboards 03 und 04 (WI-0172) ---
     Drei Masse, die der Entwurf auf diesen beiden Artboards ausdruecklich
     setzt und die es sonst nirgends gibt. Sie stehen HIER als benannte Werte
     und nicht als Zahl in der Regel darunter — dieselbe Disziplin wie beim
     Sucher: wo der Entwurf ein Mass nennt, traegt es seinen Namen. */
  /* Die Fusszeile behaelt ihre Hoehe, auch wenn sie nichts sagt (der Entwurf
     setzt `height:17px` auf beiden Artboards). Ohne sie huepfte die
     Aktionsgruppe, sobald die Zeile etwas zu melden hat. */
  --zeile-fussnote: 17px;
  --ikone-absage: 18px;

  /* --- Der Elternpfad, Artboards 05 und 06 (WI-0174) ---
     Die Masse, die der Entwurf auf genau diesen beiden Artboards setzt und
     die es sonst nirgends gibt. Sie stehen HIER als benannte Werte und nicht
     als Zahl in der Regel darunter — dieselbe Disziplin wie beim Rueckweg
     darueber: wo der Entwurf ein Mass nennt, traegt es seinen Namen. */
  /* Das Adressfeld auf 05 ist hoeher als ein gewoehnliches Feld (52 px statt
     48) — dasselbe Mass wie das Bestaetigungsfeld auf 04, und aus demselben
     Grund: es ist das einzige Feld auf seinem Bildschirm. */
  --feld-hoehe-eltern: 52px;
  /* Die beiden Standzeilen auf 06 (`border-radius:18px; padding:14px 16px`)
     und der Abstand zwischen ihnen. */
  --elternzeile-radius: 18px;
  --elternzeile-polster: 14px 16px;
  --elternzeile-ikone: 20px;

  /* --- Bildschirme (Kap. 8) --- */
  --start-kreis: 56px;
  --start-kreis-form: 46% 54% 55% 45% / 52% 44% 56% 48%;
  /* Das App-Icon auf Artboard 01 (WI-0223, nachgemessen mit WI-0281).
     WI-0223 hat 160/36 aus dem September-Brett gelesen und richtig gebaut;
     das Oktober-Brett zeichnet am `<img>` von `01-onboarding-start`
     `width:132px;height:132px;border-radius:30px` — dieselben Masse, die
     `00-email-entry` daneben traegt. Beide Tokens bleiben trotzdem getrennt:
     ein gemeinsames hiesse, dass die naechste Bewegung auf einem der beiden
     Artboards das andere ungemessen mitnimmt. Die Scheibe `--start-kreis`
     bleibt unberuehrt — sie traegt weiter den Fingerabdruck auf 03. */
  --start-marke: 132px;
  --start-marke-radius: 30px;
  --start-titel: 34px;

  /* --- Die E-Mail-Anmeldung (WI-0279, Oktober-Entwurf, Artboards 00–00l,
         06b–06f) --- */
  /* DAS ICON AUF `00` IST KLEINER ALS DAS AUF `01`. Beide Masse stehen in
     ihrem eigenen Artboard: `01-onboarding-start` zeichnet 160/36 (siehe
     `--start-marke` darueber, WI-0223), `00-email-entry` zeichnet
     `width:132px;height:132px;border-radius:30px`. Ein gemeinsames Token
     hiesse, eines der beiden Artboards ungemessen zu veraendern. */
  --einstieg-marke: 132px;
  --einstieg-marke-radius: 30px;
  /* Der Platz der Meldung unter dem Feld. Er steht AUCH LEER, sonst wandert
     der ganze Block beim ersten Fehler nach oben — `00d` verlangt
     ausdruecklich, dass der Knopf bleibt, wo er war. Der Entwurf gibt dem
     Absatz `min-height:38px`. */
  --einstieg-meldung-hoehe: 38px;
  /* DER RAND DES ADRESSFELDES AUF `00`, `00f` UND `00k`.
     Der Entwurf malt ihn `rgba(232,154,94,.7)` — und das ist Zeichen fuer
     Zeichen `--cs-warn` bei 70 %, nicht die Aktionsfarbe. Das ist Absicht und
     kein Fehler im Brett: das Feld ist die eine Stelle, an der etwas
     eingegeben wird, und der warme Rand sagt genau das. Gemischt statt
     danebengeschrieben, damit die Quelle der Farbe die eine bleibt (§7 Punkt
     12: kein Bauteil denkt sich einen eigenen Ton aus).
     DER FEHLERZUSTAND `00d` UNTERSCHEIDET SICH TROTZDEM EINDEUTIG: dort steht
     derselbe Ton in VOLLER Staerke und mit `--cs-warn-tint` als Flaeche
     (siehe `.feld--warn`). */
  --einstieg-feld-rand: color-mix(in srgb, var(--cs-warn) 70%, transparent);
  /* Die vier Ziffernkaestchen von `00b` (Entwurf: `height:58px`,
     `border-radius:16px`, `gap:12px`, Schriftgrad 26 px in der
     Ueberschriftenfamilie). */
  --ziffer-hoehe: 58px;
  --ziffer-radius: var(--radius-md);
  --ziffer-luecke: 12px;
  --ziffer-schrift: 26px;
  /* Das Kaestchen, das als naechstes dran ist: Akzentfuellung und ein
     staerkerer Rand in der Aktionsfarbe. Es ist eine ANZEIGE und keine
     Aktion — deshalb nur Rand und Tinte, kein gefuellter Terracottablock
     (Designspec Kap. 11: Terracotta bleibt die Aktionsfarbe). */
  --ziffer-dran-rand: 2px;
  /* Der Hinweiskasten von `00b`, `00h`, `00i`, `00j` und `00l` (Entwurf:
     `border-radius:20px`, `padding:16px 18px`, Zeichen 20 px). */
  --anmeldekasten-radius: 20px;
  --anmeldekasten-polster-y: 16px;
  --anmeldekasten-polster-x: 18px;
  --anmeldekasten-zeichen: 20px;
  /* Die Zurueck-Zeile am Kopf (Entwurf: `min-height:44px`, Winkel 18 px,
     Schriftgrad 14 px, Gewicht 700). */
  --kopfweg-hoehe: 44px;
  --kopfweg-zeichen: 18px;
  /* Die Fusszeile unter dem Nebenweg. Sie behaelt ihre Hoehe, auch wenn kein
     Satz darin steht (Entwurf: `height:17px` auf jedem dieser Artboards). */
  --anmeldefuss-note: 17px;
  /* DER FUSSFREIRAUM DIESER BILDSCHIRME IST KLEINER ALS DER ALLGEMEINE.
     `--buehne-unten` haelt 90 px frei, weil dort die schwebende Tableiste
     steht (HANDOFF §13). Auf keinem der siebzehn Anmeldebildschirme steht
     sie — der Entwurf setzt den Aktionsblock auf `padding-bottom:30px`, und
     die 90 px waeren hier reine Luft unter dem Hauptknopf, also genau das,
     was Designspec Kap. 10.3 Punkt 3 verbietet. */
  --anmelde-fuss: 30px;
  /* Der Laufring von `06c` (Entwurf: 96 px, Strich 3 px) und die Dauer einer
     Umdrehung. */
  --anlage-ring: 96px;
  --anlage-ring-strich: 3px;
  --anlage-ring-dauer: 1.1s;
  /* Der kleine Kreisel in der Meldung von `00g` und im Knopf von `00e`
     (Entwurf: 16 bzw. 18 px, Strich 2,5 px). */
  --kreisel-mass: 16px;
  --kreisel-strich: 2.5px;
  /* Die Warnscheibe von `06d` (Entwurf: 64 px, Rand 2 px, Glyphe 28 px). */
  --warnscheibe-mass: 64px;
  --warnscheibe-rand: 2px;
  --warnscheibe-zeichen: 28px;
  /* Der Angabenkasten von `06d` (Entwurf: `border-radius:20px`,
     `padding:16px 18px`, Zeilen 13,5 px). */
  --anlage-angaben-radius: 20px;
  --anlage-angaben-schrift: var(--schrift-hinweis);
  /* Eine Schrittzeile von `06e` (Entwurf: `min-height:44px`, Zeichen 20 px). */
  --anlage-schritt-hoehe: 44px;
  --anlage-schritt-zeichen: 20px;
  --sucher-winkel: 30px;
  --sucher-winkel-strich: 3px;
  /* Innenabstand der vier Eckwinkel und die Rundung ihrer Aussenecke —
     Artboard 07 setzt beide (16 px, 8 px). Vorher hingen sie am allgemeinen
     Polster des Rahmens, das es hier gar nicht mehr gibt. */
  --sucher-winkel-abstand: 16px;
  --sucher-winkel-rundung: 8px;
  --sucher-farbe: var(--color-accent-200);
  /* DER SUCHER HAT WIEDER EIN FESTES MASS — UND ZWAR AUS DEM ENTWURF (WI-0110).
     HANDOFF §6 Zeile 07: `height: 236px; margin-top: 56px; border-radius: 24px`.
     Die Auflage aus WI-0049 („nimm die freie Hoehe") ist am 30.08. ZURUECKGEZOGEN
     (Designspec Kap. 10.1, Produktspec 4.2), und der Grund ist nicht Platz,
     sondern Zweck:

       Bildflaeche der Karte   ~277 x 150 px   (~1,85 : 1, quer)
       Sucher im Entwurf        355 x 236 px   (~1,50 : 1, quer)
       Sucher bis WI-0110       358 x 639 px   (~0,56 : 1, hoch)

     Ein Auto ist ein BREITES Objekt. Durch ein hochkantes Fenster bekommt man
     es nur ganz ins Bild, wenn man weit zurueckgeht — dann ist es klein — oder
     man schneidet es an. Danach schneidet die Karte auf ihre quere Bildflaeche
     zu, und der groesste Teil des gerahmten Bildes faellt weg. Der gedrungene
     Kasten hat die Form des Gegenstands UND die Form des Platzes, in dem er
     landet.

     WI-0315: HIER STAND 340/28 — DAS WAR DER STAND VOR DEM 02.09.2026.
     WI-0110 hat gegen das damalige Brett gebaut und richtig gebaut. Die Runde
     vom 02.09. hat den Rahmen danach auf 236 px gesenkt und den Abstand auf
     56 px gehoben (HANDOFF §17, Zeile `07-scan-viewfinder` GEOMETRY; §6
     Zeile 07 fuehrt seitdem beide Zahlen). Diese Senkung ist in der App nie
     angekommen: gemessen 340 px gegen 236 px des Bretts, Verhaeltnis 1,03
     statt 1,50. Der Grund aus der Praxis steht im Brett daneben — ein 340er
     Fenster fasst ZWEI Autos, und dann landet das falsche im Bild.

     WARUM DAS MESSGERAET DAS NIE GEMELDET HAT: die elf Merkmale des
     Merkmalsvergleichs (WI-0092, tests/e2e/hilfe/merkmale.js) kennen Farben,
     Schrift, Seitenraender, Inhaltsanfang und Fussfreiraum — die HOEHE EINES
     ELEMENTS kommt darin nicht vor. Der Bildschirm hat 10 von 11 Merkmalen
     erfuellt, waehrend der Rahmen 104 px zu hoch stand. Deshalb traegt
     tests/design.test.js die Geometrie jetzt als eigene Zusicherung.

     Die Kopplung von Sucher und Aufnahme bleibt davon unberuehrt: die Aufnahme
     misst den Kasten zur Laufzeit (coverAusschnitt() in camera.js). Wer die
     Hoehe hier aendert, aendert damit auch den Ausschnitt der Karte — das ist
     Absicht und der ganze Sinn des Masses. Nachgerechnet in
     tests/camera.test.js („WI-0315"). */
  --sucher-hoehe: 236px;
  /* WI-0341: 56 -> 40px. Der Export `design-update-12-102026zoom` zeichnet
     `07` neu und zieht den Rahmen 16 px hoch, um darunter Platz fuer den
     Zoom-Regler zu machen — Brett `07`, Rahmenkasten `margin-top:40px`, und
     derselbe Satz im Patch (§24.9 Punkt 4: „Frame on `07` moves up 16 px
     (margin-top 56 -> 40)"). Die 16 px und der Regler sind EIN Vorgang; wer
     eines ohne das andere bewegt, bekommt eine Luecke, die nichts fuellt. */
  /* WI-0426: 40 -> 12px. Ueber dem Rahmen steht jetzt die Zaehlerzeile
     (Artboards 07/07b/07n: `margin-top:16px; min-height:28px`), und der Rahmen
     sitzt 12 px unter ihr. Die 16 px Rahmenhub aus WI-0341 bleiben im Brett
     erhalten: 16 + 28 + 12 = 56, das alte Mass vor dem Zoom-Regler. */
  --sucher-abstand-oben: 12px;
  /* 07b ZEICHNET DENSELBEN RAHMEN NAEHER AN DEN STREIFEN (Artboard 07b:
     `margin-top:20px`). Oben steht auf `07` die Hinweispille allein, auf `07b`
     zusaetzlich der Reihenstreifen — der Rahmen rutscht dafuer hoch. Ein
     gemeinsames Mass hiesse, einen der beiden Bildschirme ungemessen zu
     verschieben. */
  /* WI-0426: 20 -> 12px. Mit der Zaehlerzeile zeichnet auch `07b` den Rahmen
     12 px unter ihr; beide Masse sind seither gleich, bleiben aber zwei
     Namen, weil sie zwei Bretter messen. */
  --sucher-abstand-oben-reihe: 12px;
  --sucher-rundung: 24px;
  /* DIE FLAECHE DES RAHMENS IST EINE EIGENE UND NICHT DIE FOTOFLAECHE DER
     KARTE (WI-0315).
     Artboards `07` und `07b` malen den Rahmen
     `linear-gradient(160deg,#23262c 0%,#1a1c21 60%,#15171b 100%)` — und zwar
     NUR diese beiden; im ganzen Brett kommen die drei Stufen an keiner
     anderen Stelle vor. Die Fotoflaeche der Karte ist etwas anderes:
     `--cs-surface-photo` ist `linear-gradient(155deg,#2f3339,#1e2126)`
     (HANDOFF §12, Zeile 1149) und traegt die Kartenbilder.
     Bis WI-0315 hing der Sucher an der Kartenflaeche. Gemessen hat der
     Merkmalsvergleich das als EINE fehlende Flaechenfarbe (`#15171b` kam in
     der App nicht vor) — das war die einzige Abweichung, die das Messgeraet
     auf diesem Bildschirm je gemeldet hat. */
  --sucher-flaeche: linear-gradient(160deg, #23262c 0%, #1a1c21 60%, #15171b 100%);
  /* Der Abstand der Hinweispille zum Rahmen darunter (Artboard 07: 14 px).
     Zusammen mit --sucher-abstand-oben sind das die 70 px des Entwurfs (bis
     WI-0315 waren es 28 und damit 42). */
  --pille-abstand-unten: 14px;
  /* DER RAND DER HINWEISPILLE (WI-0315, Artboard 07:
     `border:1px solid rgba(255,225,208,.3)`).
     Gemischt statt danebengeschrieben, damit die Quelle der Farbe die eine
     bleibt (HANDOFF §7 Punkt 12: kein Bauteil denkt sich einen eigenen Ton
     aus) — dieselbe Disziplin wie bei --einstieg-feld-rand. Der Ton ist
     --color-accent-200, derselbe wie an den vier Eckwinkeln und an der
     Schrift der Pille. */
  --pille-strich: 1px;
  --pille-rand: color-mix(in srgb, var(--color-accent-200) 30%, transparent);
  /* Die Einpasshilfe: eine Silhouette aus Kap. 6, mittig im Sucher, nur
     Kontur, neutral (#cfc3ab) und stark gedaempft — sie zeigt, wo das Auto
     sitzen soll, und darf sich nie vor einen Hinweistext draengen.

     WI-0054: vorher 62 % der Sucherbreite. Eine Hilfslinie ist eine ANWEISUNG
     — wer sein Auto hineinbekommen will, tritt so weit zurueck, bis es dort
     hineinpasst. Bei 62 % verlangte sie rund die Haelfte mehr Abstand, als
     der Sucher ueberhaupt zeigen musste; zusammen mit dem beschnittenen
     Querformat-Strom war das der Grund fuer „zehn Meter zurueck". Sie fuellt
     jetzt fast die volle Breite: ein Auto aus Gehsteig-Abstand steht damit
     genau so im Rahmen, wie die Hilfe es zeigt. Weniger als 100 %, damit sie
     Hilfe bleibt und nicht Rand wird.

     WI-0110: Die Breite bleibt. Sie ist die EINPASSHILFE fuer den Kartenschnitt
     — wer sein Auto hineinlegt, bekommt ein Bild, das auf die Karte passt —,
     und eine schmalere Hilfe verlangte wieder mehr Abstand, als der Sucher
     zeigen muss. Nachgerechnet wird das in tests/camera.test.js („WI-0110").
     Die Deckkraft geht auf die .24 des Entwurfs. */
  --einpass-breite: 86%;
  --einpass-deckkraft: 0.24;
  /* 76px wie im Entwurf (Artboard 07, HANDOFF §6 Zeile 07). Bis WI-0110 stand
     hier 60px, weil der Knopf unten RECHTS im Rahmen sass und dort mit dem
     Daumen erreichbar sein musste (WI-0037). Der Entwurf verankert ihn unten
     und mittig; faellt die Erreichbarkeit erneut auf, ist das ein Befund und
     ein eigenes Item — keine stille Rueckkehr zur alten Loesung. */
  --ausloeser: 76px;
  --ausloeser-rand: 4px;
  /* --- DER SCAN-ZAEHLER UND SEINE AUSLOESER (WI-0426) ---
     Jede Zahl steht in den Brettern 07n/07c/07d/07g/07o/07w (hochkant) und
     07l/07ld (quer). */
  --zaehler-fuge: 10px;
  --zaehler-abstand-oben: 16px;
  --zaehler-hoehe: 28px;
  --zaehler-hoehe-quer: 40px;
  --zaehler-rechts-quer: 20px;
  --zaehler-schrift: 12.5px;
  --zaehler-leiste-b: 96px;
  --zaehler-leiste-b-quer: 64px;
  --zaehler-leiste-h: 4px;
  --zaehler-spur: color-mix(in srgb, var(--cs-text) 12%, transparent);
  --zaehler-platzhalter-b: 30px;
  --zaehler-platzhalter-h: 8px;
  --zaehler-platzhalter: color-mix(in srgb, var(--cs-text) 16%, transparent);
  --zaehler-rollen: 320ms;
  --ausloeser-plus: 30px;
  --ausloeser-ruht-flaeche: color-mix(in srgb, var(--cs-text) 12%, transparent);
  --ausloeser-ruht-rand: color-mix(in srgb, var(--cs-text) 25%, transparent);
  --ausloeser-kreisel: 18px;
  --ausloeser-kreisel-dauer: 0.7s;
  --ausloeser-satz-fuge: 10px;
  --ausloeser-satz-breite: 250px;
  --ausloeser-satz-zeile: 1.45;
  /* #e6dcc8 im Brett (07w, 43s) — zwischen `--cs-text` und `--cs-text-2`,
     ohne eigenes Token in §11. */
  --text-hell: color-mix(in srgb, var(--cs-text) 85%, var(--cs-text-2));
  /* --- 43s / 43t, die Kontoseite Scans (WI-0426) --- */
  --konto-scans-titel: 30px;
  --konto-scans-titel-unten: 14px;
  --konto-scans-zahl: 64px;
  --konto-scans-wort: 16px;
  --konto-scans-fuge: 12px;
  --konto-scans-kasten-polster: 22px 22px 20px;
  --konto-scans-kasten-unten: 16px;
  --konto-scans-kasten-flaeche: color-mix(in srgb, var(--color-accent) 10%, transparent);
  --konto-scans-kasten-rand: color-mix(in srgb, var(--color-accent) 40%, transparent);
  --konto-scans-strich: 1.5px;
  --konto-scans-regel: 14.5px;
  --konto-scans-regel-zeile: 1.55;
  --konto-scans-regel-unten: 22px;
  --konto-scans-abschnitt-unten: 10px;
  --konto-scans-abschnitt-laufweite: 0.08em;
  --konto-scans-anderswo-polster: 18px;
  --konto-scans-anderswo-rundung: 24px;
  /* --- DAS KAUFBLATT 50–50g UND DER KASTEN AUF 43s (WI-0427) ---
     Werte aus dem Brett „2c · Freie Scans und Pakete". Einen Farbvertrag fuer
     diese Bretter gibt es nicht (L-10) — die Farben sind deshalb aus den
     §11-Tokens gemischt, deren Wert das Brett traegt. */
  --kaufblatt-rand-aussen: 20px;
  --kaufblatt-unten: 26px;
  --kaufblatt-rundung: 32px;
  --kaufblatt-polster: 26px;
  --kaufblatt-titel: 25px;
  --kaufblatt-text: 14.5px;
  --kaufblatt-zeile: 1.55;
  --kaufblatt-fuge: 14px;
  --kaufblatt-fakt-fuge: 10px;
  --kaufblatt-haken: 20px;
  --kaufblatt-zeichen: 56px;
  --kaufblatt-zeichen-ikone: 26px;
  --kaufblatt-plus: 44px;
  --kaufblatt-kasten-rundung: 18px;
  --kaufblatt-kasten-polster: 14px 16px;
  --kaufblatt-kasten-schrift: 14px;
  --kaufblatt-laeuft-flaeche: color-mix(in srgb, var(--color-accent) 35%, transparent);
  --kaufblatt-gut-flaeche: color-mix(in srgb, var(--cs-good) 16%, transparent);
  --kaufblatt-gut-rand: color-mix(in srgb, var(--cs-good) 55%, transparent);
  --kaufblatt-akzent-flaeche: color-mix(in srgb, var(--color-accent) 12%, transparent);
  --kaufblatt-akzent-rand: color-mix(in srgb, var(--color-accent) 45%, transparent);
  --kaufblatt-ruhig-flaeche: color-mix(in srgb, var(--cs-text) 8%, transparent);
  --kaufblatt-ruhig-rand: color-mix(in srgb, var(--cs-text) 30%, transparent);
  --kaufblatt-fehler-flaeche: color-mix(in srgb, var(--cs-warn) 12%, transparent);
  --kaufblatt-fehler-rand: color-mix(in srgb, var(--cs-warn) 40%, transparent);
  --kaufblatt-aus-flaeche: color-mix(in srgb, var(--cs-text) 6%, transparent);
  --kaufblatt-aus-rand: color-mix(in srgb, var(--cs-text) 18%, transparent);
  --kaufblatt-quer-breite: 420px;
  --konto-scans-paket-flaeche: color-mix(in srgb, var(--cs-text) 5%, transparent);
  --konto-scans-paket-titel: 15px;
  --konto-scans-paket-text: 13px;
  --konto-scans-paket-zeile: 1.5;
  --konto-scans-paket-fuge: 4px;
  --konto-scans-paket-vor-knopf: 16px;
  /* --- DER ZOOM-REGLER AUF `07` UND `07l` (WI-0341) ---
     Von WI-0216 gebaut, von WI-0328 ausgebaut, am 12.10.2026 von Rob
     zurueckgeholt: der Export vom 12.10.2026 zeichnet den Regler, und damit
     ist der Grund weg, mit dem WI-0328 entschieden hatte („das Brett zeichnet
     ihn nicht").

     JEDE ZAHL HIER STEHT IM BRETT, und das ist der Unterschied zu WI-0216:
     damals waren die Masse ausdruecklich provisorisch, weil es kein Artboard
     gab. Jetzt gibt es zwei — `07-scan-viewfinder` und
     `07l-scan-viewfinder-landscape` —, und sie zeichnen den Regler in beiden
     Lagen mit denselben Bauteilen und denselben Farben. Gegengelesen gegen
     `design/handoffs/ux-2026-10-12/HANDOFF-PATCH.md` Zeile 136 (§24.9
     Punkt 4); wo Patch und Brett auseinanderliegen, gilt das Brett (die
     Beschriftung quer: Brett 12 px, Patch nennt nur die 12,5 px des
     Hochformats).

     Die 44 ist dabei KEIN Entwurfszufall, sondern dieselbe Ein-Daumen-Regel
     wie an Filterzeile, Kontoscheibe und Tableiste (Produktspec 4.0,
     Designspec Kap. 10.3 Punkt 1) — das Brett zeichnet sie als Griffreihe
     hochkant und als 44-px-Spalte quer. */
  /* Die Trefferflaeche des Griffs — in BEIDE Richtungen (Brett `07`:
     `height:44px`, Brett `07l`: `width:44px`). */
  --scan-zoom-flaeche: 44px;
  /* Die Spur (Brett: `height:6px` bzw. `width:6px`). */
  --scan-zoom-spur: 6px;
  /* Der Griff und sein heller Ring (Brett: 28 px, `border:3px solid`). */
  --scan-zoom-griff: 28px;
  --scan-zoom-ring: 3px;
  /* Der Streifen hochkant: `padding:8px 2px 0`, Fuge zur Beschriftung 2 px. */
  --scan-zoom-polster: 8px 2px 0;
  --scan-zoom-luecke: 2px;
  /* Die Beschriftung: 12,5 px hochkant, 12 px quer — zwei Zahlen, weil das
     Brett zwei zeichnet. */
  --scan-zoom-schrift: 12.5px;
  /* Der Schatten unter dem Griff (Brett: `0 2px 8px rgba(0,0,0,.4)`). Er
     steht HIER und nicht im Bauteil, wie jedes andere Mass dieser Seite;
     §11 fuehrt ihn nicht, also wird er auch nicht als `--cs-*` erfunden. */
  --scan-zoom-schatten: 0 2px 8px rgba(0, 0, 0, 0.4);
  /* Die drei Farben kommen aus dem Vertrag und nicht aus dem Bauteil:
     Spur `--cs-line-2` ist wertgleich dem gezeichneten
     `rgba(245,234,216,.14)`, der gefuellte Teil und der Ring werden aus
     `--color-accent` bzw. `--cs-on-accent` gemischt statt danebengeschrieben
     (dieselbe Disziplin wie bei --pille-rand und --details-rand). */
  --scan-zoom-gefuellt: color-mix(in srgb, var(--color-accent) 55%, transparent);
  --scan-zoom-griff-ring: color-mix(in srgb, var(--cs-on-accent) 90%, transparent);
  --kz-rahmen-strich: 2px;
  --kz-bild-radius: var(--radius-md);
  --icon-winzig: 12px;
  --icon-klein: 16px;
  /* Der Papierkorb auf der Karte (WI-0070, Artboard 14): 17 px Glyph in einem
     36-px-Kreis, unten rechts. Der Kreis traegt eine eigene, dunkle Flaeche —
     er liegt auf dem Kartenfoto und muesste sich sonst gegen jedes Bild
     durchsetzen. */
  --icon-loeschen: 17px;
  --loeschknopf-groesse: 36px;
  --loeschknopf-flaeche: rgba(24, 26, 31, 0.85);
  --icon-mittel: 22px;
  --icon-gross: 24px;
  /* Die Meldung unter dem Freundescode-Feld (WI-0071, Artboard 23): 18 px
     Symbol, 2,75 Strichstaerke, 2 px tiefer als die erste Textzeile. Die drei
     Werte stehen so im Entwurf. */
  --icon-meldung: 18px;
  --strich-meldung: 2.75;
  --meldung-zeichen-versatz: 2px;
  --schritt-zeichen: 22px;
  /* --- Die Erkennungs-Buehne, Artboards 08/09/10 (WI-0068) ---
     Der Entwurf zeichnet dreimal denselben Aufbau: eine 250-px-Buehne, darin
     eine 206-px-Scheibe, darin entweder das gezeichnete Auto (164 px), die
     QR-Glyphe (96 px) oder — bei den beiden Fehlern — zusaetzlich das
     48-px-Warnabzeichen unten rechts. Die Zahlen stehen so in HANDOFF §6
     Zeilen 08 bis 10; der Handoff fuehrt sie nicht als Token, deshalb stehen
     sie hier und nicht in tokens.css. */
  --lauf-buehne: 250px;
  --lauf-scheibe: 206px;
  --lauf-spur: 164px;
  --lauf-glyphe: 96px;
  --lauf-warnzeichen: 48px;
  --lauf-strich: 2px;
  /* Ring, Scheibe und Lichtstrich in Terracotta-Abstufungen; die angehaltene
     Seite in der Warnfarbe. Alle vier sind Mischungen aus §11-Toenen — der
     Handoff fuehrt die Deckkraft-Stufen nicht einzeln. */
  --lauf-ring-farbe: color-mix(in srgb, var(--color-accent) 55%, transparent);
  --lauf-scheibe-flaeche: color-mix(in srgb, var(--color-accent) 10%, transparent);
  --lauf-scheibe-rand: color-mix(in srgb, var(--color-accent) 30%, transparent);
  --lauf-halt-flaeche: color-mix(in srgb, var(--warn-icon) 7%, transparent);
  --lauf-halt-rand: color-mix(in srgb, var(--warn-icon) 45%, transparent);
  --lauf-strich-verlauf: linear-gradient(
    90deg,
    transparent,
    var(--color-accent-300),
    transparent
  );
  --lauf-strich-schein: 0 0 14px var(--color-accent-300);
  --lauf-ring-dauer: 2.4s;
  --lauf-trace-dauer: 2.2s;
  --lauf-sweep-dauer: 1.9s;
  --lauf-punkte-dauer: 1.4s;
  --lauf-spur-strich: 480;
  --lauf-still-farbe: var(--cs-text-off);
  /* --- Der vierte Schritt, Artboard 08b (WI-0121) ---
     Der Entwurf zeichnet die Buehne hier KLEINER und in Sage statt Terracotta:
     196 px Buehne, 160 px Scheibe, 112 px Umriss, 62 px Lupe. Die Zahlen
     stehen so in HANDOFF §6 Zeile 08b und im Artboard; der Handoff fuehrt sie
     nicht als Token, deshalb stehen sie hier wie ihre Geschwister darueber.

     DIE FARBEN KOMMEN AUS §11, NICHT AUS DEM HTML DES ENTWURFS: die Ringe aus
     --color-accent-2 (#7a8a5e, die Zweitfarbe — der Entwurf schreibt
     rgba(122,138,94,…), also genau diesen Ton), Scheibenrand und Abzeichen aus
     --cs-good, Umriss und Lupe aus --cs-good-soft. §7 Punkt 12 verbietet einem
     Bauteil, sich einen eigenen Ton auszudenken. */
  --lauf-neu-buehne: 196px;
  --lauf-neu-scheibe: 160px;
  --lauf-neu-spur: 112px;
  --lauf-lupe: 62px;
  --lauf-neu-ring-1: color-mix(in srgb, var(--color-accent-2) 50%, transparent);
  --lauf-neu-ring-2: color-mix(in srgb, var(--color-accent-2) 35%, transparent);
  --lauf-neu-flaeche: color-mix(in srgb, var(--color-accent-2) 13%, transparent);
  --lauf-neu-rand: color-mix(in srgb, var(--cs-good) 32%, transparent);
  --lauf-neu-spur-farbe: color-mix(in srgb, var(--cs-good-soft) 70%, transparent);
  --lauf-neu-ring-dauer: 2.6s;
  --lauf-look-dauer: 3.2s;
  /* --- DIE REIHE, Artboards 07b/08c/08d/09b (WI-0211) ---
     HANDOFF §5.5b2 beschreibt den Streifen als das EINE neue Bauteil dieser
     Strecke und gibt seine Masse woertlich an: „three 58 x 44px slots, radius
     12, at `padding: 12px 20px 0`, with a 12px explanatory line to their
     right". Die Zahlen stehen deshalb hier und nicht in tokens.css — der
     Handoff fuehrt sie nicht als Token.

     DIE FARBEN SIND ABLEITUNGEN AUS §11 und keine abgeschriebenen Werte: der
     laufende Platz aus --color-accent, der wartende aus der Haarlinien-Leiter,
     der gescheiterte aus --warn-icon, der freie aus --cs-line-3. §7 Punkt 12
     verbietet einem Bauteil, sich einen eigenen Ton auszudenken. */
  --reihe-platz-b: 58px;
  --reihe-platz-h: 44px;
  --reihe-platz-radius: 12px;
  --reihe-luecke: 8px;
  /* 12 px unter der Oberkante — der Entwurf setzt den Streifen auf
     `padding: 12px 20px 0`. Der seitliche Abstand kommt von der Buehne
     (--buehne-seite bzw. --space-6); er steht hier nicht ein zweites Mal. */
  --reihe-oben: 12px;
  /* Und 20 px von den Seiten. Die Buehne der Scanstrecke traegt 22 bzw. 26 px
     (--buehne-seite / --space-6); der Streifen holt die Differenz als
     negativen Aussenabstand zurueck, statt die Spalte darunter zu verschieben
     — der Entwurf setzt NUR ihn auf 20 px. */
  --reihe-seite: 20px;
  /* Und 22 px ueber der Unterkante — dort verankern die drei Artboards ihren
     Aktionsblock. */
  --reihe-unten: 22px;
  --reihe-spur-b: 46px;
  --reihe-spur-h: 18px;
  --reihe-nummer: 9.5px;
  --reihe-zeichen: 18px;
  --reihe-zeichen-frei: 16px;
  --reihe-laeuft-rand: 2px;
  --reihe-rand: 1.5px;
  --reihe-wartet-rand: var(--cs-line-3);
  --reihe-frei-rand: var(--cs-line-3);
  --reihe-fehler-flaeche: color-mix(in srgb, var(--warn-icon) 12%, transparent);
  --reihe-fehler-rand: color-mix(in srgb, var(--warn-icon) 50%, transparent);
  --reihe-wartet-deckkraft: 0.6;
  /* Die Zusage von 08d und der Ratkasten von 09b: 22 px Radius, 16/18 Polster.
     Der gute Ton fuer „kein Foto geht verloren", der ruhige fuer den Rat. */
  --reihe-kasten-radius: 22px;
  --reihe-kasten-polster: var(--space-4) 18px;
  --reihe-zusage-flaeche: var(--cs-good-tint);
  --reihe-zusage-rand: color-mix(in srgb, var(--gruen-icon) 30%, transparent);
  /* Die durchgestrichene Kamera von 09b: 52-px-Glyphe in einem 130-px-Kreis. */
  --reihe-glyphe-kreis: 130px;
  --reihe-glyphe: 52px;
  --reihe-glyphe-rand: 2.5px;
  --reihe-glyphe-flaeche: color-mix(in srgb, var(--warn-icon) 8%, transparent);
  /* --- Querformat: der Fotografier-Weg (WI-0334, HANDOFF §24.7) ---

     JEDE ZAHL HIER IST EINE ZAHL AUS DEN VIER ARTBOARDS `07l`, `08l`, `09l`
     und `13l` im Brett (`design/Carspotter App.dc.html`, Abschnitt
     „2b · Finden quer", gezeichnet auf 793 x 393). Sie gelten AUSSCHLIESSLICH
     dort — die Regeln dazu haengen an `[data-ausrichtung='quer']`, ganz unten
     in dieser Datei, und `zeichne()` setzt das Attribut nur fuer diese vier
     Zustaende. */
  /* Die Schutzzone an der Kamerakante und der Innenabstand dahinter: der
     Rahmen von `07l` beginnt bei 58 px, die Schutzzone nimmt 48 davon. */
  --quer-schutz: 48px;
  --quer-rand-innen: 10px;
  /* Die Bedienspalte rechts unter dem Daumen (§24.7, „controls in a 128 px
     column on the right"). */
  --quer-spalte: 128px;
  /* DIE ZOOM-SPALTE (WI-0341, Brett `07l`): 48 px breit, LINKS neben der
     Bedienspalte bei `right:128px`, auf derselben Hoehe wie der Rahmen
     (`top:66px; bottom:50px`). Sie ist der Grund, warum Rahmen, Hinweispille
     und Warnzeile im neuen Brett bei `right:176px` stehen statt bei 128:
     176 = 128 + 48. Die Zahl steht deshalb EINMAL hier, und die drei
     Einrueckungen rechnen damit — eine abgeschriebene 176 waere eine zweite
     Wahrheit. Beschriftung quer 12 px (Brett; der Patch nennt nur die 12,5 px
     des Hochformats), Fuge zur Spur 4 px. */
  --quer-zoom-spalte: 48px;
  --quer-zoom-schrift: 12px;
  --quer-zoom-luecke: 4px;
  /* Die Einrueckung von Rahmen, Pille und Warnzeile an der rechten Kante. */
  --quer-rand-rechts: calc(var(--quer-spalte) + var(--quer-zoom-spalte));
  /* Der Rahmen: `top:66px; bottom:50px`. */
  --quer-sucher-oben: 66px;
  --quer-sucher-unten: 50px;
  --quer-pille-oben: 16px;
  --quer-warnung-unten: 12px;
  /* Das Kreuz oben links: 44 x 44 bei `top:12px`, 18-px-Glyphe. */
  --quer-kreuz: 44px;
  --quer-kreuz-oben: 12px;
  --quer-kreuz-ikone: 18px;
  /* Die drei Plaetze quer: 52 x 34, Radius 10, Fuge 6 — kleiner als die
     58 x 44 von `07b`, weil sie in die 128-px-Spalte muessen. */
  --quer-platz-b: 52px;
  --quer-platz-h: 34px;
  --quer-platz-radius: 10px;
  --quer-platz-luecke: 6px;
  /* Die Gruppe in der Spalte ist mittig: Plaetzeblock (3 x 34 + 2 x 6 = 114),
     Fuge 22, Ausloeser samt Rand (76 + 2 x 4 = 84). Der Versatz gegen die
     Gruppenmitte ist deshalb (22 + 84) / 2 = 53 nach oben und
     (22 + 114) / 2 = 68 nach unten. */
  --quer-reihe-versatz: 53px;
  --quer-ausloeser-versatz: 68px;
  /* 08l / 09l: Buehnenspalte 300 px ab 58 (die 250-px-Buehne mittig darin),
     Textspalte ab 378 bis 40 vor der rechten Kante. Die Fuge zwischen
     Buehnenspalte und Textspalte ist damit 378 - 58 - 300 = 20; der rechte
     Rand 40. WI-0366: die Fuge stand bis dahin als 70 (gemessen von der
     BUEHNE, nicht von ihrer Spalte) — richtig gerechnet nur, solange die
     Buehne am linken Spaltenrand klebte. */
  --quer-lauf-spalte: 300px;
  --quer-lauf-fuge: 20px;
  --quer-text-rand: 40px;
  /* Der Knopf auf 08l (`Abbrechen`) misst mindestens 200 px, der auf 09l
     (`Nochmal versuchen`) mindestens 220 — je Bildschirm sein Mass. */
  --quer-knopf-min: 200px;
  --quer-knopf-min-nochmal: 220px;
  /* 13l: die Karte sitzt `left:96px; top:56px`, die Textspalte `left:350px;
     right:44px`, der Knopfblock ist auf 300 px begrenzt. 96 - 48 Schutzzone
     = 48 Innenabstand; die Fuge zur Textspalte 350 - 96 - 198 = 56. */
  --quer-wurf-links: 48px;
  --quer-wurf-oben: 56px;
  --quer-wurf-fuge: 56px;
  --quer-wurf-rechts: 44px;
  --quer-wurf-knopf-max: 300px;
  --vorschlag-silhouette-b: 86px;
  --vorschlag-silhouette-h: 44px;
  --konfidenz-flaeche: var(--warn-flaeche);
  --konfidenz-text: var(--warn-icon);
  /* Der vorgewaehlte Vorschlag (Artboard 11): 2 px Terracotta statt 1,5 px
     Haarlinie, dazu die Akzent-Tinte als Flaeche. */
  --vorschlag-wahl-rand: 2px;
  --vorschlag-wahl-flaeche: var(--cs-accent-tint);
  /* `11c-laden` (WI-0176): fuenf Umrisse in der Hoehe einer Typzeile. Der
     Entwurf zeichnet sie mit 56 px. */
  --typzeile-skelett-hoehe: 56px;
  --garage-titel: 28px;
  --fortschritt-hoehe: 8px;
  --kachel-radius: 13px;
  --kachel-streifen: 9px;
  /* Das Fotoband der Garage-Kachel — das einzige ohne feste Breite: drei
     Spalten (--kachel-spalten) auf der Buehne, also
     (393 - 2 * --buehne-seite - 2 * --raster-luecke) / 3 ~ 110 px auf dem
     Bezugsgeraet, mithin rund 110 / 52 = 2,11. Auch dieses Band steht in
     `FOTOBAENDER` (public/js/filterchain.js): wer die Hoehe, die Spaltenzahl
     oder die Luecke aendert, aendert den Zuschnitt der Filterkette mit
     (WI-0125, Begruendung an --km-foto-h). */
  --kachel-foto: 52px;
  --kachel-spalten: 3;
  /* DIE KACHEL IST FLACH, NICHT DIE KARTE (WI-0112). Sie lief auf
     --karten-koerper, also auf --cs-surface-card — dem dreistufigen Verlauf
     des KARTENKOERPERS. HANDOFF §5.3 schreibt fuer die Kachel dagegen
     woertlich `background: #22242b`, und §11 fuehrt genau diesen Ton als
     eigenes Token: --cs-tile. Es war das einzige Flaechen-Token des Handoffs,
     das die App nirgends benutzte, waehrend an seiner Stelle ein anderes
     stand — richtige Quelle, falsche Zuordnung. Sichtbare Folge: jede Kachel
     brachte DREI Farben statt einer in den Bildschirm, und auf den
     Garagen-, Deckbau- und Partiebildschirmen verdraengten diese drei alles
     andere. */
  --kachel-flaeche: var(--cs-tile);

  /* --- DIE DICHTE DER GARAGE (WI-0098, HANDOFF §5.3/§12/§13) ---
     Auf derselben Hoehe zeigte der Entwurf neun Kacheln und sechs
     Gruppen-Chips, die App drei und zwei. Die Ursache war nirgends
     „weniger Inhalt", sondern durchweg groessere Schrift und mehr Luft: die
     Garage lief auf `--space-*` und `--schrift-fliess`/`--schrift-klein` des
     Designsystems, waehrend der Entwurf hier seine eigene, engere Leiter
     zeichnet. Die Werte darunter stehen so im Handoff — jeder mit seiner
     Zeile, damit niemand sie fuer gerundete Schaetzungen haelt. */
  --raster-luecke: 10px; /* §13 „Grid gap, garage" */
  --chips-luecke: 6px; /* §13 „Chip row gap" */
  --chip-schrift: 11px; /* §12 „Chip" (9–11,5 px) */
  /* --- WI-0313: DAS KLASSENRASTER DER GARAGE (Artboards 18/19/19b, §5.5b7)
     „All nine classes are shown, always … as a 3 × 3 grid of two-line cells,
     6px gap, inside the 349px content width — class name on the first line,
     the `n×` pill and `k/4` on the second."
     Die Zahlen sind am Artboard `19-garage-collection` GEMESSEN (drei Spalten
     zu 111,66 px, 6 px Luecke, Zellen 112x39, Radius 12, Polster 6/9) und
     stehen hier je mit ihrer Zeile, damit niemand sie fuer gerundete
     Schaetzungen haelt. Die Spaltenbreite steht NICHT dabei: sie ist
     `1fr` aus der Inhaltsbreite, und genau so bleibt die Reihe bei 349 px
     stehen, ohne dass eine zweite Breitenangabe daneben alt werden kann. */
  --chip-raster-spalten: 3;
  --chip-zelle-hoehe: 39px;
  --chip-zelle-radius: 12px;
  --chip-zelle-polster: 6px 9px;
  --chip-klasse-schrift: 10.5px;
  --chip-zaehler-schrift: 10px;
  /* DIE ZEILENHOEHEN SIND HIER KEIN SCHMUCK, SONDERN DIE BEDINGUNG. Die Zelle
     ist 39 px hoch, davon 12 px Polster — zwei Zeilen muessen in 27 px passen.
     Mit der Fliess-Zeilenhoehe (1,55) waeren es 32 px, und die beiden Zeilen
     ueberlappen sichtbar. Das Artboard zeichnet 1,2 und 1,15: 12,6 + 11,5 =
     24,1 px, und darunter bleibt Luft. Am Bild nachgesehen, nicht gerechnet
     geglaubt. */
  --chip-klasse-zeile: 1.2;
  --chip-zaehler-zeile: 1.15;
  --chip-zaehler-luecke: 4px;
  --chip-mal-polster: 0 5px;
  /* Die drei Behandlungen der SAMMLUNG. Salbei kommt aus dem Zustandston
     --cs-good (§11 „status"), NICHT aus --cs-r-uncommon: der traegt denselben
     Wert, gehoert aber ausschliesslich der Seltenheitstabelle (Designspec
     Kap. 9) — ein Quartettchip, der sich daraus bediente, waere beim naechsten
     Stufenton stillschweigend mitgewandert. Dieselbe Regel wie beim
     Erfolgskreis auf 45e weiter oben. */
  --chip-voll-flaeche: color-mix(in srgb, var(--cs-good) 14%, transparent);
  --chip-voll-rand: color-mix(in srgb, var(--cs-good) 35%, transparent);
  --chip-voll-name: var(--cs-good-soft);
  /* Der Zaehler der vollen Klasse zeichnet #a8b98d — eine halbe Stufe unter
     --cs-good-soft. §11 fuehrt den Ton nicht; gemischt wird deshalb aus der
     Salbeistufe gegen den Grund, nie ein Wert ohne Quelle. Gemeldete Luecke,
     dieselbe Bauart wie --schiene-stumm weiter unten. */
  --chip-voll-zahl: color-mix(in srgb, var(--cs-good-soft) 80%, var(--cs-bg-top));
  --chip-offen-flaeche: color-mix(in srgb, var(--cs-text) 6%, transparent);
  --chip-offen-rand: color-mix(in srgb, var(--cs-text) 18%, transparent);
  --chip-offen-name: var(--cs-text-2);
  --chip-offen-zahl: var(--cs-text-dim);
  /* Die leere Klasse: gestrichelt, durchsichtig, zweimal gedaempft. `0/4`
     zeichnet #5f594e — den fuehrt §11 als --cs-text-off. Der Klassenname
     darueber zeichnet #6f6659, und DEN fuehrt §11 nicht: er liegt zwischen
     der schwachen Stufe und dem Grund, also wird gemischt (72 % trifft den
     Wert). Gemeldete Luecke. */
  --chip-leer-rand: color-mix(in srgb, var(--cs-text) 20%, transparent);
  --chip-leer-name: color-mix(in srgb, var(--cs-text-dim) 72%, var(--cs-bg-top));
  --chip-leer-zahl: var(--cs-text-off);
  /* Die `n×`-Pille in der vollen Klasse. Die TINTE darin ist dieselbe Luecke
     wie am Doppelfund-Zaehler weiter oben: das Artboard zeichnet #1e2416, §11
     fuehrt den Ton nicht — genommen ist der dunkelste Grund des Handoffs. */
  --chip-mal-flaeche: color-mix(in srgb, var(--cs-good) 90%, transparent);
  --chip-mal-text: var(--cs-bg-bottom);
  /* --- WI-0313: DER SELTENHEITS-PUNKTSTREIFEN (§4.5c, §1506)
     „Dot: 20px circle, border: 2px solid <rarity>, no fill · Off: opacity .55
     · On: opacity 1, fill rgba(<rarity>, .22), dot grows to 24px · Row:
     min-height 44px — the strip is the hit target, not the single dot."
     Die fuenf Farben kommen aus der `--cs-r-*`-Tabelle und NUR von dort
     (Designspec Kap. 9); je Ring setzt das Markup keine Farbe, sondern das
     Stylesheet liest sie unten je `data-stufenring`. */
  --stufenringe-luecke: 9px;
  --stufenringe-zeile: 44px;
  --stufenring: 20px;
  --stufenring-an: 24px;
  --stufenring-rand: 2px;
  --stufenring-aus: 0.55;
  /* Im Deckbau dichter (HANDOFF §5.5d2, ux-2026-09-02 §6.1): 18-px-Ringe in
     8 px Abstand — die Zaehlerzeile traegt links noch beide Zahlen. */
  --stufenring-deckbau: 18px;
  --stufenringe-luecke-deckbau: 8px;
  --fortschrittszeile-luecke: 12px;
  /* --- WI-0313: DIE ZWEI FLAECHEN DER GARAGEN-KOPFZEILE
     Gemessen an `19-garage-collection`: die Filterpille traegt
     `rgba(198,113,57,.16)`, die Kontoscheibe `rgba(198,113,57,.22)`. Beide
     liefen bis hierher auf `--cs-accent-tint` (.14) — EIN Wert fuer zwei
     verschiedene gezeichnete Flaechen, und die Scheibe damit zwei Stufen zu
     blass. Gemischt wird aus `--color-accent`, nicht abgeschrieben: der Ton
     ist derselbe, nur die Deckkraft ist eine andere. */
  --garage-filter-flaeche: color-mix(in srgb, var(--color-accent) 16%, transparent);
  --kontoscheibe-flaeche: color-mix(in srgb, var(--color-accent) 22%, transparent);
  /* BEIDE Werte darueber gelten NUR fuer die Gruppenreihe der Garage
     (`.chips--gruppen`), nicht fuer jede Chipreihe der App. §12 fuehrt „Chip"
     zwar als Stufe des ganzen Systems, aber die Reihen auf Start, Deckbau und
     im Wunschkanal gehoeren anderen Tranchen — sie hier mitzuziehen hiesse,
     ihre Artboards ungemessen zu veraendern. Der Befund, dass die uebrigen
     Chipreihen mit 12 px ueber der Stufe liegen, steht im Bericht und gehoert
     dorthin, wo ihr Bildschirm gemessen wird. */
  /* DER GEFILTERTE KLASSENCHIP (Artboard 19b, §5.5b7 „Filtered on").
     2 px Akzentrand auf rgba(198,113,57,.18), die Fortschrittszahl in
     #e8a877 — der Entwurf schreibt alle drei Werte aus. Sie ueberschreiben
     die anderen drei Behandlungen des Chips, weil sie die ANSICHT beschreiben
     und nicht die Sammlung; nur die salbeifarbene Auskunft darin bleibt, denn
     die gehoert der Sammlung. */
  /* --- 20b und 20c: Markenwahl und Fundzeit (WI-0213) ---
     Die Zahlen stehen so im Entwurf; jede mit ihrer Zeile, damit niemand sie
     fuer gerundete Schaetzungen haelt. */
  --radio-punkt: 11px; /* §5.5b5 „filled dot in accent" */
  --pfeil-glyphe: 11px; /* Artboard 20: der Winkel an der Zeile */
  --lupe-glyphe: 16px; /* Artboard 20b: die Lupe im Suchfeld */
  --haarlinie: 1px; /* der Trennstrich unter „Alle Marken" / „Alle" */
  /* Der Titel von 20b und 20c: der Entwurf zeichnet ihn auf 26px, also eine
     halbe Stufe unter dem h2-Grad der Skala (32px). Er ist die Ueberschrift
     eines BLATTS, das aus einer Zeile aufgeht, nicht die eines Reiters — und
     der Merkmalsvergleich hat die fehlende Sprosse genau so gemeldet. */
  --wahlseite-titel: 26px;
  /* Der Fussabstand von 20b/20c. Sie tragen keine Tableiste; die 90px, die
     --buehne-unten fuer sie freihaelt, waeren hier verschenkte Listenzeilen.
     Der Entwurf setzt seine Spalte auf `padding:20px 22px 0` und laesst die
     Liste bis dicht an die Kante laufen. */
  --wahlseite-fuss: 24px;
  --schiene-breite: 16px; /* §5.5b4 „A 16px column on the right" */
  --schiene-schrift: 9.5px; /* §5.5b4 „9.5px/700 monospace" */
  --schiene-zeile: 1.5;
  /* §5.5b4 nennt fuer die Buchstaben OHNE Eintrag `#4e4840`. Diesen Ton
     fuehrt §11 nicht; er liegt zwischen der gedaempften und der schwachen
     Textstufe und ist dunkler als beide. Gemischt wird deshalb aus der
     schwachen Stufe gegen den Grund — ein Wert ohne Quelle stuende hier
     sonst als einziger da (Designspec Kap. 9: tokens only). */
  --schiene-stumm: color-mix(in srgb, var(--cs-text-dim) 55%, var(--cs-bg-top));
  --laufweite-buchstabe: 0.1em; /* §5.5b4 „letter heading … .1em" */
  /* Die einbreite Familie der Buchstabenkoepfe und der Schiene. §12 fuehrt sie
     nicht als Token — der Entwurf setzt an beiden Stellen `ui-monospace`, also
     die Systemschrift, damit A und W gleich viel Platz nehmen und die Reihe
     eine Spalte bildet. */
  --font-einbreit: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --stumpf-deckkraft: 0.5; /* eine Zeile ohne Ziel — sichtbar, aber stumm */
  --chip-gefiltert-rand: 2px;
  --chip-gefiltert-flaeche: color-mix(in srgb, var(--color-accent) 18%, transparent);
  /* Fuer `#e8a877` gilt dasselbe wie bei der eigenen Reaktion weiter unten:
     §11 fuehrt den Ton nicht, auf der Akzentrampe liegt er zwischen 300 und
     400 — genommen wird die Sprosse der Rampe, nie ein Wert ohne Quelle. */
  --chip-gefiltert-zahl: var(--color-accent-400);
  --garage-meta: 13px; /* §12 „Body small" — die Zaehlerzeile */
  --garage-filter-schrift: 13px; /* §12 „Body small" — die Filterpille */
  /* §5.3 „caption padding". Die Kurzform steht in zwei benannten Haelften,
     seit die Kachelhoehe aus ihr gerechnet wird (WI-0328): in einem `calc()`
     ist `7px 8px` kein Wert, und die 7 ein zweites Mal hinzuschreiben waere
     die zweite Wahrheit, die beim naechsten Entwurfsstand haengen bleibt. */
  --kachel-polster-y: 7px;
  --kachel-polster-x: 8px;
  --kachel-polster: var(--kachel-polster-y) var(--kachel-polster-x);
  --kachel-name: 11px; /* §5.3 „caption font-size" */
  --kachel-generation: 10px; /* §5.3 „second line" */
  --kachel-abzeichen: 9px; /* §5.2 „NEU" — EROBERT liegt mit 9,5 px daneben */
  /* --- DIE KACHEL IST SO HOCH WIE IM BRETT, UND ZWAR JEDE (WI-0328) ---
     Gemeldet war (laufende App, 10.10.2026): „Kacheltext zeigt den vollen
     Generationsnamen ueber bis zu vier Zeilen, dadurch unterschiedliche
     Kachelhoehen in einer Reihe". Der Grund liegt nicht in der Hoehe, sondern
     im Text: `19-garage-collection` zeichnet EINE Namenszeile und darunter
     EIN kurzes Kuerzel (`8V`, `MK7`, `E46`), und solange beide Zeilen
     umbrechen durften, war die Hoehe eine Folge des Inhalts. Im Katalog
     stehen 15 von 186 Generationscodes, die dafuer zu lang sind
     (`III (319) Facelift 2020`), und ueber das Modellwissen (Spec 6.2e) kann
     ein ganzer Satz hereinkommen.
     Die Beschriftung ist deshalb zweizeilig FESTGELEGT und die Hoehe daraus
     GERECHNET — nicht abgeschrieben: Streifen + Fotoband + zwei Zeilen in
     ihren Graden und dem Polster darum. Verschiebt sich eines dieser Masse,
     verschiebt sich die Kachel mit; eine Zahl hier wuerde stehenbleiben. */
  --kachel-beschriftung: calc(
    var(--kachel-polster-y) * 2 + (var(--kachel-name) + var(--kachel-generation)) *
      var(--zeilenhoehe-heading)
  );
  --kachel-hoehe: calc(
    var(--kachel-streifen) + var(--kachel-foto) + var(--kachel-beschriftung)
  );
  /* Der gestrichelte Rahmen der leeren Garage (Artboard 21): 200 x 110. */
  --leer-rahmen-b: 200px;
  --leer-rahmen-h: 110px;
  --leer-silhouette-b: 120px;
  --leer-silhouette-deckkraft: 0.5;
  /* Der Satz unter der Einladung liest sich enger als der Knopf breit ist —
     der Entwurf setzt ihn in ein 44 px eingeruecktes Feld. */
  --leer-textbreite: 261px;
  /* Das Zeichen des Freundes im Kopf von Artboard 40. */
  --freund-zeichen: 44px;
  /* Die Kontoscheibe in der Kopfzeile der Garage (Artboards 18/19/21).
     Der Entwurf zeichnet sie 38 px. Sie bleibt hier 44 — dieselbe Hoehe, die
     die Filterpille daneben schon hat, und die Trefferflaeche, die dieses
     Repo seit WI-0044 fuer jedes Bedienelement der Kopfzeile haelt
     (Designspec 10.3 Punkt 1). Eine BEWUSSTE Abweichung, und die einzige, die
     dieses Item einfuehrt: einen bestehenden Daumenknopf zu verkleinern, um
     ein Artboard zu treffen, waere die falsche Richtung. Was der Entwurf an
     dieser Stelle wirklich beanstandet hat, war die Wortpille, nicht die
     sechs Pixel. */
  --kontoscheibe: var(--btn-hoehe-ghost);
  /* DER KONTOBEREICH (Artboards 43/44/45, WI-0099). Vier Masse, alle aus dem
     Entwurf: das Zeichen im Kopf (52 px), die Zeilenhoehe einer Einstellung
     (56 px), die Zeilenhoehe der beiden Wege hinaus (48 px) und die Ikone
     davor (20 px). Sie stehen nicht auf der Abstandsleiter — es sind
     Trefferflaechen, und die kommen aus dem Entwurf und aus Designspec Kap.
     10.3 Punkt 1, nicht aus einer Rechnung. */
  --konto-zeichen: 52px;
  /* DIE GLYPHE IM MONOGRAMMKREIS DES KONTOKOPFS (HANDOFF §4.5b, Artboard 43).
     Sie stand auf --color-accent-400, also auf Terracotta — und Terracotta ist
     nach Designspec Kap. 9 den AKTIONEN vorbehalten, waehrend §4.5b fuer eine
     Identitaet ausdruecklich einen eigenen Satz Toene fuehrt („rarity colours
     and terracotta are both taken"). Der Entwurf zeichnet die Glyphe auf `43`
     in #c9c0a8, dem Sandton jener sechs — und Sand ist dort zugleich der
     Rueckfall fuer jede Anfangsbuchstabe ohne eigene Farbe. Genau dieser Fall
     liegt hier vor: die Farbwahl der sechs Toene ist noch nicht gebaut (der
     Avatar der App ist bis heute ein TIER, `avatar_fuchs` und die 30 anderen),
     und bis sie es ist, traegt der Kreis den gezeichneten Rueckfallton statt
     einer Aktionsfarbe. Scheibe und Rand bleiben, wie der Entwurf sie auf
     diesem Artboard zeichnet. */
  --konto-zeichen-glyphe: #c9c0a8;
  --konto-zeile: 56px;
  /* DIE WAHLZEILE AUF `43h` (WI-0357, HANDOFF §28, P-3): 60 px hoch — vier
     mehr als die Kontozeile, weil die Zeile `Automatisch` eine Unterzeile
     traegt und alle drei gleich hoch stehen. Der Punkt im Ring ist 10 px. */
  --sprachwahl-zeile: 60px;
  --sprachwahl-punkt: 10px;
  /* HIER STAND `--konto-wert-zeile: 30px` — die flachere Hoehe der beiden
     Auskunftszeilen „Spitzname" und „Farbe" (WI-0116). ENTFERNT MIT WI-0331
     (Befund 43-5) zusammen mit den Zeilen selbst: das Brett zeichnet an
     dieser Stelle die zweite Schalterzeile, nicht die beiden Angaben. Der
     Grund, aus dem das Mass einmal 30 und nicht 56 px war, ist damit
     erledigt — drei reine Auskunftszeilen in Knopfhoehe hatten den Bildschirm
     ueber die 793 px geschoben. Dieselbe Hoehe fuer die Zeile, die jetzt dort
     steht, waere falsch: sie IST eine Zeile des Bretts, in Zeilenhoehe. */
  --konto-ausgang: 48px;
  --konto-ikone: 20px;
  /* DER SCHALTER unter „Deine Daten" (Artboard 43, WI-0116): 46 x 27 px mit
     3 px Polster und einem 21 px runden Knopf darin — die Masse des Entwurfs.
     Sie stehen wie die vier darueber nicht auf der Abstandsleiter: es ist eine
     Trefferflaeche, keine Rechnung. */
  --konto-schalter-b: 46px;
  --konto-schalter-h: 27px;
  --konto-schalter-polster: 3px;
  --konto-schalter-knopf: 21px;
  /* Der Winkel am Ende der Loeschzeile (Artboard 43, WI-0164): 15 px, kleiner
     als die 20 px der Ikonen darueber — die Fusszeilen tragen keine Ikone,
     und ein gleich grosser Winkel machte aus der leisesten Zeile die
     lauteste. */
  --konto-winkel: 15px;
  /* Der Haken der Datenfreigabe-Zeile (Artboard 43, WI-0331): 18 px — kleiner
     als die 20 px der Zeilenzeichen links, groesser als der 15-px-Winkel im
     Fuss. Das Brett zeichnet genau diese Groesse, und sie steht wie die
     anderen hier nicht auf der Abstandsleiter: es ist eine gezeichnete Marke,
     keine Rechnung. */
  --konto-haken: 18px;
  /* Der Aufzaehlungspunkt vor einer Verlustzeile auf 45b (6 px). Er steht
     nicht auf der Abstandsleiter: es ist eine gezeichnete Marke, keine
     Rechnung — wie `--punkt` eine Zeile weiter unten. */
  --verlust-punkt: 6px;
  /* Der Farbpunkt vor einer Seltenheitszeile im Filterblatt (Artboard 20:
     11 px). Er ist das, was die fuenf Stufen dort unterscheidbar macht —
     dieselbe Farbe wie der Streifen der Kachel, aus derselben Quelle. */
  --punkt: 11px;
  /* Das Kaestchen des Filterblatts (Artboard 20): 22 px mit 7 px Rundung, in
     einer 44 px hohen Zeile — das ist die Trefferflaeche eines Daumens. */
  --filterblatt-kaestchen: 22px;
  --filterblatt-kaestchen-radius: 7px;
  --filterblatt-zeile: 44px;
  /* Der weiche Verlauf ueber dem stehenden Fussknopf des Filterblatts: er
     laesst die Zeile darunter auslaufen, statt sie hart abzuschneiden. */
  --filterblatt-fussschatten: 0 -12px 16px var(--blatt-flaeche);
  /* DIE BEREICHSSEITE 20w (WI-0424). Saeulen 56 px, Schiene 44 px (die
     Trefferflaeche), Spur 6 px, Griff 28 px mit 3 px Rand — Masse des Bretts.
     Die Toene: Saeulen im Bereich Terracotta zu 70 %, ausserhalb der Text zu
     14 %, der Griffrand die Kartenrueckkante. Das Brett hat fuer 20w keinen
     Farbvertrag (L-10); genommen sind die Nachbartokens. */
  --wertebereich-saeulen: 56px;
  --wertebereich-saeule-radius: 4px 4px 1px 1px;
  --wertebereich-saeule-an: color-mix(in srgb, var(--color-accent) 70%, transparent);
  --wertebereich-saeule-aus: color-mix(in srgb, var(--cs-text) 14%, transparent);
  --wertebereich-schiene: 44px;
  --wertebereich-spur: 6px;
  --wertebereich-griff: 28px;
  --wertebereich-griff-rand: 3px solid color-mix(in srgb, var(--cs-back-edge) 90%, transparent);
  --wertebereich-griff-schatten: 0 2px 8px rgba(0, 0, 0, .4);
  --wertebereich-feld-flaeche: color-mix(in srgb, var(--cs-text) 5%, transparent);
  --wertebereich-feld-radius: 20px;
  --wertebereich-feldwert: 18px;
  /* DAS STEHENDE KOPFBAND (Artboards 19s und 28s, WI-0424). Das Brett malt
     es auf #201c17 mit `0 8px 16px rgba(0,0,0,.35)`; fuer beides gibt es kein
     Token und keinen Farbvertrag (L-10). Genommen ist der obere Grund
     (--cs-bg-top, #221e18) — auf ihm beginnt der Bildschirm ohnehin, das Band
     hebt sich ruhend nicht ab — und der Schatten des Bretts als eigener
     Wert neben --cs-shadow-sheet. */
  --kopfband-flaeche: var(--cs-bg-top);
  --kopfband-schatten: 0 8px 16px rgba(0, 0, 0, .35);
  /* Der Verlauf ueber den stehenden Knoepfen von 28s: 34 px bis zum Grund. */
  --deckbau-fuss-verlauf: linear-gradient(180deg, transparent 0, var(--cs-bg-bottom) var(--space-8));
  /* DIE SECHS AVATARFARBEN — HANDOFF §4.5b, Artboard 01b (WI-0171).
     Sie stehen hier und nicht in tokens.css, weil §11 sie nicht fuehrt: der
     Handoff nennt sie in §4.5b als eigenen Satz, ausdruecklich NEBEN der
     Seltenheitsskala und neben Terracotta („rarity colours and terracotta are
     both taken, so the avatar hues are a separate set").
     Je Farbe drei Werte, weil §4.5b sie als Dreiklang schreibt: Toenung .16
     als Flaeche, Rand .5, Glyphe voll. Sie erscheinen AUSSCHLIESSLICH im
     Kreis — nie auf einem Knopf, Chip oder Kartenrahmen und nie anstelle
     einer Seltenheitsfarbe. */
  --avatar-tuerkis: #5fa39b;
  --avatar-tuerkis-ton: rgba(95, 163, 155, 0.16);
  --avatar-tuerkis-rand: rgba(95, 163, 155, 0.5);
  --avatar-tuerkis-schein: rgba(95, 163, 155, 0.35);
  --avatar-rose: #d97ea0;
  --avatar-rose-ton: rgba(217, 126, 160, 0.16);
  --avatar-rose-rand: rgba(217, 126, 160, 0.5);
  --avatar-rose-schein: rgba(217, 126, 160, 0.35);
  --avatar-kornblume: #7f9ede;
  --avatar-kornblume-ton: rgba(127, 158, 222, 0.16);
  --avatar-kornblume-rand: rgba(127, 158, 222, 0.5);
  --avatar-kornblume-schein: rgba(127, 158, 222, 0.35);
  --avatar-senf: #d9b24a;
  --avatar-senf-ton: rgba(217, 178, 74, 0.16);
  --avatar-senf-rand: rgba(217, 178, 74, 0.5);
  --avatar-senf-schein: rgba(217, 178, 74, 0.35);
  --avatar-flieder: #a98cd9;
  --avatar-flieder-ton: rgba(169, 140, 217, 0.16);
  --avatar-flieder-rand: rgba(169, 140, 217, 0.5);
  --avatar-flieder-schein: rgba(169, 140, 217, 0.35);
  --avatar-sand: #c9c0a8;
  --avatar-sand-ton: rgba(201, 192, 168, 0.16);
  --avatar-sand-rand: rgba(201, 192, 168, 0.5);
  --avatar-sand-schein: rgba(201, 192, 168, 0.35);

  /* Die Groessenleiter der Scheibe (HANDOFF §4.5b). Die Glyphe waechst mit
     ihr — deshalb steht sie je Stufe daneben und nicht einmal fuer alle. */
  --avatar-gross: 112px;
  --avatar-gross-glyphe: 46px;
  --avatar-wahl: 52px;
  --avatar-wahl-glyphe: 20px;
  --avatar-mittel: 62px;
  --avatar-mittel-glyphe: 26px;
  --avatar-kopf: 44px;
  --avatar-kopf-glyphe: 19px;
  /* Die Stufe „duel confirm, friend header" aus derselben Leiter (WI-0188).
     Sie stand bis hierher nicht als Token da, obwohl §4.5b sie fuehrt — der
     Bildschirm hatte an dieser Stelle noch den neutralen Monogrammkreis. */
  --avatar-bestaetigung: 48px;
  --avatar-bestaetigung-glyphe: 20px;
  /* 40 px mit 17 px Glyphe an der Gegnerzeile von 28a. DIESE STUFE FUEHRT
     §4.5b NICHT — die Leiter dort springt von 44 auf 34 —, Artboard 28a
     zeichnet sie aber ausdruecklich (`width:40px;height:40px;font-size:17px`).
     Gemeldet als Luecke; bis der Handoff die Stufe nennt, steht sie hier
     benannt statt als roher Wert im Bauteil. */
  --avatar-auftakt: 40px;
  --avatar-auftakt-glyphe: 17px;
  --avatar-reaktion: 30px;
  --avatar-reaktion-glyphe: 14px;
  --avatar-antwort: 24px;
  --avatar-antwort-glyphe: 12px;
  --avatar-rand: 1.5px;
  --avatar-rand-stark: 2.5px;

  /* --- DAS REAKTIONSBLATT (HANDOFF §5.5c, Familie `16r-*`, WI-0181) ---
     Wie bei der schwebenden Leiste darunter schreibt der Entwurf die
     Geometrie DIESES EINEN Bauteils in festen Pixeln vor und nicht auf der
     Abstandsleiter. Die Masse stehen deshalb hier als eigene Tokens: das
     Blatt ist EIN Bauteil mit EINER Geometrie, und wer sie aendert, aendert
     sie an dieser Stelle statt in einem Dutzend Regeln.

     DIE DREI HOEHEN SIND DER KERN. Sie sind fest, weil der Entwurf sie fest
     zeichnet: ein Blatt, das mit der Liste waechst, laesst beim Scrollen
     Zeilen unter den Knopf rutschen und springt, wenn die Liste ankommt. */
  --reaktionen-hoehe-liste: 430px;
  --reaktionen-hoehe-kurz: 310px;
  --reaktionen-hoehe-auswahl: 466px;
  --reaktionen-polster-oben: 14px;
  --reaktionen-polster-seite: 22px;
  --reaktionen-polster-unten: 26px;
  --reaktionen-radius: 32px;
  --reaktionen-schatten: 0 -18px 40px rgba(0, 0, 0, 0.55);
  /* Der Gradientenschleier: er hebt das Blatt ab, LOESCHT die Karte aber
     nicht — man soll weiterlesen koennen, worauf man antwortet. */
  --reaktionen-schleier-hoehe: 120px;
  --reaktionen-schleier: linear-gradient(180deg, rgba(19, 17, 16, 0), rgba(19, 17, 16, 0.82));
  /* Die Maske der rollenden Liste — oben 18 px, unten 14 px. Eine halb
     sichtbare Zeile liest sich damit als angeschnitten und nicht als kaputt. */
  --reaktionen-maske: linear-gradient(
    transparent,
    #000 18px,
    #000 calc(100% - 14px),
    transparent
  );
  --reaktionen-griff-breite: 36px;
  --reaktionen-griff-hoehe: 4px;
  --reaktionen-griff-treffer: 44px;
  --reaktionen-griff-versatz: 20px;
  --reaktionen-griff-abstand: 8px;
  --reaktionen-griff-farbe: var(--cs-line-4);
  /* Die Ueberschrift des Blatts steht auf 22 px — zwischen h4 (20) und h3
     (25) der Skala. §12 fuehrt die Stufe nicht; sie steht deshalb hier
     benannt statt als Zahl im Bauteil. */
  --reaktionen-titel: 22px;
  /* §5.5c schreibt die Grade dieser Zeile aus: Absendername 13,5px/700,
     Zeitangabe 11px, Satzpille 13,5px/700, `Antworten` 12,5px/700, die
     Zahlzeile 12,5px, der Name einer Antwort 12,5px, das Zeichen in der
     Pille 15px. Die Skala der App fuehrt 13,5 (`--schrift-hinweis`) und 11
     (`--schrift-abschnitt`); 12,5 ist die Caption-Stufe aus §12, die schon an
     mehreren Stellen als eigener Wert steht, und 15px fuehrt sie nirgends. */
  --reaktion-name: var(--schrift-hinweis);
  --reaktion-zeit: var(--schrift-abschnitt);
  --reaktion-satz: var(--schrift-hinweis);
  --reaktion-caption: 12.5px;
  --reaktion-emoji: 15px;
  --reaktion-pille-hoehe: 32px;
  /* Die Kopfzeile der Familie `16r-*` (WI-0330, 16r-2): `‹`-Scheibe,
     Modellname (15px/700), Sammelnummer (12,5px, leiser Ton). Die 15 fuehrt
     die Skala nirgends, die 12,5 ist dieselbe Caption-Stufe wie oben — sie
     wird deshalb nicht ein zweites Mal geschrieben. */
  --reaktionen-kopf-modell: var(--reaktion-emoji);
  /* Salbei fuer das, was jemand anderes gesagt hat. Flaeche und Text fuehrt
     §11 als --cs-good-tint / --cs-good-soft; den Rand nennt §5.5c mit .45 und
     §11 nicht — er wird deshalb aus derselben Farbe gemischt, nicht daneben
     geschrieben. Dieselbe Bauart wie --gruen-rand. */
  --reaktion-pille-flaeche: var(--cs-good-tint);
  --reaktion-pille-rand: color-mix(in srgb, var(--cs-good) 45%, transparent);
  --reaktion-pille-text: var(--cs-good-soft);
  /* Terrakotta fuer die EIGENE. Sie ist hier KEINE Aktionsfarbe, sondern eine
     Auskunft — „das hast du gesagt" —, und deshalb steht sie an der Pille und
     nicht an einem Knopf. Gemischt wird aus --color-accent: es ist wertgleich
     mit --cs-accent (#c67139), und §16 bindet es als die Quelle, die die App
     durchgaengig abruft. §11 fuehrt fuer die Flaeche --cs-accent-tint (.14),
     der Entwurf zeichnet hier .18. */
  --reaktion-eigen-flaeche: color-mix(in srgb, var(--color-accent) 18%, transparent);
  --reaktion-eigen-rand: color-mix(in srgb, var(--color-accent) 60%, transparent);
  /* §5.5c nennt fuer den Text `#e8a877`. Diesen Ton fuehrt §11 nicht; auf der
     Akzentrampe des Designsystems liegt er zwischen 300 (#ffc6a5) und 400
     (#f6a06b). Genommen wird die naechste Sprosse der Rampe statt eines
     Werts, den keine Quelle kennt (Designspec Kap. 9: tokens only). */
  --reaktion-eigen-text: var(--color-accent-400);
  --reaktion-antwort-einzug: 40px;
  --reaktion-antwort-linie: 1.5px solid var(--cs-line-2);
  --reaktion-aktion-versatz: -2px;
  --reaktion-skelett-hoehe: 64px;
  /* Der stumpfe Knopf: er ist NICHT nur abgeblendet, er traegt eine eigene
     Flaeche — sonst laese er sich als „gerade nicht getroffen" statt als
     „geht noch nicht". §11 fuehrt beide Werte. */
  --reaktion-stumpf-flaeche: var(--cs-fill-1);
  --reaktion-stumpf-text: var(--cs-text-dim);
  --btn-hoehe-treffer: 44px;
  --btn-wahl-rand: 2px;
  /* Die Altersstufenzeile auf Artboard 02 — 52 px, deutlich ueber den 44 px
     Mindesttrefferflaeche aus HANDOFF §4.5. */
  --anmeldung-zeile: 52px;
  /* DIE SCHWEBENDE PILLE — HANDOFF §4.3, Wert fuer Wert (WI-0093).
     Der Entwurf schreibt die Geometrie dieses einen Bauteils in festen
     Pixeln vor und nicht auf der Abstandsleiter (§13 fuehrt nur den
     Fussfreiraum). Deshalb stehen die Masse hier als eigene Tokens: die
     Leiste ist EIN Bauteil mit EINER Geometrie, und wer sie aendert, aendert
     sie an dieser Stelle statt in vier Regeln.

     Bis WI-0093 waren Polster und Schriftgrad von der Leiter abgeleitet
     (`--space-2`, `--schrift-klein`). Das ergab eine Leiste, die nirgends
     genau die Masse des Entwurfs traf — und mit dem vierten Eintrag
     „Wunsch" war sie breiter als die 393 px des Geraets und hing links und
     rechts hinaus. Die Eintraege sind seitdem drei (siehe app.js). */
  --tableiste-flaeche: rgba(35, 30, 24, 0.85);
  --tableiste-blur: blur(10px);
  --tableiste-unten: 16px;
  --tableiste-polster: 6px;
  --tableiste-luecke: 4px;
  --tableiste-randbreite: 1px;
  /* §4.3 nennt `rgba(245,234,216,.12)`. Auf der Haarlinien-Rampe des
     Handoffs (§11) liegt der Wert zwischen --cs-line-1 (.10) und
     --cs-line-2 (.14); genommen wird die naechste Stufe der Rampe statt
     eines Werts, den §11 nicht kennt (Designspec Kap. 9: Tokens only). */
  --tableiste-randfarbe: var(--cs-line-2);
  /* Der Eintrag: 44 px Mindesthoehe (§4.5 „Minimum hit target everywhere"),
     0/20 Polster, 14 px — §12, Zeile „Tab item". */
  --tableiste-knopf: 44px;
  --tableiste-knopf-polster: 20px;
  --tableiste-schrift: 14px;
  /* Die Leiste traegt ihre Hoehe als Token: die Kartenseite rechnet mit ihr
     ihren Fussfreiraum aus — statt zu schaetzen, wie hoch sie gerade ist.
     Der Rand zaehlt mit, sonst faellt die Rechnung um zwei Pixel zu knapp
     aus. */
  --tableiste-hoehe: calc(
    var(--tableiste-knopf) + var(--tableiste-polster) * 2 + var(--tableiste-randbreite) * 2
  );
  /* Der Freiraum am Fuss jeder Buehne. HANDOFF §13 verlangt „Bottom inset
     for the tab bar: >= 90px"; die Leiste selbst belegt 16 + 58 = 74 px,
     der Rest ist Luft zwischen Inhalt und Leiste. Seit WI-0096 sind es 90
     statt 96 px — die Untergrenze aus §13 —, weil auf 393 px jeder Pixel
     zaehlt, den ein Bildschirm sonst unter die Falz schiebt.

     WI-0323 (Befund G2) — DIE ZAHL IST ABGELEITET, NICHT ABGESCHRIEBEN.
     Bis hierher stand hier das Literal `90px`, und die Rechnung, die es
     ergibt, stand nur im Satz darueber. Das sind zwei Wahrheiten ueber
     DASSELBE Mass: wer die Leiste um einen Pixel aendert, aendert den
     Freiraum nicht mit, und der Inhalt laeuft ihr unter — genau der Befund,
     der gemeldet wurde. Die Leiste schwebt `--tableiste-unten` ueber der
     Kante, ist `--tableiste-hoehe` hoch, und darueber gehoert derselbe
     Spalt noch einmal als Luft (der Bericht nennt „tab-bar height + 16 px",
     und 16 px IST `--tableiste-unten`). Macht 16 + 58 + 16 = 90 px, also
     exakt die Untergrenze aus §13 — die Zahl bewegt sich nicht, nur ihre
     Herkunft. Dieselbe Bauart wie `--karte-fuss` weiter oben, das seinen
     Fussfreiraum schon so rechnet; zwei Rechenweisen fuer denselben
     Freiraum waeren eine zuviel.

     SIE GILT UEBER DEN GEMEINSAMEN TRAEGER. Angeschoben wird nichts je
     Bildschirm: `.app__buehne` traegt sie als `padding-bottom`, und das
     ist der Kasten, in dem JEDER rollende Bildschirm seinen Inhalt hat. */
  --buehne-unten: calc(var(--tableiste-unten) * 2 + var(--tableiste-hoehe));
  /* SEITLICH: HANDOFF §4.2, Zeile „Tab screen" — `padding: 20–22px 22px 0`.
     Bis WI-0096 stand hier die Abstandsleiter (--space-4, also 18 px), und
     der Merkmalsvergleich meldete den Seitenrand auf JEDEM zugeordneten
     Bildschirm als zu schmal: der Entwurf zeichnet die Inhaltsspalte bei
     21–25 px, die App lag bei 18. Ein Bildschirm hat EINE Spalte, nicht jeder
     Bildschirm seine eigene — deshalb steht der Wert hier und nicht in einer
     Regel je Bildschirm.

     OBEN bleibt es bei 26 px, und das ist gemessen statt gewaehlt: der
     Entwurf faengt je Bildschirm verschieden an — 20 px im Deckbau, 22 px auf
     dem Duell-Einstieg, 24 px in der Garage, 28–30 px auf Auswahl, Korrektur
     und der Zustimmung zum Einsatz. Innerhalb der Toleranz von 4 px trifft
     26 px die meisten davon; 20 px haette drei Bildschirme aus der Toleranz
     geschoben, die vorher darin lagen. Wo der Entwurf weit davon abweicht —
     die Buehnen-Seiten mit ihren 56 px —, steht die Zahl weiter unten je
     Bildschirm. */
  --buehne-oben: 26px;
  --buehne-seite: 22px;
  /* DIE SYSTEMRAENDER DES GERAETS, AN EINER STELLE (WI-0417).

     Die Seite traegt `viewport-fit=cover` (public/index.html), und die
     Capacitor-Huelle legt die Webansicht unter Statusleiste, Dynamic Island
     und Home-Indikator. Ohne diese Raender standen in der iOS-App Uhrzeit und
     Akku auf der Ueberschrift „Garage", dem Filter und dem Konto-Knopf. Wer
     einen Systemrand braucht, nimmt DIESE Tokens, nie ein eigenes `env()`:
     `.app` polstert damit oben und unten fuer jeden Bildschirm, und nur was
     sich aus dem Fluss loest (`position: fixed`) rechnet sie selbst dazu.

     Im Browser, auf dem Rechner und auf Android ohne Kerbe ist `env()` 0 —
     dort aendert sich kein Pixel. Die Seitenraender gelten nur quer, und quer
     gibt es nur den Fotografier-Weg (07l/08l/09l/13l). */
  --sicher-oben: env(safe-area-inset-top, 0px);
  --sicher-unten: env(safe-area-inset-bottom, 0px);
  --sicher-links: env(safe-area-inset-left, 0px);
  --sicher-rechts: env(safe-area-inset-right, 0px);
  /* Die Hoehe, die zwischen den beiden Systemraendern bleibt. Was seine Masse
     aus der Fensterhoehe rechnet, rechnet mit DIESER — sonst wuerde eine
     Karte um die Raender zu gross und die Seite rollte. */
  --sicher-hoehe: calc(100dvh - var(--sicher-oben) - var(--sicher-unten));
  --toast-flaeche: #e2eecb;
  --toast-text: #3d4a2c;
  --wurf-raum: var(--cs-bg-reveal);
  --strich-karte: 1.6;
  --strich-kachel: 1.8;
  --skelett-flaeche: color-mix(in srgb, var(--cs-text) 6%, transparent);
  --buehne-max: 420px;

  /* --- Wunschkanal (Spec 12.1) --- */
  --wunsch-flaeche-hoehe: 96px;
  --wunsch-antwort-hoehe: 60px;
  /* Der Anhang wird ganz gezeigt, nur die Hoehe ist gedeckelt — bezogen auf
     den Bildschirm, damit ein hochkantes Handyfoto gross genug bleibt und die
     Meldungsliste trotzdem blaetterbar bleibt. */
  --wunsch-anhang-hoehe: 60vh;
  --wunsch-verlauf-strich: 2px;
  /* Wie weit eine abgesagte Meldung zuruecktritt (Artboard 47). */
  --wunsch-abgesagt-deckkraft: 0.75;

  /* --- Bilanz (Artboard 41, Produktspec 4.8, WI-0100) --- */
  /* Die Kategorienzeile ist eine dreispaltige Tabelle: Name, Balken, Anteil.
     Nur die beiden Aussenspalten haben ein festes Mass, damit die Balken auf
     gleicher Hoehe anfangen und enden — sonst laege „0–100 km/h" gegenueber
     „Gewicht" um zwei Zentimeter versetzt und die Balken waeren nicht mehr
     vergleichbar. Die Werte sind die des Entwurfs (96 px / 34 px). */
  --bilanz-name-breite: 96px;
  --bilanz-anteil-breite: 34px;
  /* Der Balken einer Kategorie, die NICHT die staerkste ist. Der Entwurf
     zeichnet dafuer denselben Terracotta-Ton mit halber Deckkraft — er wird
     gemischt statt danebengeschrieben, damit Terracotta die eine Aktionsfarbe
     bleibt (Designspec Kap. 9). */
  --bilanz-balken-leise: color-mix(in srgb, var(--color-accent) 55%, transparent);

  /* --- Freunde, Deckbau, Duell (T3) --- */
  /* Der eigene Code-QR MUSS in echtem Schwarz auf echtem Weiss stehen — das
     ist keine Gestaltungsfrage, sondern die Bedingung, unter der eine Kamera
     ihn ueberhaupt liest. Die App-Palette fuehrt bewusst kein reines Weiss
     (Kap. 1: "kein Grau"), deshalb sind das die einzigen zwei rohen Farbwerte
     in diesem ganzen Block. */
  --qr-hell: #fff;
  --qr-dunkel: #000;
  --qr-flaeche: var(--qr-hell);
  /* Artboard 23 zeichnet das Quadrat mit 118 px — NEBEN dem Code, nicht
     darueber. Bis WI-0096 stand es mit 176 px allein in der Spalte und schob
     das Eingabefeld unter die Falz. 118 px sind fuer eine Handykamera aus
     Vorlesedistanz ausreichend; der Code daneben ist ohnehin der zweite Weg. */
  --qr-seite: 118px;
  /* Der Block „Dein Code", wenn der Abruf scheitert oder noch laeuft
     (Artboard 24, WI-0073). Der Entwurf zeichnet einen Kasten mit 24 px
     Radius, einem Haarstrich in der Warnfarbe bei 35 %, 22 px Polster und
     einem 44-px-Kreis fuer das Symbol; die Flaeche ist der Seitengrund bei
     5 % — die schwaechste Stufe desselben Schleiers, den --feld-flaeche bei
     8 % und --blatt-rand bei 14 % fuehren. Der Kreisel ist der eingebettete
     20-px-Kreisel aus HANDOFF §6 (Strichstaerke 3, 0,7 s je Umlauf); es ist
     der erste im Stylesheet, deshalb steht er hier und nicht im Bauteil. */
  --code-fehler-radius: 24px;
  --code-fehler-flaeche: var(--cs-fill-1);
  --code-fehler-rand: color-mix(in srgb, var(--warn-icon) 35%, transparent);
  --code-fehler-strich: 1px;
  --code-fehler-polster: 22px;
  --code-fehler-kreis: 44px;
  --code-fehler-zeichen: var(--icon-mittel);
  --kreisel-groesse: 20px;
  --kreisel-strich: 3;
  --kreisel-dauer: 0.7s;
  --deckbau-kachel: 84px;
  /* „Automatisch füllen" (Artboard 28, WI-0089): eine Pille NEBEN einer
     Textzeile, nicht im Handlungsblock — deshalb flacher als der Ghost-Knopf
     (44px) und mit einem Haarstrich statt der 1.5px der Karte. Rand und
     Schrift kommen aus den vorhandenen Tokens (--feld-rand ist der
     Seitengrund bei 22 %, genau der Rand des Entwurfs). */
  --fuellen-hoehe: 36px;
  --fuellen-strich: 1px;

  /* --- Duell aufsetzen (Artboard 26, WI-0096) ---
     Der Entwurf zeichnet die Wahlkarten mit 20 px Radius und dem gewaehlten
     Rand bei 2 px, die Deckgroessen als 46-px-Pillen. Radius und Hoehe stehen
     auf der Leiter aus §13 nicht — deshalb hier, und nur hier. */
  --wahlkarte-radius: 20px;
  --wahlkarte-rand-aktiv: 2px;
  --groesse-hoehe: 46px;

  /* --- Die Fahrzeuggruppe waehlen (Artboard 26b, WI-0180) ---
     Der Entwurf zeichnet die Gruppenzeilen als 56-px-Bloecke mit 20 px Radius
     und 16 px Seitenpolster, den Gruppennamen in der Ueberschriftenschrift auf
     19 px, den Haken mit 18 px Kantenlaenge. Die gesperrte Zeile steht bei
     45 % Deckkraft — sie bleibt lesbar und ist erkennbar nicht waehlbar.
     Radius und Rand sind dieselben Werte wie an der Wahlkarte von Artboard 26;
     Hoehe, Namensgrad, Haken und Deckkraft fuehrt die Leiter aus §13 nicht,
     deshalb stehen sie hier und nur hier. */
  --gruppenzeile-hoehe: 56px;
  --gruppenzeile-polster: 16px;
  --gruppenzeile-name: 19px;
  --gruppenzeile-haken: 18px;
  --gruppenzeile-gesperrt: 0.45;
  /* Der gestrichelte Einladungskasten, wenn es gar keine Gruppe gibt
     (26b-gruppe-keine) — dasselbe Muster wie die leere Garage (Artboard 21):
     22 px Radius, 20 px Polster, Haarstrich gestrichelt. */
  --gruppen-leer-radius: 22px;
  /* Der Fusssatz von 26b steht auf 12,5 px — die Stufe zwischen `--schrift-klein`
     (12) und `--schrift-hinweis` (13,5), die die Leiter sonst nicht hat. */
  --gruppen-fuss-schrift: 12.5px;
  /* Artboard 26b setzt den Handlungsblock auf 30 px ueber der Kante. Der
     allgemeine Fussfreiraum haelt die schwebende Tableiste frei — die steht
     auf diesem Bildschirm nicht (TABLEISTE_SICHTBAR, public/js/app.js), und
     der Raum waere reine Luft. Dieselbe Ueberlegung wie beim Wurf. */
  --gruppen-fuss-abstand: 30px;

  /* --- Verbindung wird aufgebaut (Artboard 25, WI-0096) ---
     Zwei 60-px-Zeichen wandern in 2,6 s aufeinander zu; der Entwurf setzt sie
     bei -46/+46 px an. Timing und Kurve sind die des Entwurfs. */
  --verbinden-zeichen: 60px;
  --verbinden-schrift: 24px;
  /* Die EIGENE Scheibe auf Artboard 25: `rgba(198,113,57,.22)` mit einem Rand
     auf .6. §11 fuehrt fuer Terracotta nur `--cs-accent-tint` (.14) — die App
     hatte deshalb die dunklere Stufe und stand um eine Farbe neben dem
     Entwurf. Gemischt aus `--color-accent`, wie das Reaktionsblatt es fuer
     seine .18 schon tut: eine Deckkraft daneben zu schreiben waere ein
     zweiter Terracotta-Ton. */
  --verbinden-eigen-flaeche: color-mix(in srgb, var(--color-accent) 22%, transparent);
  --verbinden-eigen-rand: color-mix(in srgb, var(--color-accent) 60%, transparent);
  --verbinden-weg: 46px;
  --verbinden-dauer: 2.6s;

  /* --- Laufende Partien und der Zaehler am Reiter (Artboard 22, WI-0066) ---
     Die Werte stehen im HANDOFF: der Zaehler in §4.3 (20px hoch, Pille,
     11.5px/800), die Zeilen als Block-Radius aus §13 (20-26px). Die
     Akzentflaeche der Einladung ist derselbe Terracotta-Schleier wie ueberall,
     hier als Mischung statt als ausgeschriebenes rgba. */
  --duell-offen-radius: 22px;
  --duell-offen-radius-still: 20px;
  --duell-offen-flaeche: var(--cs-accent-tint);
  --duell-offen-rand: color-mix(in srgb, var(--color-accent) 50%, transparent);
  /* Der Rand der UEBERFAELLIGEN Eroberungs-Wartezeile (Artboard 22e,
     WI-0335): `rgba(198,113,57,.45)` im Entwurf — derselbe Terracotta wie
     --duell-offen-rand, nur 45 statt 50 % und als Mischung statt als
     ausgeschriebenes rgba. */
  --duell-offen-rand-ueberfaellig: color-mix(in srgb, var(--color-accent) 45%, transparent);
  --duell-offen-zeichen: 34px;
  /* Die Glyphe IN dieser Scheibe (Artboard 22: `font-size: 15px`). Sie stand
     bis WI-0330 nicht da, weil der Kreis geerbt hat; seit die Gegnerzeile die
     getoente Avatarscheibe traegt (22-3), braucht sie ihr eigenes Mass. */
  --duell-offen-zeichen-glyphe: 15px;
  --duell-offen-uhr: 18px;

  /* --- Die Kopfzeile von Artboard 22 (WI-0318 F-1, WI-0330 22-1) ---
     Die Hoehe steht im HANDOFF §6, Zeile 22 (38-px-Pille in der Titelzeile).
     Die Bilanz-Pille ist seit WI-0330 die EINZIGE dort.
     HIER STANDEN `--duell-kopf-freund-flaeche`/`-rand` — die Terrakotta-Werte
     der entfallenen `+ Freund`-Pille, zuletzt getragen von der gestrichelten
     Zeile am Ende von „Gegner wählen". Beide Zeile und Token sind am
     13.10.2026 entfallen (Rob, WI-0344, F-1 aus WI-0343): das Brett zeichnet
     die Zeile nicht, und ohne sie hatte keine andere Stelle die Werte mehr
     gelesen. */
  --duell-kopf-pille-hoehe: 38px;
  --duell-kopf-pille-schrift: 13.5px;
  --zaehler-seite: 20px;
  --zaehler-schrift: 11.5px;
  /* §4.3: `padding: 0 6px` — damit auch eine zweistellige Zahl noch in eine
     Pille passt, statt das Quadrat zu sprengen. */
  --zaehler-polster: 6px;
  /* Am AKTIVEN Reiter steht die Zahl hell auf dem Terracotta des Reiters, am
     ruhenden auf dem Auskunftston — HANDOFF §4.3, beide Faelle ausdruecklich.
     Der Ton der Schrift auf hellem Grund ist die dunkle Stufe der
     Akzentrampe; ausgeschrieben stuende er hier ein zweites Mal. */
  --zaehler-flaeche: var(--gruen-icon);
  --zaehler-text: var(--raum-bg);
  --zaehler-flaeche-aktiv: var(--btn-text);
  --zaehler-text-aktiv: var(--color-accent-700);

  /* --- Duell-Ergebnisring (Designspec 7.2, letzter Absatz) ---
     Terracotta bleibt Aktionen vorbehalten; das Ergebnis bekommt trotzdem
     eine eigene Farbe je Ausgang. Sieg nimmt den vorhandenen Erfolgston
     (--gruen-icon, Kap. 4) — keine neue Farbe. Nur die Sternspitze MUSS rein
     weiss sein, die Designspec nennt sie woertlich ("#a4c76b/#fff") und die
     App-Palette fuehrt sonst kein reines Weiss. */
  /* --- Der Rundenauftakt (Produktspec 7.3a) ---
     Der Gewinnhintergrund ist `--cs-bg-win` aus HANDOFF §11. Er liegt heute
     unter dem gewonnenen Auftakt; das gewonnene Duell und der gewonnene
     Vergleich (Artboards 32/33/38) holen ihn sich von hier. */
  --sieg-hintergrund: var(--cs-bg-win);
  /* Die Zeichen: 46 px in der Wahl, 62 px im Ergebnis — daneben das Label. */
  --auftakt-ikone: 46px;
  --auftakt-ikone-gross: 62px;
  --auftakt-name: 13.5px;
  /* WI-0319 (F-12) — die Beschriftung „Du"/Gegnername ueber dem Zeichen
     (Artboard 28b/28c), 10.5 px wie am Artboard gemessen. */
  --auftakt-wer: 10.5px;
  --auftakt-urteil: 34px;
  /* Gewaehlt traegt 2 px Terracotta auf getoenter Flaeche, ungewaehlt die
     Haarlinie des Seitengrunds — dieselben zwei Staerken wie ueberall sonst. */
  --auftakt-rand: 1.5px solid color-mix(in srgb, var(--cs-text) 18%, transparent);
  --auftakt-rand-gewaehlt: 2px solid var(--color-accent);
  --auftakt-flaeche-gewaehlt: color-mix(in srgb, var(--color-accent) 16%, transparent);
  --auftakt-rand-sieger: 2px solid var(--gruen-icon);
  /* Auf 28c traegt die EIGENE, unterlegene Seite eine Warn-Haarlinie statt der
     neutralen — der Entwurf zeichnet sie so, und sie sagt ohne Worte, welche
     der beiden meine war. */
  --auftakt-rand-verloren: 1.5px solid color-mix(in srgb, var(--warn-icon) 45%, transparent);
  /* --- „Wer beginnt", 28d/28e (Handoff v3 §17) ---
     Die Scheibe traegt den Anfangsbuchstaben dessen, der beginnt: 104 px, die
     Marke darin 40 px. Der Leuchtreif sitzt 14 px darum herum — und AUSSCHLIESSLICH
     auf 28d (§14 fuehrt ihn nur dort). */
  --auftakt-scheibe: 104px;
  --auftakt-marke: 40px;
  /* Der Rand der grossen Scheibe (28d/28e). Er ist staerker als die 1,5 px
     jeder anderen Avatarscheibe (§4.5b) — der Entwurf zeichnet ihn mit 2 px,
     weil er hier zugleich der Traeger des Ausgangs ist. */
  --auftakt-marke-rand: 2px;
  --auftakt-reif-ueberstand: 14px;
  --auftakt-scheibe-flaeche: color-mix(in srgb, var(--cs-text) 8%, transparent);
  /* Die Aussage („Du beginnst") ist die groesste Schrift der Partie — 46 px. */
  --auftakt-aussage: 46px;
  --auftakt-aussage-zeile: 15px;
  /* Der Fortschrittsbalken: 4 px, die Spur gedaempft, der Lauf in der Farbe
     des Ausgangs. Seine Dauer ist dieselbe wie die Frist in app.js. */
  --auftakt-balken: 4px;
  --auftakt-balken-spur: color-mix(in srgb, var(--cs-text) 12%, transparent);
  --auftakt-balken-dauer: 1.6s;

  /* --- Die elf Zustaende der laufenden Partie (Artboards 29–39, WI-0095) ---
     Alle Masse stehen im Entwurf; hier stehen sie EINMAL, und jedes Bauteil
     unten greift ueber var() zu. Farben kommen ausnahmslos aus --cs-*. */
  /* Die Raender der Partiebuehne (§5.5: `padding: 12px 20px 0`; die
     Inhaltsspalte darunter sitzt bei 24–26 px). */
  --partie-rand-oben: 12px;
  --partie-rand-seite: 24px;
  /* Kopfzeile (§5.5): Einsatz links, Runde mittig, Ausgang rechts. */
  --partie-kopf-polster: 12px 20px 0;
  --partie-kopf-mitte: 12.5px;
  --partie-kopf-ausgang: 13px;
  /* Die vier festen Saetze der Partie (§5.5b3, Artboards 31b/31c/31d;
     WI-0214). Alle Masse aus dem Entwurf, hier EINMAL. */
  --partie-nachricht-knopf: 34px;
  --partie-nachricht-glyphe: 16px;
  /* An: Rand `rgba(198,113,57,.6)` auf `rgba(198,113,57,.16)`, Glyphe
     `#e8a877`. Aus: Rand `rgba(245,234,216,.2)`, durchsichtig, Glyphe
     `#8d8272` (§5.5b3). Gemischt statt hingeschrieben, wie ueberall sonst —
     eine Deckkraft daneben waere ein zweiter Terracotta-Ton. */
  --nachricht-knopf-rand: color-mix(in srgb, var(--color-accent) 60%, transparent);
  --nachricht-knopf-flaeche: color-mix(in srgb, var(--color-accent) 16%, transparent);
  --nachricht-knopf-glyphe: #e8a877;
  --nachricht-knopf-aus-rand: var(--cs-line-3);
  --nachricht-knopf-aus-glyphe: var(--raum-text-schwach);
  /* Das 2 x 2-Raster im Blatt: 58-px-Zeilen, 10 px Abstand (§6). */
  --nachricht-satz-hoehe: 58px;
  --nachricht-satz-radius: 18px;
  --nachricht-satz-schrift: 14.5px;
  --nachricht-satz-zeichen: 17px;
  /* Die fliegende Pille (§5.5b3): Radius 999, 28-px-Scheibe, 15px/800,
     16-px-Zeichen. */
  --nachricht-pille-polster: 8px 16px 8px 8px;
  --nachricht-pille-abstand: 9px;
  --nachricht-pille-schrift: 15px;
  --nachricht-pille-zeichen: 16px;
  --avatar-nachricht: 28px;
  --avatar-nachricht-glyphe: 13px;
  /* Die zwei Spuren: die Hoehen, auf denen der Entwurf die zwei Pillen
     zeichnet (214 px und 470 px in einem 793-px-Rahmen = 27 % / 59 %). In
     Prozent, damit sie auf jeder Bildschirmhoehe dasselbe Verhaeltnis
     halten — ein fester Pixelwert saesse auf einem kurzen Geraet im Fuss. */
  --nachricht-spur-1: 27%;
  --nachricht-spur-2: 59%;
  --nachricht-flug-1: 4.4s;
  --nachricht-flug-2: 5.2s;
  --nachricht-wippe: 1.6s;
  --nachricht-wippe-weg: 5px;
  --nachricht-neigung: 3deg;
  /* Die ruhige Fassung (`prefers-reduced-motion`, §5.5b3): oben mittig, 2,5 s. */
  --nachricht-ruhig-oben: 12%;
  --nachricht-ruhig-dauer: 2.5s;
  /* Die eine erklaerende Zeile auf 31d. */
  --nachricht-aus-radius: 18px;
  --nachricht-aus-polster: 12px 14px;
  --nachricht-aus-abstand: 11px;
  --nachricht-aus-schrift: 12.5px;
  /* Die halbe Karte des Vergleichs (§5.4): 150 px, Zahlen statt Balken. */
  --partie-halb-breite: 150px;
  --partie-halb-radius: var(--radius-md);
  --partie-halb-polster: 10px;
  --partie-halb-name: 16px;
  --partie-halb-klasse: 11px;
  /* Fotoband der Halbkarte, 150 / 58 = 2,59 (mit --partie-halb-breite). Es
     steht in `FOTOBAENDER` (public/js/filterchain.js) — wer es aendert,
     aendert den Zuschnitt der Filterkette mit; Begruendung an --km-foto-h. */
  --partie-halb-foto: 58px;
  --partie-halb-zeile: 11.5px;
  --partie-halb-gespielt: 19px;
  --partie-halb-rand-sieger: 0 0 0 2px var(--gruen-icon), 0 0 18px rgba(var(--sieg-farbe-glow), 0.35);
  --partie-halb-rand-verlierer: 0 0 0 1.5px var(--feld-rand);
  /* Die gespielte Zeile wird aus der Liste HERAUSGEHOBEN — beim Sieger gruen
     gefuellt, beim Verlierer nur umrandet. */
  --partie-gespielt-radius: 9px;
  --partie-gespielt-polster: 6px 8px;
  --partie-gespielt-flaeche: color-mix(in srgb, var(--cs-good) 18%, transparent);
  --partie-gespielt-rand: 1.5px solid var(--gruen-icon);
  --partie-gespielt-rand-verlierer: 1.5px solid
    color-mix(in srgb, var(--warn-icon) 50%, transparent);
  /* Die Urteilszeile: 23 px im Vergleich (§5.4), 34 px in der Bewegung. */
  --partie-urteil: 23px;
  --partie-urteil-gross: 34px;
  /* Die Stapelzeile auf 29: eine kleine Rueckseite links. */
  --partie-ruecken-breite: 48px;
  --partie-ruecken-hoehe: 66px;
  /* Das dritte Element der Stapelzeile, solange Karten im Topf liegen
     (HANDOFF §5.5b6, WI-0346): derselbe lila Ton wie der EROBERT-Chip und
     der Gleichstand — `--cs-r-epic` mit `--cs-epic-soft` als Schrift, kein
     neuer Farbwert. */
  --partie-stapel-topf-flaeche: color-mix(in srgb, var(--cs-r-epic) 14%, transparent);
  --partie-stapel-topf-rand: 1px solid color-mix(in srgb, var(--cs-r-epic) 40%, transparent);
  --partie-stapel-topf-radius: 12px;
  /* 34 px hoch und 11 px Innenpolster — die Masse, die §5.5b6 fuer die
     Bloecke der Stapelzeile ausschreibt. */
  --partie-stapel-topf-hoehe: 34px;
  --partie-stapel-topf-polster: 11px;
  /* Der Topf (36): vier Rueckseiten fallen in die Mitte. */
  --partie-topfkarte-breite: 76px;
  --partie-topfkarte-hoehe: 106px;
  --partie-topf-flaeche: color-mix(in srgb, var(--cs-r-legendary) 10%, transparent);
  --partie-topf-rand: 1.5px solid color-mix(in srgb, var(--cs-r-legendary) 45%, transparent);
  --partie-topf-titel: var(--cs-r-legendary);
  --partie-topf-dauer: 900ms;
  --partie-topf-versatz: 160ms;
  --partie-topf-kurve: cubic-bezier(0.25, 0.9, 0.3, 1);
  /* Die Ringe der gewonnenen Runde (33). Bei der verlorenen gibt es KEINE. */
  --partie-ring: 300px;
  --partie-ring-dauer: 1.6s;
  --partie-ring-versatz: 0.55s;
  --partie-karten-dauer: 1.8s;
  --partie-karten-dauer-verloren: 1.9s;
  --partie-karten-kurve: cubic-bezier(0.5, 0, 0.5, 1);
  /* Das Ergebnis (38/39): 150 px Ring, 42 px Titel. */
  --partie-ergebnis-titel: 42px;

  /* --- WI-0208: die Rundenstrecke vom 06.09. (HANDOFF §22) --- */
  /* Der Balken des Vergleichs (32/34) laeuft 1,4 s — kuerzer als die 1,6 s des
     Auftakts, „weil der Vergleich schon gelesen ist, wenn er erscheint"
     (§22.2). Die Zahl ist dieselbe wie die Frist in app.js (`STRECKE_MS`). */
  --partie-balken-dauer: 1.4s;
  /* Die Aufdeckung auf 31 (§5.5b, §22.4): heben 220 ms, danach 620 ms drehen.
     Bei 840 ms steht das Gesicht — dort wechselt der Bildschirm. */
  --partie-aufdeck-heben: 220ms;
  --partie-aufdeck-drehen: 620ms;
  --partie-aufdeck-kurve: cubic-bezier(0.35, 0, 0.2, 1);
  /* 33b — der Wartestand. Die Karten sind erledigt, nicht taetig. */
  --partie-warten-karten: 0.55;
  --partie-warten-titel: 30px;
  /* Der Salbei-Block „Du bist durch" — KEIN Knopf. Flaeche und Text fuehrt
     §11 als --cs-good-tint / --cs-good-soft; den Rand zeichnet 33b mit .45,
     also wird er aus derselben Farbe gemischt statt danebengeschrieben —
     dieselbe Bauart wie --gruen-rand und --reaktion-pille-rand. */
  --partie-durch-hoehe: 48px;
  --partie-durch-flaeche: var(--cs-good-tint);
  --partie-durch-rand: color-mix(in srgb, var(--cs-good) 45%, transparent);
  --partie-durch-text: var(--cs-good-soft);
  --partie-durch-haken: 17px;

  --sieg-farbe: var(--gruen-icon);
  --sieg-farbe-glow: 164, 199, 107;
  --sieg-stern-hell: var(--qr-hell);
  --niederlage-farbe: var(--raum-text-gedaempft);
  --ergebnis-ring-schein: 0 0 26px rgba(var(--sieg-farbe-glow), 0.6);
  --duell-funke-dauer-min: 1.3s;
  --duell-funke-dauer-max: 1.9s;
  --duell-stern-dauer-min: 1.5s;
  --duell-stern-dauer-max: 2s;
}

/* --- Seltenheit: was aus der Farbe folgt (Kap. 5) ---
 *
 * WARUM DIESE SECHS NICHT IM :root-BLOCK DARUEBER STEHEN: ein `var()` in einer
 * EIGENEN Eigenschaft wird dort eingesetzt, wo die Eigenschaft DEKLARIERT ist,
 * nicht dort, wo sie benutzt wird. Am `:root` allein waeren sie fertig
 * gerechnet — und die Karte, die weiter unten ihren eigenen Ton setzt, erbte
 * den fertigen Wert statt der Vorschrift. Genau daran hingen bis WI-0048 die
 * fehlende Balkenfuellung, der fehlende Kantenschein, die farblosen Flaechen
 * von Kopfbalken und Gruppenkreis und der unsichtbare Streifen der
 * Garagenkachel.
 *
 * Deshalb steht die Vorschrift hier ZWEIMAL zur Auswertung, aber nur EINMAL
 * geschrieben: am `:root` rechnet sie mit der neutralen Vorstufe, und an jedem
 * Element mit `data-stufe` — das ist das seltenheitsgefuehrte Element, an dem
 * public/js/design.js ueber card.faerbe() Ton und Attribut gemeinsam setzt —
 * rechnet sie neu mit dessen Ton. Wer eine dieser Eigenschaften braucht,
 * benutzt weiter denselben Tokennamen; es gibt keinen zweiten Weg daneben. */
:root,
[data-stufe] {
  --kante-gefaerbt: 0 0 0 2.5px var(--r-g), inset 0 0 40px rgba(var(--r-glow), 0.12),
    0 0 26px rgba(var(--r-glow), 0.45), var(--cs-shadow-card);
  /* Dieselbe Kante eine Stufe kraeftiger — die maximierte Karte des
     Doppeltipps (Artboard 15b, §17: Rahmen 3px, inset 52px/.14, Schein
     44px/.5). Sie steht allein auf dem Schirm und traegt deshalb mehr. */
  --km-kante-gefaerbt: 0 0 0 3px var(--r-g), inset 0 0 52px rgba(var(--r-glow), 0.14),
    0 0 44px rgba(var(--r-glow), 0.5), var(--cs-shadow-card);
  --glow-flaeche: rgba(var(--r-glow), 0.16);
  --balken-fuellung: linear-gradient(90deg, var(--r-c), var(--r-g));
  --balken-glow: 0 0 6px rgba(var(--r-glow), 0.6);
  --silhouette-glow: drop-shadow(0 0 8px rgba(var(--r-glow), 0.55));
  --halo: radial-gradient(ellipse at 50% 45%, rgba(var(--r-glow), 0.22), transparent 62%);
}
/* == TOKEN-BLOCK: ENDE == */

/* --------------------------------------------------------------------------
 * Grundlage
 * ------------------------------------------------------------------------ */

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--raum-bg);
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--schrift-fliess);
  line-height: var(--zeilenhoehe-fliess);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
  letter-spacing: var(--laufweite-heading);
  margin: 0;
}

h1 {
  font-size: var(--schrift-h1);
}
h2 {
  font-size: var(--schrift-h2);
}
h3 {
  font-size: var(--schrift-h3);
}
h4 {
  font-size: var(--schrift-h4);
}
h5 {
  font-size: var(--schrift-h5);
}
h6 {
  font-size: var(--schrift-h6);
  text-transform: uppercase;
  letter-spacing: var(--laufweite-versal);
}

p {
  margin: 0;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Ikonen tragen ihre Groesse hier, nicht als width/height am Element — sonst
 * stuende wieder ein roher Wert im Bauteil. */
.ikone {
  flex: none;
  width: var(--icon-gross);
  height: var(--icon-gross);
}

.ikone--schild {
  width: var(--icon-klein);
  height: var(--icon-klein);
}

.ikone--haken {
  width: var(--icon-winzig);
  height: var(--icon-winzig);
}

.app {
  position: relative;
  min-height: 100dvh;
  /* Die Systemraender (WI-0417): JEDER Bildschirm liegt in `.app__buehne`,
     und die beginnt damit unter Statusleiste und Dynamic Island und endet
     ueber dem Home-Indikator. Der Grund darunter laeuft von Kante zu Kante
     weiter. */
  padding-top: var(--sicher-oben);
  padding-bottom: var(--sicher-unten);
  background: var(--raum-verlauf);
  display: flex;
  flex-direction: column;
}

/* DIE ZWEI SONDERGRUENDE AUS §11 (WI-0188). Der Entwurf malt sie auf den
   RAHMEN des Artboards — unter allem, von Kante zu Kante —, und genau das ist
   diese Stelle: `#app` ist die einzige Flaeche, die den ganzen Bildschirm
   traegt. Welchen Grund ein Bildschirm braucht, sagt er selbst an `data-raum`;
   public/js/app.js hebt den Wert hierher.

   `--cs-bg-stage` ist die Buehne, auf der gewartet wird (Artboard 25, dieselbe
   wie 08); `--cs-bg-win` liegt unter dem gewonnenen Auftakt (28d). Beide sind
   Token aus §11 und standen bis hierher an keinem Bildschirm. */
.app[data-raum='buehne'] {
  background: var(--cs-bg-stage);
}

.app[data-raum='sieg'] {
  background: var(--sieg-hintergrund);
}

.app__buehne {
  flex: 1;
  width: 100%;
  max-width: var(--buehne-max);
  margin: 0 auto;
  padding: var(--buehne-oben) var(--buehne-seite) var(--buehne-unten);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Die Kartenseite (WI-0038): Hier steht die Karte unter Platzdruck, deshalb
   endet die Buehne dicht ueber der schwebenden Leiste statt am allgemeinen
   Fussfreiraum. Was dadurch frei wird, nimmt die Karte — verdeckt wird nichts,
   denn --karte-fuss deckt die Leiste samt Abstand vollstaendig ab. */
.app__buehne[data-bildschirm='karte'] {
  /* Oben traegt seit WI-0055 die Kopfzeile mit dem Schliessen-Kreuz den
     Abstand zur Bildkante; das allgemeine Polster kaeme oben drauf und ginge
     der Karte verloren. */
  padding-top: var(--kd-rand-oben);
  padding-bottom: var(--karte-fuss);
  /* Die Kante, an der die gewischte Kartenseite verschwindet (WI-0051). Ohne
     sie waere der herausgleitende Block scrollbare Breite und das Handy
     bekaeme einen waagerechten Balken. `clip` statt `hidden`: `hidden` machte
     die Buehne zum Scrollbehaelter und naehme der Seite das senkrechte
     Scrollen. Der Schnittrand laesst den Kartenschein stehen, damit die
     Ruhelage aussieht wie vorher. */
  overflow-x: clip;
  overflow-clip-margin: var(--wisch-schnitt-rand);
}

/* DIE RAENDER DES AUFDECKBILDSCHIRMS (WI-0097, Artboard 13).
   Der Entwurf setzt ihn auf `16px 26px 0` mit dem Aktionsblock bei `bottom:
   26` — er zeigt KEINE Tableiste, und der allgemeine Fussfreiraum von 96px
   (der die schwebende Leiste freihaelt) war hier deshalb reine Luft. Oben
   dasselbe: die Augenbraue „NEUE KARTE" steht im Entwurf dicht an der Kante,
   nicht ein volles Polster darunter. */
.app__buehne[data-bildschirm='wurf'] {
  padding: var(--space-2) var(--datenblock-fuge) var(--space-6);
}

/* DER FUSS VON ARTBOARD 26b (WI-0180) — derselbe Gedanke wie beim Wurf: der
   Bildschirm zeigt keine Tableiste, der allgemeine Fussfreiraum hielte sie
   umsonst frei, und der Entwurf setzt den Handlungsblock auf 30 px ueber der
   Kante. */
.app__buehne[data-bildschirm='gruppenwahl'] {
  padding-bottom: var(--gruppen-fuss-abstand);
}

/* Dasselbe fuer die beiden Wahlbildschirme des Garagenfilters (20b/20c): auch
   sie tragen keine Tableiste, und die 90px, die fuer sie frei blieben, kosten
   genau das, was diese Bildschirme brauchen — Listenzeilen. Der Entwurf fuehrt
   die Liste auf beiden Artboards bis dicht an die untere Kante. */
.app__buehne[data-bildschirm='garage_marke'],
.app__buehne[data-bildschirm='garage_fundzeit'] {
  padding-bottom: var(--wahlseite-fuss);
}

.gestapelt {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.mittig {
  text-align: center;
  align-items: center;
}

/*
 * DIE KLEINE VERSALZEILE UEBER EINER GRUPPE (HANDOFF §4.6 und §12, Zeile
 * „Section label"): 11 px, Gewicht 800, .08em Laufweite, versal,
 * --cs-text-dim. Der Entwurf schreibt damit JEDEN Abschnitt an — „Wartet auf
 * dich", „Gegner wählen", „Dein Code", „Deckgröße".
 *
 * SIE IST EIN ETIKETT, KEINE UEBERSCHRIFT ZWEITER ORDNUNG, und deshalb eine
 * Klasse auf dem vorhandenen h4 statt eines neuen Tags: die Gliederung des
 * Dokuments bleibt, wie sie war (h3 Bildschirmtitel, h4 Abschnitt), nur das
 * Aussehen folgt dem Entwurf. Der h4-Grad der Skala (20 px) bleibt fuer alles
 * andere unveraendert.
 *
 * IHR TON — ERLEDIGT MIT WI-0340. Der Entwurf faerbt sie im HTML mit
 * #a89c88. Bis WI-0340 stand hier --cs-text-dim, weil §4.6 und §12 beide
 * dieses Token nennen und §11 #a89c88 gar nicht fuehrte: §7 Punkt 12
 * verbietet einem Bauteil, sich einen eigenen Ton auszudenken, also wurde der
 * naechstliegende vorhandene genommen und die Abweichung als Befund gemeldet
 * (WI-0337/WI-0338: 49 der 171 Farbabweichungen hingen daran). Die Luecke ist
 * geschlossen — HANDOFF §16.7 („Add `#A89C88` as `label`", 01.10.2026) fuehrt
 * den Ton seit WI-0340 als --cs-label in §11, und die Zeile bindet daran.
 * Dass §4.6/§12 im Fliesstext weiter --cs-text-dim nennen, ist die AELTERE
 * Stelle; die datierte Entscheidung in §16.7 geht vor.
 */
/*
 * DER TITEL EINES REITER-BILDSCHIRMS (HANDOFF §12, Zeile „Screen title
 * (tab)"): 28 px in der Ueberschriftenfamilie. Die Skala fuehrt zwischen h2
 * (32 px, „Screen title (flow)") und h3 (25 px, „Sheet title") keinen Grad
 * dafuer — der Entwurf zeichnet die Duell-Bildschirme aber genau dazwischen.
 * Deshalb eine Klasse auf dem vorhandenen h3 statt eines neuen Grades in der
 * Skala: die Skala kommt aus dem Handoff und wird nicht von Hand ergaenzt
 * (public/css/tokens.css, Kopf).
 */
.bildschirm-titel {
  font-size: var(--schrift-titel-reiter);
}

.abschnitt {
  font-family: var(--font-body);
  font-size: var(--schrift-abschnitt);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-versal);
  line-height: var(--zeilenhoehe-fliess);
  text-transform: uppercase;
  color: var(--raum-text-etikett);
}

.meta {
  color: var(--raum-text-meta);
  font-size: var(--schrift-klein);
}

/* „Body small", untere Stufe (§12: 13–14,5 px). Der Entwurf setzt darauf die
   erklaerenden Zeilen unter einem Absatz — die Unterzeile des Deckbaus, den
   Satz zur Elternmail auf dem gesperrten Duell. */
.hinweis {
  font-size: var(--schrift-hinweis);
  color: var(--raum-text-gedaempft);
  line-height: var(--zeilenhoehe-fliess);
}

/* Die Zeile, die eine Zahl traegt (§12 „Body small", obere Stufe). */
.zeile {
  font-size: var(--schrift-zeile);
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

.gedaempft {
  color: var(--raum-text-gedaempft);
}

.fliess {
  color: var(--raum-fliess);
}

/* --------------------------------------------------------------------------
 * Knoepfe, Felder — Terracotta ist die EINZIGE Aktionsfarbe (Kap. 1)
 * ------------------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--btn-hoehe);
  padding: 0 var(--space-6);
  border: 0;
  border-radius: var(--radius-pille);
  background: var(--color-accent);
  color: var(--btn-text);
  font-family: var(--font-body);
  font-size: var(--btn-schrift);
  font-weight: var(--gewicht-fett);
  box-shadow: var(--btn-glow);
  cursor: pointer;
}

.btn[disabled] {
  box-shadow: none;
  cursor: not-allowed;
}

/* Die HAUPTAKTION im ausgeschalteten Zustand — §4.5 „Primary disabled".
   Sie traegt eine eigene Flaeche und eine eigene Schriftfarbe, keine
   Deckkraft (siehe --btn-flaeche-aus im Token-Block). */
.btn[disabled]:not(.btn--ghost):not(.btn--ghost-warn):not(.btn--gestrichelt):not(.btn--fuellen) {
  background: var(--btn-flaeche-aus);
  color: var(--btn-text-aus);
}

/* Die zurueckgenommenen Formen haben keine Flaeche, die blasser werden
   koennte — sie bleiben bei der Deckkraft. */
.btn--ghost[disabled],
.btn--ghost-warn[disabled],
.btn--gestrichelt[disabled],
.btn--fuellen[disabled] {
  opacity: var(--deaktiviert-deckkraft);
}

.btn--ghost {
  min-height: var(--btn-hoehe-ghost);
  font-size: var(--btn-schrift-ghost);
  font-weight: var(--gewicht-kraeftig);
  background: transparent;
  border: var(--ghost-rand);
  color: var(--ghost-text);
  box-shadow: none;
}

/* Der warnende Ghost (WI-0070, Artboard 17) — dieselbe Form, warmer Rand und
   warme Schrift. Er steht dort, wo ein Knopf etwas WEGNIMMT. */
.btn--ghost-warn {
  border: var(--ghost-warn-rand);
  color: var(--ghost-warn-text);
}

.btn--gestrichelt {
  min-height: var(--btn-hoehe-ghost);
  background: transparent;
  border: var(--karte-rand) dashed var(--feld-rand);
  color: var(--ghost-text);
  font-weight: var(--gewicht-halb);
  box-shadow: none;
}

.btn--voll {
  width: 100%;
}

/* DIE PILLE `Weitere Kartendetails` (WI-0114, Artboards 14 und 15, §17).
   Seit v3 der einzige Weg in die Detailansicht mit Wurf und Besitzerkette.

   Sie ist die HAUPTAKTION ihres Blocks und sieht danach aus — ohne der volle
   Terracotta-Knopf zu sein: der bleibt den Wegen vorbehalten, die etwas
   veraendern (Kap. 1, „Terracotta ist die einzige Aktionsfarbe"). Deshalb
   Akzentfuellung und warmer Rand statt Flaeche, und deshalb kein Schein. */
.btn--details {
  min-height: var(--details-hoehe);
  background: var(--cs-accent-tint);
  border: var(--karte-rand) solid var(--details-rand);
  color: var(--details-text);
  font-size: var(--btn-schrift-ghost);
  box-shadow: none;
}

/* Die Balkendiagramm-Ikone links in der Pille: sie steht fuer die
   Werte-Auskunft dahinter, nicht fuers Vergroessern. */
.ikone--balken {
  width: var(--details-ikone);
  height: var(--details-ikone);
  flex: none;
  color: var(--warn-icon);
}

.link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--raum-text-gedaempft);
  font-family: var(--font-body);
  font-size: var(--schrift-klein);
  text-decoration: underline;
  cursor: pointer;
}

.feld {
  width: 100%;
  min-height: var(--btn-hoehe);
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--btn-schrift);
}

.feld::placeholder {
  color: var(--raum-text-schwach);
}

.feldgruppe {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* Die BESCHRIFTUNG einer Feldgruppe steht in Versalien (HANDOFF §12, h6).
   Eine Meta-Zeile daneben — der Zeichenzaehler unter dem Beschreibungsfeld,
   die Zeile unter „Bild dazu" (Artboard 46) — ist KEINE Beschriftung und
   bleibt in normaler Schreibung; sonst schriee der Zaehler lauter als das
   Feld, zu dem er gehoert. */
.feldgruppe > span:not(.meta) {
  font-size: var(--schrift-h6);
  text-transform: uppercase;
  letter-spacing: var(--laufweite-versal);
  color: var(--raum-text-etikett);
}

.hinweis--gruen {
  background: var(--gruen-flaeche);
  border: var(--karte-rand) solid var(--gruen-rand);
  border-radius: var(--radius-md);
  color: var(--gruen-text);
  padding: var(--space-3);
  font-size: var(--schrift-klein);
}

/* Derselbe Kasten MIT dem Stern davor (Artboard 12, WI-0068). Eigene Klasse
   und nicht am Grundbauteil: die Loeschabfrage (Artboard 17) fuehrt in
   demselben Kasten Fliesstext mit einer fetten Stelle darin — als Flexzeile
   stuende ihre Hervorhebung neben dem Satz statt darin. */
.hinweis--gruen--zeichen {
  display: flex;
  gap: var(--space-3);
}

.hinweis--gruen--zeichen .ikone--stern {
  width: var(--icon-klein);
  height: var(--icon-klein);
  color: var(--gruen-icon);
}

.blatt {
  background: var(--blatt-flaeche);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-karte);
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  box-shadow: var(--shadow-lg);
}

.blatt--unten {
  margin-top: auto;
}

/* --------------------------------------------------------------------------
 * Die Seite und ihr Aktionsblock (HANDOFF §4.2/§4.4, WI-0068)
 *
 * Der Entwurf verankert die Hauptaktion jeder Ablaufseite UNTEN: Inhalt oben,
 * `margin-top:auto` am Aktionsblock, darunter der Fussabstand. Ohne das stand
 * auf `11-scan-pick-model` 276 px und auf `12-scan-manual-entry` 370 px
 * ungenutzter Raum unter den Knoepfen — und der Daumen musste in die
 * Bildschirmmitte greifen (Designspec 10.3 Punkt 1).
 * ------------------------------------------------------------------------ */

.seite {
  flex: 1;
  min-height: 0;
}

.aktionsblock {
  margin-top: auto;
  padding-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --------------------------------------------------------------------------
 * Start
 * ------------------------------------------------------------------------ */

.start {
  justify-content: center;
  gap: var(--space-6);
}

/* Artboard 01 zentriert seinen Inhalt senkrecht (`justify-content: center`
   ueber die volle Hoehe). Damit das Zentrieren ueberhaupt greift, muss der
   Block die Buehne AUSFUELLEN — sonst ist er nur so hoch wie sein Inhalt und
   „zentriert" ihn in sich selbst. Das fiel erst mit WI-0171 auf: bis dahin
   fuellten Zeichenraster und Altersstufen die Hoehe von allein, und seit die
   beiden eigene Schritte sind, ist der Bildschirm kurz.
   Nur der Startbildschirm: `.start` traegt auch der Anmeldeweg mit dem Code
   und der Codebildschirm, und beide stehen so, wie ihr Entwurf sie zeichnet. */
.app__buehne[data-bildschirm='start'] .start {
  flex: 1;
}

/* DIE MARKE AUF ARTBOARD 01 — SEIT WI-0223 DAS APP-ICON, NICHT DIE KAMERA.
   `.start__kreis` ist seit WI-0045 der Platz der Marke auf 01; der Name
   bleibt, der Inhalt ist getauscht. Was hier WEGFAELLT, ist die
   Terracotta-Scheibe samt Glut: sie war der Rahmen des Kameraglyphs, und
   Terracotta gehoert der AKTION (Designspec Kap. 11) — der Entwurf zeichnet
   an dieser Stelle nur das Icon, ohne Flaeche darunter. Die Tokens
   `--start-kreis*` bleiben, weil das Skelett sie weiter fuehrt (die Scheibe
   auf 03 ist mit WI-0302 fort). */
.start__kreis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Das Icon selbst. Die Datei bringt ihre Rundung als Clip-Pfad schon mit —
   der Radius steht hier trotzdem, weil er im Entwurf am Element steht und
   nicht an der Datei: wer die Datei eines Tages austauscht, soll die Ecken
   nicht verlieren. */
.start__marke {
  display: block;
  width: var(--start-marke);
  height: var(--start-marke);
  border-radius: var(--start-marke-radius);
}

.start__titel {
  font-family: var(--font-heading);
  font-size: var(--start-titel);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
  letter-spacing: var(--laufweite-heading);
}

/* --------------------------------------------------------------------------
 * DER NAMENSSCHRITT GEGEN DAS OKTOBER-BRETT — 01, 01e, 01f (WI-0281, IG-03)
 *
 * Das Brett zeichnet drei Lagen uebereinander, und `.start` selbst bekommt
 * keine davon: die Klasse traegt auch der Altzugang (`altzugang`, `zettel`,
 * IG-01), und eine Regel an ihr nahm die beiden mit, ohne dass sie gemessen
 * wuerden. Alles Neue haengt deshalb an `.start__*` bzw. an den drei geteilten
 * Bauteilen aus WI-0279 (`.kopfweg`, `.anmeldefuss`, `.warnzeile`).
 * ------------------------------------------------------------------------ */

/* Die Mitte: Icon, Titel, Frage, Feld, Meldeplatz und Fussabsatz, mittig
   ueber die freie Hoehe — `flex:1;justify-content:center` wie im Brett. Feld,
   Meldeplatz und Fussabsatz stehen darin auf voller Breite (`align-self:
   stretch` im Brett), der Rest mittig. */
.start__mitte {
  flex: 1;
  min-height: 0;
  justify-content: center;
  gap: var(--space-2);
}

/* Das Icon hat im Brett 24 px Luft nach unten — mehr als die Luecke des
   Stapels, und es ist die einzige Stelle mit einem eigenen Abstand. */
.start__kreis {
  margin-bottom: var(--space-3);
}

.start__feld {
  align-self: stretch;
}

/* DER PLATZ UNTER DEM FELD, 38 px — auch leer (Artboard 01). Dieselbe Hoehe
   wie auf `00` und aus demselben Grund: der Fussblock darf beim ersten zu
   kurzen Namen nicht wandern. Deshalb auch dasselbe Token — zwei Zahlen fuer
   dieselbe gezeichnete Hoehe waeren zwei Wahrheiten. */
.start__meldung {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  min-height: var(--einstieg-meldung-hoehe);
}

/* BEIDE SAETZE STEHEN VORGEZEICHNET IM PLATZ und werden nur ein- und
   ausgeblendet (siehe `startNameEl`). `hidden` ALLEIN reicht dafuer nicht:
   `.warnzeile` setzt selbst `display:flex`, und eine Autorenregel sticht das
   `display:none`, das der Browser dem Attribut mitgibt — die Absage aus `01e`
   stand damit auch auf `01` da, bei leerem Feld, und das Referenzbild hat es
   gezeigt. Dieselbe Bauart wie `.tableiste[hidden]` und `.toast[hidden]`. */
.start__meldung > [hidden] {
  display: none;
}

/* `01f`: die Auskunft zur schon gewaehlten Farbe. Kein Warnton — sie sagt,
   dass etwas BLEIBT, und `--cs-warn` gehoert der Absage daneben. */
.start__farbe {
  margin: 0;
  text-align: left;
  /* Derselbe gedaempfte Ton wie der Fussabsatz darunter — das Brett faerbt
     beide Zeilen auf `01f` mit #8d8272. */
  color: var(--raum-text-schwach);
}

/* Der Schutzsatz unter dem Feld (Artboards 01/01e/01f). Er steht im Brett
   LINKS und im gedaempften Ton `--cs-text-dim` — `01` fuehrt `dim` in
   design/colours.json als tragende Farbe, und bis WI-0281 fehlte sie dem
   Bildschirm. Vor WI-0281 stand der Satz zentriert unter dem Knopf; das
   Oktober-Brett setzt ihn ueber den Fussblock, weil der Knopf dort den
   unteren Rand haelt. */
.start__fuss {
  align-self: stretch;
  margin: 0;
  text-align: left;
  color: var(--raum-text-schwach);
}

/* Die Fusszeile „Drei bis sechzehn Zeichen." traegt im Brett denselben
   gedaempften Ton. Die Regel bleibt auf den Namensschritt BESCHRAENKT: die
   acht Geschwister aus WI-0279 teilen dieses Bauteil, ihre Artboards zeichnen
   den Ton genauso — aber sie sind nicht dieses Item, und ihre App-Seite ist
   nicht aufgenommen. Die allgemeine Korrektur gehoert dem Item, das sie
   besitzt; gemeldet ist sie im Bericht. */
.start .anmeldefuss__note {
  color: var(--raum-text-schwach);
}

/* --------------------------------------------------------------------------
 * Anmeldung, Schritt 2 und 3 — Artboards 01b und 02 (WI-0171)
 * ------------------------------------------------------------------------ */

/* DIE BEIDEN FOLGESCHRITTE, und warum sie nicht `.start` benutzen.
   `.start` zentriert seinen Inhalt (Artboard 01 tut das auch). 01b und 02
   sind dagegen von OBEN gesetzt, mit einem `margin-top: auto` vor der
   Aktionsgruppe — genau das, was Designspec Kap. 10.3 Punkt 1 und 3
   verlangen: die Hauptaktion im unteren Drittel, und kein leerer Raum
   darunter, wo das Geraet mehr hergibt. */
.anmeldung {
  flex: 1;
  justify-content: flex-start;
  padding-top: var(--space-4);
  gap: var(--space-3);
}

.anmeldung__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Die Vorschau: Scheibe und Name untereinander, mittig (01b). */
.anmeldung__vorschau {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) 0;
}

/* Auf 02 steht dieselbe Scheibe allein und links — der Entwurf zeigt dort,
   WAS gewaehlt wurde, und bietet keine zweite Wahl an. */
.anmeldung__vorschau--zeile {
  flex-direction: row;
  align-items: center;
  align-self: flex-start;
}

.anmeldung__name {
  font-family: var(--font-heading);
  font-size: var(--schrift-h4);
}

/* Der Satz ueber dem Knopf schiebt die Aktionsgruppe nach unten. */
.anmeldung__fuss {
  margin: auto 0 0;
}

/* --------------------------------------------------------------------------
 * DIE E-MAIL-ANMELDUNG — Artboards 00, 00b–00l, 06b–06f (WI-0279)
 *
 * DREI REGELN GELTEN AUF ALLEN SIEBZEHN, und sie sind Designspec Kap. 10.3:
 *
 *   1. Die Hauptaktion liegt UNTEN. Jeder dieser Bildschirme schiebt seinen
 *      Aktionsblock mit `margin-top: auto` an den Fuss — kein fester Abstand,
 *      der auf 393 x 793 zufaellig passt.
 *   2. Jeder hat einen sichtbaren Rueckweg. Entweder die Zurueck-Zeile am
 *      Kopf (`.kopfweg`) oder einen Nebenweg im Fuss; `06c` ist die eine
 *      begruendete Ausnahme — dort ist nichts zu entscheiden.
 *   3. Keine feste Hoehe, wo das Geraet mehr hergibt: `flex: 1` auf dem
 *      Block, `min-height` statt `height` auf den Plaetzen, die ihre Hoehe
 *      auch leer behalten muessen.
 *
 * KEINE HARTKODIERTEN WERTE. Farben kommen aus `--cs-*` bzw. den Aliassen im
 * Token-Block, Abstaende aus `--space-*`, Radien aus `--radius-*` und den
 * Masse-Tokens darueber. Fehler tragen AUSSCHLIESSLICH `--warn-icon`
 * (`--cs-warn`) und `--warn-flaeche` (`--cs-warn-tint`) — Terracotta bleibt
 * der Aktion vorbehalten.
 * ------------------------------------------------------------------------ */

/* Keine Tableiste, also kein Platz fuer eine: diese Bildschirme enden dicht
   ueber der unteren Kante, wie der Entwurf sie zeichnet (siehe
   --anmelde-fuss).

   `start` STEHT SEIT WI-0281 GANZ IN DIESER LISTE. WI-0279 hat die Auswahl
   bewusst auf `[data-stand]` verengt — also auf die vier Anlagezustaende
   `06c`–`06f` —, weil der Namensschritt `01` damals nicht umgebaut werden
   durfte und mit seinem Fuss auch sein Referenzbild gewandert waere. Das ist
   jetzt der Auftrag: Artboard `01` setzt seinen Aktionsblock auf
   `padding-bottom:30px`, eine Tableiste steht hier so wenig wie auf den
   anderen sechzehn, und die 90 px von `--buehne-unten` waeren genau die
   leere Luft unter dem Hauptknopf, die Designspec Kap. 10.3 Punkt 3
   verbietet. Mit der ganzen Auswahl springt der Bildschirm beim Wechsel
   zwischen `01` und `06c`–`06f` ausserdem nicht mehr. */
/* `konto_email` STEHT MIT IN DIESER LISTE (WI-0287, Artboards 43b/43c).
   Beide Bretter setzen ihren Aktionsblock auf `padding-bottom:30px`, und eine
   schwebende Tableiste gibt es hier nicht: `konto_email` steht so wenig in
   `TABLEISTE_SICHTBAR` wie `konto` selbst (public/js/app.js). Die 90 px von
   `--buehne-unten` waeren damit genau die leere Luft unter dem Hauptknopf,
   die Designspec Kap. 10.3 Punkt 3 verbietet — die 90-px-Zusage des Entwurfs
   gilt dort, wo die Leiste WIRKLICH schwebt. */
.app__buehne[data-bildschirm='anmelden'],
.app__buehne[data-bildschirm='code'],
.app__buehne[data-bildschirm='umstieg'],
.app__buehne[data-bildschirm='botcheck'],
.app__buehne[data-bildschirm='konto_email'],
.app__buehne[data-bildschirm='start'] {
  padding-bottom: var(--anmelde-fuss);
}

/* Die Zurueck-Zeile am Kopf von 00b, 00c, 00g–00j und 06d. Sie ist ein KNOPF
   und sieht nicht danach aus: der Entwurf zeichnet sie als Textzeile mit
   Winkel, ohne Flaeche und ohne Rand. */
.kopfweg {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: var(--space-2);
  min-height: var(--kopfweg-hoehe);
  padding: 0;
  border: 0;
  background: none;
  color: var(--raum-fliess);
  font-family: var(--font-body);
  font-size: var(--schrift-zeile);
  font-weight: var(--gewicht-kraeftig);
  cursor: pointer;
}

/* EIGENE KLASSE, NICHT `.ikone--winkel`: die gehoert dem Winkel nach RECHTS
   am Ausgang des Kontobildschirms (Artboard 43). Eine gemeinsame Regel haette
   diesem Zeichen hier eine Groesse gegeben — und damit dem anderen dort, ohne
   dass es jemand gemessen haette. */
.ikone--kopfweg {
  width: var(--kopfweg-zeichen);
  height: var(--kopfweg-zeichen);
  flex: none;
}

/* Der Fussblock: Hauptknopf, Nebenweg, Fusszeile — in dieser Reihenfolge und
   am unteren Rand. Die beiden unteren Plaetze behalten ihre Hoehe, auch wenn
   sie leer sind (siehe --anmeldefuss-note im Token-Block). */
.anmeldefuss {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: auto;
}

.anmeldefuss__neben {
  display: flex;
  flex-direction: column;
  min-height: var(--btn-hoehe-ghost);
}

.anmeldefuss__note {
  margin: 0;
  min-height: var(--anmeldefuss-note);
  text-align: center;
}

/* Der Hinweiskasten mit Zeichen links. Dieselbe Flaeche und derselbe Rand wie
   jedes andere Blatt der App (--cs-fill-1 / --cs-line-2), nur mit dem
   groesseren Radius, den der Entwurf diesen Kaesten gibt. */
.anmeldekasten {
  display: flex;
  gap: var(--space-3);
  padding: var(--anmeldekasten-polster-y) var(--anmeldekasten-polster-x);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--anmeldekasten-radius);
  background: var(--cs-fill-1);
}

/* Der WARNENDE Kasten (Artboard 00j, das Stundenlimit). Flaeche und Rand aus
   dem Warnton — und ausdruecklich nicht aus Terracotta: das Limit ist ein
   Zustand, keine Aktion (Designspec Kap. 9). */
.anmeldekasten--warn {
  border-color: var(--warn-icon);
  background: var(--warn-flaeche);
}

.anmeldekasten__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  color: var(--raum-fliess);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
}

.anmeldekasten__kopf {
  color: var(--raum-text);
}

.ikone--brief,
.ikone--uhr,
.ikone--schloss-klein {
  width: var(--anmeldekasten-zeichen);
  height: var(--anmeldekasten-zeichen);
  flex: none;
  color: var(--raum-text-hell);
}

.anmeldekasten--warn .ikone--uhr {
  color: var(--warn-icon);
}

/* Die Warnzeile unter einem Feld (00d, 00f). Sie steht im Platz, den
   `.einstieg__meldung` ohnehin frei haelt — sie schiebt nichts. */
.warnzeile {
  display: flex;
  gap: var(--space-2);
  margin: 0;
  color: var(--warn-icon);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
  text-align: left;
}

.warnzeile .ikone {
  width: var(--icon-klein);
  height: var(--icon-klein);
  flex: none;
}

/* --- 00, 00d, 00e, 00f, 00k: der Einstieg --- */

/* Der Inhalt steht MITTIG ueber der ganzen Hoehe, der Aktionsblock am Fuss —
   genau so zeichnet es der Entwurf (`flex:1` auf dem Mittelteil,
   `margin-top:auto` auf dem Fuss). */
.einstieg {
  flex: 1;
  gap: var(--space-3);
}

.einstieg__mitte {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
}

.einstieg__marke {
  display: block;
  width: var(--einstieg-marke);
  height: var(--einstieg-marke);
  border-radius: var(--einstieg-marke-radius);
  margin-bottom: var(--space-3);
}

.einstieg__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--start-titel);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
  letter-spacing: var(--laufweite-heading);
}

.einstieg__frage {
  margin: 0 0 var(--space-2);
}

/* Das Feld traegt auf 00 den AKZENTRAHMEN des Entwurfs: es ist die eine
   Stelle, an der etwas eingegeben wird, und der Rahmen sagt genau das. Er ist
   eine Markierung, keine Flaeche — Terracotta bleibt der Aktion. */
.einstieg__feld {
  align-self: stretch;
  border-color: var(--einstieg-feld-rand);
  text-align: center;
}

/* Waehrend des Versands (00e) tritt das Feld zurueck: der Entwurf nimmt ihm
   Rahmen und Tinte, weil daran gerade nichts zu aendern ist. */
.einstieg__feld[disabled] {
  border-color: var(--blatt-rand);
  background: var(--cs-fill-1);
  color: var(--raum-text-gedaempft);
}

/* Bei abgewiesener Adresse (00d) traegt es den Warnton — Rand UND Flaeche,
   wie der Entwurf sie setzt. Als MODIFIKATOR am Feld und nicht als Regel am
   Stand der Buehne: dasselbe Feld steht auf 00l, und dort traegt die Buehne
   keinen Stand (00l ist ein eigener Bildschirm, kein Zustand von 00). */
.feld--warn {
  border-color: var(--warn-icon);
  background: var(--warn-flaeche);
}

/* Der Platz der Meldung. Er steht auch leer (siehe Kopf dieses Abschnitts). */
.einstieg__meldung {
  align-self: stretch;
  display: flex;
  min-height: var(--einstieg-meldung-hoehe);
}

.einstieg__zusicherung {
  align-self: stretch;
  margin: 0;
  text-align: center;
}

/* Der kleine Kreisel im Knopf von 00e und in der Meldung von 00g. Er ist
   dasselbe Bauteil an zwei Stellen; die Farbe erbt er. */
.kreisel {
  width: var(--kreisel-mass);
  height: var(--kreisel-mass);
  flex: none;
  border: var(--kreisel-strich) solid var(--cs-line-4);
  border-top-color: currentColor;
  border-radius: var(--radius-pille);
  animation: kreisel-dreht var(--anlage-ring-dauer) linear infinite;
}

@keyframes kreisel-dreht {
  to {
    transform: rotate(360deg);
  }
}

/* --- 00b, 00c, 00g, 00h, 00i, 00j: das Postfach --- */

.postfach {
  flex: 1;
  gap: var(--space-3);
}

.postfach__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.postfach__an {
  margin: 0 0 var(--space-2);
}

/* Die vier Kaestchen. Das Feld darueber ist UNSICHTBAR, aber bedienbar: es
   deckt die Reihe vollstaendig ab, damit ein Tipp irgendwo auf die Kaestchen
   die Tastatur oeffnet. `opacity:0` statt `display:none` — ein verstecktes
   Feld ist nicht fokussierbar, und dann koennte niemand tippen. */
.ziffern {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--ziffer-luecke);
}

.ziffern__kasten {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--ziffer-hoehe);
  border: var(--karte-rand) solid var(--cs-line-4);
  border-radius: var(--ziffer-radius);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-family: var(--font-heading);
  font-size: var(--ziffer-schrift);
}

.ziffern__kasten[data-dran='ja'] {
  border: var(--ziffer-dran-rand) solid var(--color-accent);
  background: var(--cs-accent-tint);
}

/* Abgewiesener Code (00c): alle vier tragen den Warnton. */
.ziffern[data-falsch='ja'] .ziffern__kasten {
  border-color: var(--warn-icon);
  background: var(--warn-flaeche);
}

/* Gesperrter Code (00i): die Reihe tritt ganz zurueck — hier ist nichts mehr
   einzutippen. Der Stand haengt am BEHAELTER und nicht am `disabled` des
   Feldes: das Feld steht im Baum NACH den Kaestchen, und ein
   Geschwisterwaehler zeigt nur nach vorn. */
.ziffern[data-gesperrt='ja'] .ziffern__kasten {
  border-color: var(--cs-line-2);
  background: var(--cs-fill-1);
  color: var(--cs-text-off);
}

.ziffern__feld {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  background: none;
  color: transparent;
  font-size: var(--ziffer-schrift);
  text-align: center;
  caret-color: transparent;
  opacity: 0;
  cursor: text;
}

/* Die Zeile unter den Kaestchen. Sie ist NIE leer: Gueltigkeit, Pruefung oder
   die benannte Absage — ein stummes Feld gibt es hier nicht. */
.codemeldung {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0;
  min-height: var(--einstieg-meldung-hoehe);
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
  text-align: center;
}

.codemeldung--warn {
  justify-content: flex-start;
  color: var(--warn-icon);
  text-align: left;
}

.codemeldung .kreisel {
  color: var(--color-accent);
}

.codemeldung--warn .ikone {
  width: var(--icon-klein);
  height: var(--icon-klein);
  flex: none;
}

/* --- 00l: der Umstieg --- */

.umstieg {
  flex: 1;
  gap: var(--space-3);
  padding-top: var(--space-3);
}

.umstieg__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* --- 06b: die Botpruefung --- */

.botcheck {
  flex: 1;
  gap: var(--space-3);
}

.botcheck__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Das Kaestchen ist die ganze Zeile: der Entwurf zeichnet eine Flaeche mit
   Rand, in der links das Quadrat und rechts der Satz steht. Angetippt wird
   die Zeile, nicht das 26-px-Quadrat — auf einem Handy trifft niemand
   zuverlaessig 26 px. */
.botcheck__haken {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: calc(var(--btn-hoehe) + var(--space-8));
  padding: 0 var(--anmeldekasten-polster-x);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--anmeldekasten-radius);
  background: var(--cs-fill-1);
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--schrift-fliess);
  text-align: left;
  cursor: pointer;
}

.botcheck__kasten {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--anlage-schritt-zeichen);
  height: var(--anlage-schritt-zeichen);
  flex: none;
  border: var(--karte-rand) solid var(--cs-line-4);
  border-radius: var(--radius-sm);
}

/* GESETZT heisst Terracotta, und hier ist es richtig: der Haken IST die
   Aktion dieses Bildschirms. */
.botcheck__kasten[data-gesetzt='ja'] {
  border-color: var(--color-accent);
  background: var(--cs-accent-tint);
  color: var(--color-accent);
}

.botcheck__kasten .ikone--haken {
  width: var(--icon-klein);
  height: var(--icon-klein);
}

.botcheck__fussnote {
  margin: 0;
}

/* --- 06c, 06d, 06e, 06f: die vier Anlagezustaende --- */

.anlage {
  flex: 1;
  gap: var(--space-3);
}

/* 06c steht MITTIG und ohne jeden Knopf — es gibt hier nichts zu
   entscheiden. */
.anlage--laeuft {
  justify-content: center;
  gap: var(--space-6);
}

.anlage__ring {
  width: var(--anlage-ring);
  height: var(--anlage-ring);
  border: var(--anlage-ring-strich) solid var(--cs-accent-disabled);
  border-top-color: var(--color-accent);
  border-radius: var(--radius-pille);
  animation: kreisel-dreht var(--anlage-ring-dauer) linear infinite;
}

.anlage__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.anlage__titel--fertig {
  text-align: center;
}

.warnscheibe {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--warnscheibe-mass);
  height: var(--warnscheibe-mass);
  flex: none;
  border: var(--warnscheibe-rand) solid var(--warn-icon);
  border-radius: var(--radius-pille);
  background: var(--warn-flaeche);
  color: var(--warn-icon);
}

.warnscheibe .ikone {
  width: var(--warnscheibe-zeichen);
  height: var(--warnscheibe-zeichen);
}

/* Der Angabenkasten von 06d: was behalten wurde, Zeile fuer Zeile. */
.anlage__angaben {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--anmeldekasten-polster-y) var(--anmeldekasten-polster-x);
  border: var(--karte-rand) solid var(--cs-line-1);
  border-radius: var(--anlage-angaben-radius);
  background: var(--cs-fill-1);
}

.anlage__zeile {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--anlage-angaben-schrift);
}

.anlage__etikett {
  color: var(--raum-text-hell);
}

.anlage__wert {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

/* Die drei Schrittzeilen von 06e. Sie sind eine BILANZ und keine Liste zum
   Antippen — ohne Flaeche, ohne Rand, ohne Winkel. */
.anlage__schritte {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.anlage__schritt {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--anlage-schritt-hoehe);
  color: var(--raum-text);
  font-size: var(--schrift-fliess);
}

.anlage__schritt .ikone {
  width: var(--anlage-schritt-zeichen);
  height: var(--anlage-schritt-zeichen);
  flex: none;
  color: var(--gruen-icon);
}

/* Was noch fehlt, traegt den Warnton und ein kraeftigeres Gewicht — es ist
   die eine Zeile, auf die es gerade ankommt. */
.anlage__schritt--offen {
  color: var(--warn-icon);
  font-weight: var(--gewicht-kraeftig);
}

.anlage__schritt--offen .ikone {
  color: var(--warn-icon);
}

/* Die Scheibe von 06f: der eben gewaehlte Avatar, mittig. */
.anlage__scheibe {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-2);
}

.anlage--fertig .ikone--auto {
  width: var(--anmeldekasten-zeichen);
  height: var(--anmeldekasten-zeichen);
  flex: none;
  color: var(--gruen-icon);
}


/* --------------------------------------------------------------------------
 * HIER STANDEN DIE REGELN DES ALTZUGANGS — ENTFERNT MIT WI-0302
 *
 * `.rueckwegseite*`, `.wortkarte*`, `.feld--wortfolge`, `.wortfolge__*`
 * (Artboards 03 und 04) und `.elternseite*` (Artboards 05 und 06). HANDOFF
 * §21.3 fuehrt 03 und 04 als REMOVED, §23.1 nimmt 05 und 06 mit.
 * ------------------------------------------------------------------------ */

/* --------------------------------------------------------------------------
 * Scannen
 * ------------------------------------------------------------------------ */

/* DIE SCANSEITE IN DER REIHENFOLGE DES ENTWURFS (Artboard 07, WI-0110).
 *
 * Von oben nach unten: Hinweispille — Sucher (236 px) — Warnzeile —
 * Schutzzusage — Ausloeser, unten verankert. Im Rahmen liegen nur noch
 * Livebild, Silhouette und die vier Eckwinkel.
 *
 * Vorgeschichte in einem Absatz: WI-0049 liess den Sucher die freie Hoehe
 * nehmen (Designspec Kap. 10.3 Punkt 3, „keine feste Hoehe, wo das Geraet
 * mehr hergibt"). Diese Auflage ist am 30.08. zurueckgezogen — sie war eine
 * Entscheidung ueber PLATZ, und der Einwand dagegen ist einer ueber den ZWECK:
 * das Bild muss auf die Karte passen (siehe --sucher-hoehe oben).
 *
 * `gap` steht auf 0, und die Abstaende stehen als Rand an den Teilen. Der
 * Entwurf setzt sie einzeln (14 / 28 / 10 px); ein gemeinsamer Zwischenraum
 * haette jeden davon um denselben Betrag verschoben. */
.scan {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
  /* Bezugsrahmen fuer das Kennzeichen-Blatt, das die ganze Seite abdeckt. */
  position: relative;
}

/* Der Sucher: das Mass steht im Entwurf und nicht im Fenster. `flex: none`
 * gehoert dazu — ohne es zoege ein Flex-Elternteil den Kasten wieder auf und
 * die 236 px waeren nur noch ein Wunsch. */
.sucher {
  position: relative;
  flex: none;
  width: 100%;
  height: var(--sucher-hoehe);
  margin-top: var(--sucher-abstand-oben);
  border-radius: var(--sucher-rundung);
  background: var(--sucher-flaeche);
  overflow: hidden;
}

/* DER RAHMEN AUF `07b` SITZT HOEHER (Artboard 07b: `margin-top:20px`).
 * Ueber ihm steht dort der Reihenstreifen und nicht nur die Pille; derselbe
 * `:has()`-Griff wie bei der Buehne der Reihe weiter unten — die Ausnahme
 * gilt NUR fuer den Zustand, der sie braucht, und `07` bleibt unberuehrt. */
.scan:has(.reihe) .sucher {
  margin-top: var(--sucher-abstand-oben-reihe);
}

/* --------------------------------------------------------------------------
 * DER SCAN-ZAEHLER (WI-0426, Artboards 07n/07c/07d/07g/07o/07w)
 *
 * Eine Zeile zwischen Pille und Rahmen: Balken 96 x 4, `{count}/{total}`,
 * „Scans übrig". Er ist eine ANZEIGE und keine Aktion — kein Zeiger, kein
 * Tippziel. Die Farbe traegt der Zustand: knapp, leer und wartend in
 * Terracotta-Warnton, unbekannt gedaempft; Balken und Zahl erben sie.
 * ------------------------------------------------------------------------ */
.scan-zaehler {
  display: flex;
  align-items: center;
  align-self: center;
  gap: var(--zaehler-fuge);
  margin-top: var(--zaehler-abstand-oben);
  min-height: var(--zaehler-hoehe);
  font-size: var(--zaehler-schrift);
  font-weight: 700;
  color: var(--cs-text-mute);
  pointer-events: none;
  user-select: none;
}

.scan-zaehler[data-scan-zaehler='07c'],
.scan-zaehler[data-scan-zaehler='07d'],
.scan-zaehler[data-scan-zaehler='07g'],
.scan-zaehler[data-scan-zaehler='07w'] {
  color: var(--cs-warn);
}

.scan-zaehler[data-scan-zaehler='07o'] {
  color: var(--cs-text-dim);
}

.scan-zaehler__leiste {
  position: relative;
  flex: none;
  width: var(--zaehler-leiste-b);
  height: var(--zaehler-leiste-h);
  border-radius: var(--radius-pille);
  background: var(--zaehler-spur);
  overflow: hidden;
}

.scan-zaehler__fuellung {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: inherit;
  background: currentColor;
  transition: width var(--zaehler-rollen) ease-out;
}

.scan-zaehler__zahl {
  font-variant-numeric: tabular-nums;
}

/* Nach einer neuen Karte rollt die Zahl einmal von oben herein. */
.scan-zaehler__zahl--rollt {
  display: inline-block;
  animation: scan-zaehler-rollt var(--zaehler-rollen) ease-out;
}

@keyframes scan-zaehler-rollt {
  from {
    transform: translateY(-60%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

/* 07o: der Stand ist nicht geladen — eine Platzhalterpille statt der Zahl. */
.scan-zaehler__platzhalter {
  display: inline-block;
  width: var(--zaehler-platzhalter-b);
  height: var(--zaehler-platzhalter-h);
  border-radius: var(--radius-pille);
  background: var(--zaehler-platzhalter);
}

@media (prefers-reduced-motion: reduce) {
  .scan-zaehler__fuellung {
    transition: none;
  }
  .scan-zaehler__zahl--rollt {
    animation: none;
  }
}

/* Die Hinweispille steht UEBER dem Rahmen, nicht darin (Artboard 07). Im
 * Rahmen war sie eine der Sachen, die dem Livebild Flaeche wegnahmen; der
 * Entwurf zaehlt abschliessend auf, was drinsteht, und sie ist nicht dabei. */
.scan > .hinweis-pille {
  margin-bottom: var(--pille-abstand-unten);
}

/* SAFE AREAS: bis WI-0417 trug der Sucher als einziger Bildschirm den
 * Systemrand selbst (WI-0049/WI-0110) — und alle anderen lagen in der
 * iOS-App unter der Statusleiste. Seitdem polstert `.app` mit `--sicher-*`
 * fuer JEDEN Bildschirm; hier stuende er doppelt. */
.app__buehne[data-bildschirm='scannen'] {
  /* 18 px oben wie im Entwurf (Artboard 07: Inhaltsspalte `padding: 16px 18px`,
     gemessen 18 px ueber der ersten Kante). Der allgemeine --buehne-oben von
     26 px war die groesste Abweichung dieses Bildschirms im Befund
     (`inhalt_oben`, docs/entwurfs-vergleich.md). */
  padding-top: var(--space-4);
}

/* DER KONTOBEREICH FAENGT HOEHER AN (WI-0331, Artboard 43).

   Dieselbe Bauart und derselbe Grund wie beim Sucher darueber: `--buehne-oben`
   ist mit 26 px der gemessene Mittelwert ueber alle Bildschirme, und 43 liegt
   nicht in seiner Naehe — das Brett setzt seine Inhaltsspalte auf
   `padding: 12px 22px 0`. Solange die Seite mit dem Kopf anfing, waren das
   13 px Abstand im Merkmal `inhalt_oben`; seit der Kopfweg (`‹ Zurück`) davor
   steht, kommt seine halbe Zeilenhoehe dazu und der Abstand verdoppelte sich.
   Der Weg ist gezeichnet, der Abstand war es nicht.

   13,2 px (`--space-3`) statt 12: die Abstandsleiter kennt keine 12, und ein
   Mass neben ihr waere eine zweite Leiter. 1,2 px liegen weit innerhalb der
   Toleranz, mit der dieser Vergleich misst.

   NUR 43 UND SEIN BLATT. Die Regel haengt am Bildschirm und nicht an
   `--buehne-oben` — die uebrigen Bildschirme bleiben unberuehrt
   (Scope-Lock). Der Fussfreiraum bleibt, wie er ist: die Tableiste steht auf
   43 ohnehin nicht, und `--buehne-unten` traegt ihn fuer alle.

   WI-0357: `43h` (die Sprachwahl) zeichnet dieselbe Inhaltsspalte
   (`padding: 12px 22px`) mit demselben Kopfweg davor — gemessen 40 statt 13 px
   `inhalt_oben` ohne diese Zeile. */
.app__buehne[data-bildschirm='konto'],
.app__buehne[data-bildschirm='konto_sprache'] {
  padding-top: var(--space-3);
}

/* DIE MASSE DER ABLAUFSEITEN AUF DER SCAN-STRECKE (WI-0068).
 *
 * Der Entwurf setzt die Inhaltsspalte dieser fuenf Bildschirme auf 26–30 px
 * Seitenrand und verankert den Aktionsblock 30 px ueber der Unterkante; die
 * drei Erkennungs-Seiten beginnen 56 px unter dem Kopf. Die Buehne traegt
 * sonst ueberall --space-4 (17,6 px) — gemessen waren das 9 bis 10 px zu
 * wenig auf jeder Seite. Hier stehen die Masse je Bildschirm, damit die
 * uebrigen 40 Bildschirme davon unberuehrt bleiben (SCOPE-LOCK). */
.app__buehne[data-bildschirm='scan_laeuft'],
.app__buehne[data-bildschirm='scan_fehler'],
.app__buehne[data-bildschirm='scan_qr'],
/* Artboard 25 IST dieselbe Seite (HANDOFF §6 Zeile 25: „Same stage as 08") —
   also auch dieselben Masse. Sie steht hier in derselben Regel und nicht in
   einer zweiten daneben (WI-0096). */
.app__buehne[data-bildschirm='verbinden'] {
  padding: calc(var(--space-6) + var(--space-8)) var(--space-6) var(--space-8);
}

/* DIE BILDSCHIRME OHNE TABLEISTE brauchen ihren Fussfreiraum nicht (HANDOFF
   §4.3: die Leiste ist auf allen Duell-Aufsetz-Bildschirmen ausgeblendet).
   `--buehne-unten` haelt 96 px fuer eine Leiste frei, die dort gar nicht
   steht — gemessen waren das auf dem Aufsetzen 130 px unter der Falz, waehrend
   der Entwurf den Bildschirm auf feste 793 px zeichnet (WI-0096). */
.app__buehne[data-bildschirm='aufsetzen'],
.app__buehne[data-bildschirm='deckbau'],
.app__buehne[data-bildschirm='einsatz'],
/* WI-0212: der Wiederfund traegt die Leiste ebenso wenig — die Artboards 13c
   und 13d zeichnen ihren Aktionsblock unten verankert auf 24 px und nichts
   darunter. Gemessen waren mit dem allgemeinen Fussfreiraum 32 px (13c) und
   63 px (13d) unter der Falz, auf Bildschirmen, die der Entwurf auf feste
   793 px zeichnet. */
.app__buehne[data-bildschirm='doppelfund'] {
  padding-bottom: var(--space-6);
}

/* Der Deckbau faengt hoeher an als die uebrigen — Artboard 28 setzt ihn auf
   18 px, und das Kartenraster darunter braucht jede Zeile. */
.app__buehne[data-bildschirm='deckbau'] {
  padding-top: var(--space-4);
}

/* Das Aufsetzen traegt VIER Gruppen (Bezugsart, Einsatz, Serie, Groesse) auf
   einem Bildschirm, den der Entwurf mit drei zeichnet. Der allgemeine Abstand
   der Buehne (13 px je Zwischenraum) summiert sich dabei auf ueber hundert
   Pixel — der Entwurf setzt zwischen Versalzeile und Gruppe 8 px und zwischen
   den Gruppen 16 px. Deshalb hier die engere Leiter (WI-0096). */
.app__buehne[data-bildschirm='aufsetzen'] > .gestapelt {
  gap: var(--space-2);
}

.app__buehne[data-bildschirm='aufsetzen'] .aktionsblock {
  padding-top: var(--space-2);
}

.app__buehne[data-bildschirm='auswahl'],
.app__buehne[data-bildschirm='korrektur'] {
  padding-left: var(--space-6);
  padding-right: var(--space-6);
  padding-bottom: var(--space-8);
}

/* ARTBOARD 11c — DIE EINZIGE SEITE DER SCAN-STRECKE, DIE ROLLT (WI-0176).
 *
 * Der Entwurf zeichnet sie auf feste 793 px: Ueberschrift, Suchpille und
 * Aktionsblock stehen, und NUR die Typenliste dazwischen rollt
 * (`flex:1;min-height:0;overflow:auto`). Damit das aufgeht, muss die Buehne
 * bei der Fensterhoehe enden — `.app` traegt sonst nur `min-height`, waechst
 * also mit dem Inhalt, und eine Marke mit zwanzig Typen schoebe „Diesen Typ
 * nehmen" unter die Bildkante. Genau das verbietet Designspec 10.3 Punkt 1.
 *
 * Die Seitenmasse sind die des Artboards (`padding:24px 26px 0`, Aktionsblock
 * 30 px ueber der Kante) — dieselbe Leiter wie auf 11 und 12 daneben. */
.app__buehne[data-bildschirm='typen'] {
  max-height: var(--sicher-hoehe);
  padding: var(--space-6) var(--space-6) var(--space-8);
}

/* Das Livebild fuellt den Rahmen und liegt UNTER den Eckwinkeln und der
 * Einpasshilfe — deshalb absolut, nicht im Fluss.
 *
 * ACHTUNG, `object-fit: cover` IST HIER NICHT NUR GESCHMACK: `cover` fuellt
 * den Kasten und schneidet das hochkante Sensorbild dafuer oben und unten ab
 * (seit WI-0110 der Regelfall). Der Nutzer rahmt also einen AUSSCHNITT. Die
 * Aufnahme in public/js/camera.js rechnet genau diesen Ausschnitt nach und
 * zeichnet nur ihn auf die Leinwand — sonst kommt ein anderes Bild an als das
 * gerahmte (zwei Drittel Wand, Auto am unteren Rand).
 *
 * Wer `object-fit`, die Kasten-Masse oder die angeforderte Aufloesung
 * aendert, aendert `coverAusschnitt()` in camera.js mit. Sucher und Aufnahme
 * brauchen DIESELBE Geometrie.
 *
 * Deshalb steht hier `inset: 0` und keine eigene Groesse: das Video ist immer
 * genau der Kasten. Bei jeder Aenderung der Sucherform — kleiner und hochkant,
 * dann volle Hoehe (WI-0049), 340 px gedrungen (WI-0110), jetzt die 236 px des
 * Bretts (WI-0315) — wanderte die
 * Aufnahme von allein mit, weil sie das Video zur Laufzeit misst. Wer dem
 * Video hier eine ANDERE Flaeche gibt als dem Sucher, bricht genau diese
 * Kopplung. */
.sucher__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Dieselbe Flaeche wie der Rahmen — sie ist nur sichtbar, solange noch kein
     Bild da ist, und zwei Toene uebereinander waeren eine Kante, die der
     Entwurf nicht zeichnet. */
  background: var(--sucher-flaeche);
}

/* Die Einpasshilfe: sie zeigt, wo das Auto im Bild sitzen soll. Sie liegt
 * ueber dem Videobild, aber sie ist KEIN Bedienelement — `pointer-events:
 * none` sorgt dafuer, dass jeder Druck durch sie hindurch beim Ausloeser
 * ankommt, und sie liegt unter Pille, Fusszeile und dem Kennzeichen-Blatt
 * (z-index 1), damit sie keinen Hinweis- oder Fehlertext stoert. Auf die
 * Aufnahme hat sie keinen Einfluss: gezeichnet wird das <video>, nicht der
 * Sucher. */
.sucher__einpass {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--einpass-breite);
  opacity: var(--einpass-deckkraft);
  pointer-events: none;
}

.sucher__einpass .silhouette {
  /* Die Hoehe kommt aus dem viewBox-Verhaeltnis (120:44), nicht aus einem
     Elternkasten — sonst waere sie null. Farbe und Schein braucht die
     Hilfslinie nicht zu regeln: ausserhalb einer Karte steht --r-g auf der
     neutralen Vorstufe, und den Schein traegt nur die Fotoflaeche. */
  height: auto;
}

.sucher__winkel {
  position: absolute;
  width: var(--sucher-winkel);
  height: var(--sucher-winkel);
  border: var(--sucher-winkel-strich) solid var(--sucher-farbe);
}

/* 16 px Innenabstand und eine gerundete Aussenecke — Artboard 07. Bis WI-0110
   hingen sie am Polster des Rahmens (17,6 px); das Polster ist weg, seit im
   Rahmen nichts mehr im Fluss steht. */
.sucher__winkel--ol {
  top: var(--sucher-winkel-abstand);
  left: var(--sucher-winkel-abstand);
  border-right: 0;
  border-bottom: 0;
  border-radius: var(--sucher-winkel-rundung) 0 0 0;
}
.sucher__winkel--or {
  top: var(--sucher-winkel-abstand);
  right: var(--sucher-winkel-abstand);
  border-left: 0;
  border-bottom: 0;
  border-radius: 0 var(--sucher-winkel-rundung) 0 0;
}
.sucher__winkel--ul {
  bottom: var(--sucher-winkel-abstand);
  left: var(--sucher-winkel-abstand);
  border-right: 0;
  border-top: 0;
  border-radius: 0 0 0 var(--sucher-winkel-rundung);
}
.sucher__winkel--ur {
  bottom: var(--sucher-winkel-abstand);
  right: var(--sucher-winkel-abstand);
  border-left: 0;
  border-top: 0;
  border-radius: 0 0 var(--sucher-winkel-rundung) 0;
}

/* DIE HINWEISPILLE — und sie ist eine PILLE, kein freier Satz (WI-0315).
 *
 * Artboard 07 malt sie
 * `border:1px solid rgba(255,225,208,.3); font-size:13.5px; font-weight:700`.
 * In der App stand hier KEIN Rand, 12 px und Gewicht 500 — nebeneinander
 * gelegt war das der zweite sichtbare Unterschied dieses Bildschirms nach der
 * Rahmenhoehe: ohne Rand und bei halbem Gewicht schwebt der Satz ueber der
 * Seite, statt in einer Kapsel zu sitzen.
 *
 * WARUM DER MERKMALSVERGLEICH AUCH DAS NICHT GEMELDET HAT — und das ist
 * dieselbe Luecke wie bei der Rahmenhoehe, nur an einer anderen Stelle:
 * `schriftgroessen` vergleicht als LEITER (je Entwurfsgroesse die
 * naechstliegende der App), und 13,5 px gibt es auf diesem Bildschirm schon
 * — in der Warnzeile. Dass die PILLE 12 px traegt, faellt damit nicht auf.
 * `schriftgewichte` zaehlt, wieviele Entwurfsgewichte in der App FEHLEN; die
 * 500 der Pille ist ein zusaetzliches und kein fehlendes. Beide Merkmale
 * standen auf „sitzt", waehrend die Pille falsch stand.
 *
 * Diese Pille gehoert `07`/`07b` allein: `.hinweis-pille` hat genau eine
 * Fundstelle (`scannenBildschirm()` in app.js). Kein anderer Bildschirm
 * bewegt sich hier mit. */
.hinweis-pille {
  flex: none;
  align-self: center;
  background: var(--tableiste-flaeche);
  border: var(--pille-strich) solid var(--pille-rand);
  /* #ffe1d0 wie im Entwurf (Artboard 07). --raum-text (#f5ead8) stand hier,
     solange die Pille im Rahmen lag; ausserhalb traegt sie den Akzentton, den
     der Entwurf ihr gibt — derselbe wie an den vier Eckwinkeln. */
  color: var(--color-accent-200);
  border-radius: var(--radius-pille);
  padding: var(--space-2) var(--space-4);
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-kraeftig);
}

/* DIE FUSSZEILE STEHT UNTER DEM RAHMEN, NICHT MEHR DARIN (WI-0049).
 *
 * Drin war sie ein Band am unteren Sucherrand — und lief bei zwei Zeilen in
 * die beiden unteren Eckwinkel hinein, weil die auf derselben Hoehe an den
 * Seiten kleben. Mehr Innenabstand haette den Text nur schmaler und damit
 * dreizeilig gemacht: dieselbe Kollision, eine Zeile spaeter.
 *
 * Ausserhalb des Rahmens kann sie beliebig umbrechen, ohne irgendetwas zu
 * treffen — die Schutzzusage steht deshalb ganz ohne Reserve im Sucher da,
 * und der Sucher gewinnt das Band als Bildflaeche dazu.
 *
 * Der Entwurf zeichnet sie nicht; die Produktspec 4.2 verlangt sie („ein
 * Hinweis, dass das Kennzeichen automatisch unkenntlich gemacht wird"). Sie
 * steht deshalb weiter da, aber unter der Warnzeile und ausserhalb des
 * Rahmens — dort stoert sie keine der Sachen, die der Entwurf aufzaehlt.
 *
 * WI-0328 — SCHILD UND SATZ STEHEN AUF EINER GRUNDLINIE.
 *
 * Gemeldet war (Bildschirmfoto der laufenden App, 10.10.2026): „Schild-Symbol
 * am linken Rand, Text zweizeilig zentriert, nicht ausgerichtet". Die Ursache
 * ist `align-items: center` bei umbrechendem Text: der Mittelpunkt des
 * Schildes liegt dann zwischen den beiden Zeilen, und weil der Textblock
 * fast die ganze Spalte fuellt, sitzt das Schild optisch am Rand.
 *
 * `baseline` legt es stattdessen auf die Grundlinie der ERSTEN Zeile — die
 * Grundlinie einer eingebundenen Grafik ist ihre Unterkante, das Schild steht
 * also auf der Linie, auf der auch der Satz steht. Das ist dieselbe
 * Ausrichtung, die das Brett der Warnzeile darueber gibt (dort faellt sie mit
 * `center` zusammen, weil der Satz einzeilig ist). Umbrechen darf sie
 * weiterhin: eine Zeile erzwingen hiesse, den Satz zu kuerzen, und er ist
 * eine Produktzusage aus 4.2 und kein Entwurfstext, den man kuerzen darf.
 * Seine Groesse behaelt das Schild dabei von selbst — `.ikone` traegt
 * `flex: none` und mit `--ikone--schild` ein eigenes Mass. */
.scan__fuss {
  /* WI-0395 — das Schild gehoert in den Textfluss. Als Flex-Zeile fuellte der
   * umbrechende Satz die ganze Spalte, und das Schild blieb allein am linken
   * Rand stehen (Foto 393x793). Als Inline-Grafik steht es direkt vor dem
   * ersten Wort, auf der Hoehe der ersten Zeile, und der Satz darf weiter
   * umbrechen und zentriert bleiben. */
  display: block;
  flex: none;
  margin-top: var(--space-2);
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-klein);
  text-align: center;
}

.scan__fuss .ikone {
  display: inline-block;
  margin-inline-end: var(--space-2);
  vertical-align: middle;
}

/* DIE WARNZEILE UNTER DEM SUCHER (Artboard 07, WI-0068).
 *
 * Der Entwurf zeichnet sie zwischen Sucher und Ausloeser, in --cs-warn und
 * mit dem Warndreieck davor. Sie fehlte bis hierher ganz — und sie ist der
 * einzige Satz auf der Strecke, der nichts ueber die App sagt, sondern ueber
 * die Strasse. Sie steht ausserhalb des Rahmens, aus demselben Grund wie die
 * Schutzzusage darunter (WI-0049): drin liefe sie in die Eckwinkel. */
.scan__warnung {
  display: flex;
  flex: none;
  /* 10 px unter dem Rahmen (Artboard 07: `padding: 10px 6px 0`). */
  margin-top: var(--space-2);
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  color: var(--warn-icon);
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-kraeftig);
  text-align: center;
}

.scan__warnung .ikone {
  width: var(--icon-mittel);
  height: var(--icon-mittel);
}

/* DER ZOOM-REGLER ZWISCHEN RAHMEN UND WARNZEILE (WI-0341, Brett `07`).
 *
 * WIEDER DA, UND ZWAR AUF ANSAGE. WI-0216 hat ihn gebaut und dabei selbst
 * gemeldet, dass das damalige Brett ihn nicht zeichnet; WI-0328 hat genau
 * diese Luecke gegen ihn entschieden. Der Export vom 12.10.2026 zeichnet ihn
 * auf `07` UND `07l`, und Rob hat am selben Tag entschieden, dass der Export
 * gewinnt. Der Grund von WI-0328 ist damit nicht ueberstimmt, sondern
 * weggefallen.
 *
 * GEZEICHNET SIND VIER TEILE, UND GENAU VIER STEHEN HIER: Spur, gefuellter
 * Teil, Griff und zwei Beschriftungen. Sie sind ECHTE Elemente und keine
 * `::-webkit-slider-*`-Pseudos — aus zwei Gruenden, und beide sind gemessen:
 * ein Pseudo-Element taucht in `document.querySelectorAll('*')` nicht auf,
 * also saehe der Merkmalsvergleich (tests/e2e/hilfe/merkmale.js) seine Farben
 * nicht, waehrend er sie auf der Brettseite sieht; und dieselben vier Teile
 * tragen quer eine ANDERE Achse, was mit zwei Herstellerpseudos je Richtung
 * vier Regelsaetze statt einem bedeutet haette.
 *
 * DAS BEDIENELEMENT BLEIBT TROTZDEM EIN `input[type=range]`. Es liegt
 * durchsichtig ueber den vier Teilen und traegt die ganze Bedienung: Daumen,
 * Maus, Tastatur, Name. Was man SIEHT, folgt ihm ueber `--zoom-anteil` — eine
 * Zahl, die der Eingabezweig in public/js/app.js auf den Streifen schreibt,
 * ohne die Buehne neu zu bauen (sonst risse der Neuaufbau den Zug unter dem
 * Daumen ab).
 *
 * DIE TRAGENDE ZAHL IST 44 UND NICHT 28: der Griff ist 28 px gross, die
 * Griffreihe darum 44 — die Ein-Daumen-Regel der Fabrik (Produktspec 4.0,
 * Designspec Kap. 10.3 Punkt 1), und das Brett zeichnet sie genau so.
 *
 * `flex: none` wie am Rahmen darueber: die Scanseite ist eine Flex-Spalte,
 * und ein zusammendrueckbarer Streifen waere bei knapper Hoehe zuerst weg. */
.scan__zoom {
  display: flex;
  flex: none;
  flex-direction: column;
  /* Brett `07`: `padding:8px 2px 0` am Streifen, Fuge 2 px. Der Abstand zum
     Rahmen steckt im Polster und nicht in einem Rand — so wie das Brett ihn
     setzt. */
  padding: var(--scan-zoom-polster);
  gap: var(--scan-zoom-luecke);
}

/* Die Griffreihe: 44 px hoch, und sie ist der Bezugsrahmen fuer die drei
   Teile darin. */
.scan__zoom-feld {
  position: relative;
  height: var(--scan-zoom-flaeche);
}

/* Die Spur ueber die ganze Breite, mittig in der Griffreihe. */
.scan__zoom-spur {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--scan-zoom-spur);
  margin-top: calc(var(--scan-zoom-spur) / -2);
  border-radius: var(--radius-pille);
  background: var(--cs-line-2);
}

/* Der gefuellte Teil waechst vom weiten Ende her — hochkant also von links.
   Das Brett zeichnet ihn in EINER Stellung (22 %); hier steht statt der
   gezeichneten Zahl der echte Stand der Linse. */
.scan__zoom-gefuellt {
  position: absolute;
  left: 0;
  width: var(--zoom-anteil, 0%);
  top: 50%;
  height: var(--scan-zoom-spur);
  margin-top: calc(var(--scan-zoom-spur) / -2);
  border-radius: var(--radius-pille);
  background: var(--scan-zoom-gefuellt);
}

/* Der Griff sitzt auf dem Ende des gefuellten Teils. `margin` zieht ihn um
   seinen halben Durchmesser zurueck, damit seine MITTE auf dem Wert steht und
   nicht seine Kante. */
.scan__zoom-griff {
  position: absolute;
  left: var(--zoom-anteil, 0%);
  top: 50%;
  width: var(--scan-zoom-griff);
  height: var(--scan-zoom-griff);
  margin: calc(var(--scan-zoom-griff) / -2) 0 0 calc(var(--scan-zoom-griff) / -2);
  border-radius: var(--radius-pille);
  background: var(--color-accent);
  border: var(--scan-zoom-ring) solid var(--scan-zoom-griff-ring);
  box-shadow: var(--scan-zoom-schatten);
  /* Reine Anzeige: der Daumen trifft das Feld darueber, nicht diesen Kreis. */
  pointer-events: none;
  box-sizing: border-box;
}

/* DAS ECHTE BEDIENELEMENT — durchsichtig, aber vollstaendig.
 *
 * `appearance: none` ist Voraussetzung und keine Geschmacksfrage: die
 * eingebaute Schiene bringt ihre eigene Dicke und Griffgroesse mit, und beide
 * sind von aussen nicht zu aendern. Was bleibt, ist die Trefferflaeche — und
 * die traegt der Griff mit seinen 44 px, damit ein Zug auch dort anfaengt, wo
 * der Daumen hinfaellt. */
.scan__zoom-regler {
  appearance: none;
  -webkit-appearance: none;
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

/* Webkit und Gecko brauchen GETRENNTE Regeln: ein Herstellerpseudo, das der
   Browser nicht kennt, macht die ganze Regel ungueltig — auch den Teil, den
   er kennt. Gezeichnet wird in beiden nichts; es geht allein um die
   Trefferflaeche. */
.scan__zoom-regler::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--scan-zoom-flaeche);
  height: var(--scan-zoom-flaeche);
  border: 0;
  background: transparent;
}

.scan__zoom-regler::-moz-range-thumb {
  width: var(--scan-zoom-flaeche);
  height: var(--scan-zoom-flaeche);
  border: 0;
  background: transparent;
}

/* Die beiden Enden des Wegs: `Weit` links, `Nah` rechts (Brett `07`).
   12,5 px in --cs-text-mute — dem Ton, den das Brett dort mit `#b5a992`
   zeichnet; gebunden wird an das Token und nicht an die Zahl. */
.scan__zoom-beschriftung {
  display: flex;
  justify-content: space-between;
}

.scan__zoom-ende {
  color: var(--raum-text-gedaempft);
  font-size: var(--scan-zoom-schrift);
  line-height: 1.2;
}

.ausloeser {
  width: var(--ausloeser);
  height: var(--ausloeser);
  /* `flex: none` haelt den Kreis rund: ohne es staucht ein Flex-Elternteil
     mit knapper Hoehe die Hoehe und nicht die Breite, und aus dem Knopf wird
     ein Ei. */
  flex: none;
  align-self: center;
  border-radius: var(--radius-pille);
  border: var(--ausloeser-rand) solid var(--color-accent-200);
  background: var(--color-accent);
  box-shadow: var(--btn-glow);
  cursor: pointer;
  padding: 0;
}

/* UNTEN VERANKERT UND MITTIG, WIE IM ENTWURF (Artboard 07, WI-0110).
 *
 * Bis hierher sass er unten RECHTS IM Rahmen (WI-0037): Rob hatte ihn im
 * Juli-Test mit dem Daumen nicht erreicht. Der Entwurf verankert ihn unten
 * und mittig, und dieses Item baut ihn so. `margin-top: auto` ist die
 * Verankerung — der Knopf sinkt an das untere Ende der Scanseite, egal wie
 * hoch das Fenster ist, statt auf einem festen Abstand zu sitzen.
 *
 * Faellt die Erreichbarkeit erneut auf, ist das ein BEFUND und ein eigenes
 * Item — nicht eine stille Rueckkehr nach unten rechts.
 *
 * Er steht damit ausserhalb des Rahmens und kann bauartbedingt weder Pille
 * noch Eckwinkel noch eine der beiden Zeilen darunter verdecken. Der
 * `z-index`-Kunstgriff aus WI-0012 (der Knopf lag im Rahmen unter dem absolut
 * gesetzten <video> und fing den Druck nicht mehr ab) wird hier nicht mehr
 * gebraucht: im Fluss der Seite liegt kein Videobild ueber ihm. */
.scan > .ausloeser {
  margin-top: auto;
}

.ausloeser[disabled] {
  opacity: var(--deaktiviert-deckkraft);
  cursor: progress;
}

/* 07d — DER AUSLOESER WIRD EIN PLUS (WI-0426). Der Akzentkreis bleibt, das
   Plus (30 px, 3 px Strich) steht darin. Er oeffnet das Kaufblatt 50
   (WI-0427). */
.ausloeser--plus {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--cs-on-accent);
  cursor: pointer;
}

.ausloeser--plus .ikone--plus {
  width: var(--ausloeser-plus);
  height: var(--ausloeser-plus);
}

/* 07g und 07w — DER AUSLOESER RUHT: grauer Kreis statt Akzent, kein Glanz.
   Er ist `disabled`, aber nicht durchscheinend wie der beschaeftigte Knopf —
   das Brett zeichnet ihn deckend. */
.ausloeser--ruht,
.ausloeser--ruht[disabled] {
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 1;
  background: var(--ausloeser-ruht-flaeche);
  border-color: var(--ausloeser-ruht-rand);
  box-shadow: none;
  color: var(--cs-text-3);
  cursor: default;
}

.ikone--ausloeser-kreisel {
  width: var(--ausloeser-kreisel);
  height: var(--ausloeser-kreisel);
  animation: kreisel-dreht var(--ausloeser-kreisel-dauer) linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .ikone--ausloeser-kreisel {
    animation: none;
  }
}

/* Der Satz unter dem Ausloeser: „Warte auf deine Karten" (07g) bzw. der
   Paketsatz (07w). Die Gruppe hat 10 px Fuge. */
.scan__ausloeser-satz {
  align-self: center;
  max-width: var(--ausloeser-satz-breite);
  margin: var(--ausloeser-satz-fuge) 0 0;
  font-size: var(--schrift-hinweis);
  font-weight: 700;
  line-height: var(--ausloeser-satz-zeile);
  text-align: center;
  color: var(--cs-text-mute);
}

.scan__ausloeser-satz--pakete {
  color: var(--text-hell);
}

/* --------------------------------------------------------------------------
 * Kennzeichen — Stufe 3 der Filterkette, ein Zustand von "Scannen"
 * ------------------------------------------------------------------------ */

/* DAS BLATT DECKT DIE SCANSEITE AB, NICHT MEHR NUR DEN RAHMEN (WI-0110).
 *
 * Es war ein Zustand DES SUCHERS und lag deshalb in ihm. Solange der Rahmen
 * rund 600 px hoch war, ging das auf. Mit den 236 px des Entwurfs geht es
 * nicht mehr (WI-0315; bei 340 px ging es schon nicht): Ueberschrift,
 * Vorschaubild, Hinweis und zwei Knoepfe brauchen
 * zusammen mehr als 200 px, und fuer das Bild blieben rund 60 uebrig. Genau
 * an der DARGESTELLTEN Groesse dieses Bildes rechnet kennzeichenRahmen() in
 * app.js die Tippstelle aufs Kennzeichen — ein Bild von 60 px Hoehe ist keine
 * Flaeche, auf der ein Daumen ein Kennzeichen trifft.
 *
 * Es bleibt ein Blatt und wird keine eigene Seite: der Weg, der Zustand und
 * der Ausstieg aendern sich nicht, nur der Kasten, den es abdeckt. Bezug ist
 * `.scan` (`position: relative` dort), und weil es das letzte Kind ist, liegt
 * es ueber Pille, Rahmen, Zeilen und Ausloeser. */
.kennzeichen {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--sucher-rundung);
  background: var(--blatt-flaeche);
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  justify-content: center;
}

/* DER KASTEN TRAEGT DIE FORM DER AUFNAHME — hier stand der gemeldete Fehler.
 *
 * VORHER: `width: 100%` am Kasten, `height: auto` am Bild. Der Kasten ist ein
 * Flusselement in einer Spalte, die kuerzer ist als ihr Inhalt, also wurde er
 * gestaucht (`flex-shrink`). Das Bild darin behielt seine volle Hoehe, und
 * `overflow: hidden` schnitt den Rest weg — auf 393x793 blieben von 430 Pixel
 * Bildhoehe 202 uebrig. Sichtbar war der obere Teil, UNTEN fehlte knapp die
 * Haelfte: genau die Meldung „im Foto war unten abgeschnitten".
 *
 * Doppelt falsch war es, weil die Tippstelle aufs Kennzeichen an der
 * DARGESTELLTEN Groesse des Kastens gerechnet wird (kennzeichenRahmen() in
 * app.js). Ein Tipp am unteren Bildrand landete damit nicht dort, wo das
 * Kennzeichen wirklich sitzt.
 *
 * JETZT: `aspect-ratio` traegt das Verhaeltnis der Aufnahme — als Zahl aus
 * dem Bild, gesetzt in app.js, nicht als Wert im Stilblatt. Der Kasten darf
 * schrumpfen (`min-height: 0`), aber weil das Verhaeltnis feststeht, geht die
 * Breite mit der Hoehe mit; `align-self: center` nimmt ihm die Dehnung auf
 * volle Spaltenbreite, `max-width: 100%` haelt ihn bei querformatigen
 * Aufnahmen im Blatt. Der Kasten huellt das Bild also immer genau ein: nichts
 * wird zugeschnitten, nichts laeuft ueber das Blatt hinaus, und
 * Tippstelle und Bildkoordinaten stimmen eins zu eins ueberein. */
.kennzeichen__bild {
  position: relative;
  aspect-ratio: var(--kz-verhaeltnis, 3 / 4);
  flex: 0 1 auto;
  align-self: center;
  min-height: 0;
  max-width: 100%;
  border-radius: var(--kz-bild-radius);
  overflow: hidden;
  background: var(--foto-flaeche);
  cursor: crosshair;
}

.kennzeichen__bild > canvas,
.kennzeichen__bild > img {
  display: block;
  width: 100%;
  height: 100%;
}

/* Der Rahmen sitzt in Bildanteilen — die vier Zahlen kommen aus der
 * Tippstelle, nicht aus dem Stilblatt. */
.kennzeichen__rahmen {
  position: absolute;
  left: var(--kz-x);
  top: var(--kz-y);
  width: var(--kz-b);
  height: var(--kz-h);
  border: var(--kz-rahmen-strich) solid var(--color-accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--btn-glow);
  /* Der Tipp gehoert dem Bild: `offsetX` bleibt so relativ zum Bildkasten,
   * auch wenn er auf einem Rahmen landet (WI-0434). */
  pointer-events: none;
}

/* WI-0434 — VORLAEUFIG: der Knopf, der einen vorgesetzten Rahmen entfernt.
 * Kein Artboard zeichnet ihn (Luecke in design/HANDOFF.md); gebaut im Stil
 * des Kreuzes oben links, nur aus vorhandenen Token. */
.kennzeichen__entfernen {
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(50%, -50%);
  width: var(--quer-kreuz);
  height: var(--quer-kreuz);
  display: grid;
  place-items: center;
  padding: 0;
  border: var(--pille-strich) solid var(--cs-line-2);
  border-radius: var(--radius-pille);
  background: var(--tableiste-flaeche);
  color: var(--color-accent);
  pointer-events: auto;
}

.kennzeichen__entfernen svg {
  width: var(--quer-kreuz-ikone);
  height: var(--quer-kreuz-ikone);
}

.kennzeichen__hinweis {
  color: var(--raum-fliess);
  font-size: var(--schrift-klein);
  text-align: center;
}

/* --------------------------------------------------------------------------
 * Die drei Erkennungs-Seiten (Artboards 08, 09, 10 — WI-0068)
 *
 * WAS SICH GEAENDERT HAT: es waren Blaetter am unteren Bildschirmrand. Der
 * Entwurf zeichnet sie als GANZE Seiten („Full page, not a sheet", HANDOFF §6
 * Zeile 08) — Buehne oben, Ueberschrift, Unterzeile, Schrittliste, und die
 * Aktionen unten verankert. Gefehlt haben dabei die Buehne, die Ueberschrift
 * in der Anzeigeschrift (der Merkmalsvergleich meldete auf `scan_laeuft`
 * „Rokkitt kommt gar nicht vor" und 17 px Abstand in der Groessenleiter) und
 * bei 08 der einzige Ausgang.
 * ------------------------------------------------------------------------ */

.lauf {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

/* Die 250-px-Buehne mit der 206-px-Scheibe darin. */
.lauf__buehne {
  position: relative;
  flex: none;
  width: var(--lauf-buehne);
  height: var(--lauf-buehne);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-6);
}

.lauf__ring {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--lauf-ring-farbe);
  animation: cs-ring var(--lauf-ring-dauer) ease-out infinite;
}

.lauf__ring[data-ring='2'] {
  animation-delay: 0.8s;
}

.lauf__ring[data-ring='3'] {
  animation-delay: 1.6s;
}

.lauf__scheibe {
  position: absolute;
  width: var(--lauf-scheibe);
  height: var(--lauf-scheibe);
  border-radius: var(--radius-pille);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--lauf-scheibe-flaeche);
  border: var(--karte-rand) solid var(--lauf-scheibe-rand);
}

/* Angehalten (Artboards 09 und 10): gestrichelter Rand in der Warnfarbe,
   keine Ringe, keine Bewegung. */
.lauf__buehne[data-art='halt'] .lauf__scheibe {
  background: var(--lauf-halt-flaeche);
  border-style: dashed;
  border-color: var(--lauf-halt-rand);
}

/* Das gezeichnete Auto in der Scheibe. Es ist dieselbe Silhouette wie die
   Einpasshilfe im Sucher — der Entwurf zeichnet auf beiden Bildschirmen
   denselben Umriss, und zwei Umrisse waeren zwei Wahrheiten. */
.lauf__spur {
  display: block;
  width: var(--lauf-spur);
}

/* DIE STRICHLUECKE STEHT IN DEN KEYFRAMES, NICHT AM ELEMENT (der Entwurf setzt
   sie am Element). Grund: ohne laufende Animation — abgeschaltete Bewegung,
   ein Browser ohne CSS-Animationen — bliebe die Luecke sonst auf ihrer
   Startlaenge stehen, und der Umriss waere dauerhaft unsichtbar. So herum
   steht er in Ruhe fertig da und wird von der Animation gezeichnet.
   (Im Referenzbild ist er trotzdem nicht zu sehen: der Bildvergleich setzt
   unendliche Animationen auf ihren ERSTEN Rahmen zurueck. Das Artboard zeigt
   dort aus demselben Grund dieselbe leere Scheibe — geprueft am 30.08.) */
.lauf__spur .silhouette {
  height: auto;
  stroke: var(--color-accent-400);
  animation: cs-trace var(--lauf-trace-dauer) ease-out infinite alternate;
}

/* Auf der angehaltenen Seite steht der Umriss grau und vollstaendig da. */
.lauf__spur--still .silhouette {
  stroke: var(--lauf-still-farbe);
  stroke-dasharray: none;
  stroke-dashoffset: 0;
  animation: none;
}

.lauf__glyphe {
  display: inline-flex;
  color: var(--lauf-still-farbe);
}

.lauf__glyphe .ikone--qr {
  width: var(--lauf-glyphe);
  height: var(--lauf-glyphe);
}

/* Der wandernde Lichtstrich (HANDOFF §14.2, Zeile 08). */
.lauf__strich {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--lauf-strich);
  background: var(--lauf-strich-verlauf);
  box-shadow: var(--lauf-strich-schein);
  animation: cs-sweep var(--lauf-sweep-dauer) ease-in-out infinite;
}

/* Das Warnabzeichen unten rechts an der Buehne (Artboards 09 und 10). */
.lauf__warnzeichen {
  position: absolute;
  right: var(--space-4);
  bottom: var(--space-4);
  width: var(--lauf-warnzeichen);
  height: var(--lauf-warnzeichen);
  border-radius: var(--radius-pille);
  background: var(--blatt-flaeche);
  border: var(--karte-rand) solid var(--lauf-halt-rand);
  color: var(--warn-icon);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
 * DER VIERTE SCHRITT — Artboard 08b (WI-0121, Spec 4.3 / 6.2a)
 *
 * KEIN ZWEITER BILDSCHIRM UND KEINE ZWEITE WARTEDARSTELLUNG. Es ist dieselbe
 * `.lauf`-Seite mit derselben Buehne, derselben Schrittliste und demselben
 * unten verankerten Ausgang — die Regeln hier ueberschreiben nur, was der
 * Entwurf auf 08b anders zeichnet.
 *
 * UND ER ZEICHNET GENAU EINE SACHE ANDERS: die Stimmung. Terracotta heisst in
 * dieser App „es arbeitet gerade", die Warnfarbe heisst „es ist etwas schief".
 * Ein Auto, das noch niemand gefunden hat, ist keines von beidem — es ist die
 * beste Nachricht, die das Spiel zu vergeben hat. Deshalb Sage, deshalb eine
 * suchende Lupe statt des scannenden Lichtstrichs, und deshalb ein „Neu" an
 * der Buehne statt eines Warnabzeichens.
 * ------------------------------------------------------------------------ */

.lauf__buehne[data-art='recherche'] {
  width: var(--lauf-neu-buehne);
  height: var(--lauf-neu-buehne);
}

.lauf__buehne[data-art='recherche'] .lauf__ring {
  border-color: var(--lauf-neu-ring-1);
  animation-duration: var(--lauf-neu-ring-dauer);
  animation-delay: 0s;
}

/* Zwei Ringe, der zweite blasser und um die halbe Dauer versetzt — so
   zeichnet der Entwurf sie (HANDOFF §14 Zeile 08b). */
.lauf__buehne[data-art='recherche'] .lauf__ring[data-ring='2'] {
  border-color: var(--lauf-neu-ring-2);
  animation-delay: calc(var(--lauf-neu-ring-dauer) / 2);
}

.lauf__buehne[data-art='recherche'] .lauf__scheibe {
  width: var(--lauf-neu-scheibe);
  height: var(--lauf-neu-scheibe);
  background: var(--lauf-neu-flaeche);
  border-color: var(--lauf-neu-rand);
}

/* Der Umriss steht BLASS und vollstaendig da: gesucht wird darueber, nicht
   an ihm. Deshalb keine Strichanimation wie auf 08 — die Bewegung gehoert
   hier der Lupe. */
.lauf__spur--blass {
  width: var(--lauf-neu-spur);
}

.lauf__spur--blass .silhouette {
  stroke: var(--lauf-neu-spur-farbe);
  stroke-dasharray: none;
  stroke-dashoffset: 0;
  animation: none;
}

.lauf__lupe {
  position: absolute;
  display: inline-flex;
  color: var(--cs-good-soft);
  animation: cs-look var(--lauf-look-dauer) ease-in-out infinite;
}

.lauf__lupe .ikone--lupe {
  width: var(--lauf-lupe);
  height: var(--lauf-lupe);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Das „Neu" oben rechts an der Buehne — die Stelle, an der 09 und 10 ihr
   Warnabzeichen tragen, nur oben statt unten und in Sage statt in der
   Warnfarbe. Es ist das eine Wort, das den Fund als Nachricht ausweist. */
.lauf__neu {
  position: absolute;
  top: 0;
  right: 0;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pille);
  background: var(--cs-good);
  /* Dunkle Tinte auf hellem Sage — derselbe Weg wie beim Zaehler am ruhenden
     Reiter (--zaehler-text), keine zweite Regel fuer denselben Fall. */
  color: var(--raum-bg);
  font-size: var(--schrift-abschnitt);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-versal);
  text-transform: uppercase;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}

/* Die Unterzeile am laufenden vierten Schritt: derselbe Listeneintrag, nur
   mit einem leiseren Satz darunter, der den Grund nennt. */
.schritt__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.schritt__zusatz {
  font-size: var(--schrift-klein);
  line-height: var(--zeilenhoehe-fliess);
  color: var(--raum-text-schwach);
}

/* Der laufende vierte Schritt ist die AUSSAGE der Seite — der Entwurf setzt
   seine erste Zeile kraeftig und in der Textfarbe, nicht im Fliesston. */
.lauf[data-lauf='recherche'] .schritt[data-stand='aktiv'] .schritt__zeile {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

/* UND SEIN KREISEL DREHT IN SAGE, NICHT IN TERRACOTTA. Auf 08 heisst
   Terracotta „es arbeitet"; hier arbeitet es auch, aber an einer guten
   Nachricht — der Entwurf zeichnet den Kreisel deshalb in --cs-good, wie die
   drei Haken darueber. Ein terracottafarbener Ring mitten in einer sagefarbenen
   Seite waere der einzige Fremdkoerper darauf. */
.lauf[data-lauf='recherche'] .schritt[data-stand='aktiv'] .schritt__zeichen {
  border-color: var(--gruen-icon);
  border-top-color: transparent;
}

/* --------------------------------------------------------------------------
 * DIE REIHE — hoechstens drei Fotos gleichzeitig (WI-0211)
 * Artboards 07b, 08c, 08d und 09b; HANDOFF §5.5b2.
 * ------------------------------------------------------------------------ */

/* DER STREIFEN steht UEBER dem Inhalt auf jedem Bildschirm dieses Ablaufs und
   ist die einzige Darstellung der Reihe — kein Abzeichen sonstwo, kein Zaehler
   in der Tableiste (HANDOFF §5.5b2). Er nimmt die volle Breite; auf der
   Erkennungsseite steht `.lauf` auf `align-items: center`, deshalb das
   ausdrueckliche `align-self`. */
.reihe {
  display: flex;
  flex: none;
  align-self: stretch;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

/* DER STREIFEN SITZT WEIT OBEN, und dafuer weicht die Buehne von ihrem Polster
   ab: die Erkennungsseiten beginnen sonst 56 px unter dem Kopf (WI-0068), der
   Entwurf setzt den Streifen auf 12 px. Derselbe `:has()`-Griff wie bei der
   verlorenen Eroberung auf `partie` — die Ausnahme gilt NUR fuer den Zustand,
   der sie braucht, und `07`, `08` und `09` bleiben unberuehrt.

   Seiten und Fuss gehen mit: die Artboards 08c, 08d und 09b verankern ihren
   Aktionsblock auf `left/right: 20px; bottom: 22px`, waehrend die
   Erkennungsseiten sonst 26 bzw. 35 px tragen. Gemessen waren das 5 bis 12 px
   je Kante (docs/entwurfs-vergleich.md). */
.app__buehne[data-bildschirm='scan_laeuft']:has(.reihe),
.app__buehne[data-bildschirm='scan_fehler']:has(.reihe) {
  padding: var(--reihe-oben) var(--reihe-seite) var(--reihe-unten);
}

/* Im Sucher genauso. Den Systemrand traegt seit WI-0417 `.app`. */
.app__buehne[data-bildschirm='scannen']:has(.reihe) {
  padding-top: var(--reihe-oben);
}

/* Im Sucher polstert die Buehne 22 px; der Streifen holt sich die zwei
   Pixel zurueck, die der Entwurf ihm mehr gibt. */
.app__buehne[data-bildschirm='scannen'] .reihe {
  margin-inline: calc(var(--reihe-seite) - var(--buehne-seite));
}

.reihe__plaetze {
  display: flex;
  flex: none;
  gap: var(--reihe-luecke);
}

.reihe__platz {
  position: relative;
  flex: none;
  width: var(--reihe-platz-b);
  height: var(--reihe-platz-h);
  border-radius: var(--reihe-platz-radius);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Der laufende Platz traegt den Akzent — dieselbe Aussage wie der Ring auf 08:
   „hieran wird gerade gearbeitet". */
.reihe__platz[data-stand='laeuft'] {
  background: var(--cs-accent-tint);
  border: var(--reihe-laeuft-rand) solid var(--color-accent);
}

.reihe__platz[data-stand='wartet'] {
  background: var(--cs-fill-1);
  border: var(--reihe-rand) solid var(--reihe-wartet-rand);
}

.reihe__platz[data-stand='fehler'] {
  background: var(--reihe-fehler-flaeche);
  border: var(--reihe-rand) solid var(--reihe-fehler-rand);
}

/* Der freie Platz ist gestrichelt: er ist ein Angebot und kein Zustand. */
.reihe__platz[data-stand='frei'] {
  border: var(--reihe-rand) dashed var(--reihe-frei-rand);
}

.reihe__spur {
  display: flex;
  align-items: center;
  justify-content: center;
}

.reihe__spur .silhouette {
  width: var(--reihe-spur-b);
  height: var(--reihe-spur-h);
  color: var(--color-accent-400);
}

/* Der wartende Platz zeigt dasselbe Auto, nur leiser — er arbeitet nicht. */
.reihe__spur--blass .silhouette {
  color: var(--raum-text-gedaempft);
  opacity: var(--reihe-wartet-deckkraft);
}

/* Der Lichtstrich, derselbe wie auf der Buehne von 08 — dieselbe Keyframe,
   damit Streifen und Buehne im selben Takt laufen. */
.reihe__strich {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--lauf-strich);
  background: var(--lauf-strich-verlauf);
  animation: cs-sweep var(--lauf-sweep-dauer) ease-in-out infinite;
}

/* Die Nummer oben rechts: sie sagt, das WIEVIELTE Foto hier wartet — und
   genau darauf nehmen die Saetze daneben Bezug („Foto 2 wartet"). */
.reihe__nummer {
  position: absolute;
  top: 3px;
  right: 5px;
  font-size: var(--reihe-nummer);
  font-weight: var(--gewicht-fett);
  color: var(--raum-text-gedaempft);
}

.reihe__zeichen {
  display: flex;
  align-items: center;
  justify-content: center;
}

.reihe__platz[data-stand='fehler'] .reihe__zeichen .ikone {
  width: var(--reihe-zeichen);
  height: var(--reihe-zeichen);
  color: var(--warn-icon);
  stroke-width: 2.75;
}

.reihe__platz[data-stand='frei'] .reihe__zeichen .ikone {
  width: var(--reihe-zeichen-frei);
  height: var(--reihe-zeichen-frei);
  color: var(--raum-text-schwach);
}

/* Die Erklaerzeile rechts neben den Plaetzen. Sie darf umbrechen — die Saetze
   des Entwurfs sind zweizeilig gesetzt. */
.reihe__zeile {
  flex: 1;
  min-width: 0;
  font-size: var(--schrift-klein);
  line-height: 1.35;
  color: var(--raum-text-gedaempft);
}

/* Die Zusage von 08d: „Kein Foto geht verloren." Sie traegt den guten Ton,
   weil sie eine gute Nachricht ist — und nicht den Warnton, obwohl sie in
   einem Moment steht, in dem die Kamera gerade nichts annimmt. */
.reihe__zusage,
.reihe__rat {
  align-self: stretch;
  border-radius: var(--reihe-kasten-radius);
  padding: var(--reihe-kasten-polster);
  margin-top: var(--space-4);
}

.reihe__zusage {
  background: var(--reihe-zusage-flaeche);
  border: 1px solid var(--reihe-zusage-rand);
  color: var(--gruen-text);
}

/* Der Ratkasten von 09b ist ruhig: der Rat ist keine zweite Fehlermeldung. */
.reihe__rat {
  background: var(--cs-fill-1);
  border: 1px solid var(--cs-line-2);
  color: var(--raum-text-gedaempft);
}

.reihe__zusage p,
.reihe__rat p {
  margin: 0;
  font-size: 13px;
  line-height: var(--zeilenhoehe-fliess);
}

/* Die durchgestrichene Kamera von 09b. Sie steht an der Stelle, an der 09 den
   angehaltenen Ring zeigt — und sie sagt etwas anderes: nicht „der Vorgang
   steht", sondern „DIESES Foto ist weg". */
.reihe__glyphe {
  flex: none;
  width: var(--reihe-glyphe-kreis);
  height: var(--reihe-glyphe-kreis);
  border-radius: var(--radius-pille);
  border: var(--reihe-glyphe-rand) solid var(--lauf-halt-rand);
  background: var(--reihe-glyphe-flaeche);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-4);
}

.reihe__glyphe .ikone--kamera-durch {
  width: var(--reihe-glyphe);
  height: var(--reihe-glyphe);
  color: var(--warn-icon);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Die Zeitlimit-Notiz ueber dem Ausgang (Spec 6.2a Bedingung 4). Sie ist
   keine Fussnote, sondern die Zusage, dass die Karte kommt — deshalb ein
   eigener, umrandeter Kasten und keine graue Zeile. */
.lauf__notiz {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--cs-fill-1);
  border: 1px solid var(--cs-line-1);
  font-size: var(--schrift-klein);
  line-height: var(--zeilenhoehe-fliess);
  /* Artboard 08b faerbt Satz UND Uhr im Etikettton (`#a89c88`); das Zeichen
     erbt ihn als `currentColor`. */
  color: var(--raum-text-etikett);
  margin: 0;
}

.lauf__notiz .ikone--uhr {
  width: var(--icon-meldung);
  height: var(--icon-meldung);
  margin-top: var(--meldung-zeichen-versatz);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Die Suchgeste der Lupe (HANDOFF §14, neue Keyframe `cs-look`). Sie wandert
   ueber den Umriss und kommt dorthin zurueck, wo sie angefangen hat — die
   Werte stehen so im Entwurf. */
@keyframes cs-look {
  0% {
    transform: translate(-24px, 6px) scale(0.92);
  }
  25% {
    transform: translate(4px, -10px) scale(1);
  }
  50% {
    transform: translate(26px, 4px) scale(0.96);
  }
  75% {
    transform: translate(-2px, 12px) scale(1.02);
  }
  100% {
    transform: translate(-24px, 6px) scale(0.92);
  }
}

/* Die Punkte laufen IM Text mit, nicht daneben (WI-0096).
   Vorher war das ein Flexkasten mit zwei Kindern. Solange die Ueberschrift auf
   eine Zeile passt, sieht man keinen Unterschied — bei zwei Zeilen aber wird
   der Textkasten so breit wie die Ueberschrift, und die Punkte rutschen an den
   rechten Rand der ERSTEN Zeile, weit weg vom letzten Wort. Genau das war auf
   `25-duel-connecting` zu sehen, dessen Ueberschrift zweizeilig ist.
   Der Abstand, den `gap` gesetzt hat, steht jetzt als Aussenabstand an den
   Punkten — eine einzeilige Ueberschrift wird damit unveraendert gesetzt. */
.lauf__titel {
  display: block;
  text-align: center;
}

 /* Die drei versetzt animierten Punkte. Sie heissen seit WI-0095 nach dem,
   was sie sind, und nicht nach dem Scanlauf: Artboard 30 zeichnet sie ein
   zweites Mal, hinter „Warte auf Miras Ansage". */
.punkte {
  display: inline-flex;
  margin-left: var(--space-1);
  vertical-align: baseline;
}

.punkte > span {
  animation: cs-dots var(--lauf-punkte-dauer) infinite;
}

.punkte > span:nth-child(2) {
  animation-delay: 0.2s;
}

.punkte > span:nth-child(3) {
  animation-delay: 0.4s;
}

/* Die Schrittliste nimmt die volle Breite — der Entwurf setzt sie linksbuendig
   unter die mittige Ueberschrift (`align-self:stretch`). */
.lauf .schritte {
  align-self: stretch;
  margin-top: var(--space-6);
}

.lauf .aktionsblock {
  align-self: stretch;
}

@keyframes cs-ring {
  0% {
    transform: scale(0.82);
    opacity: 0.7;
  }
  100% {
    transform: scale(1.5);
    opacity: 0;
  }
}

@keyframes cs-trace {
  from {
    stroke-dasharray: var(--lauf-spur-strich);
    stroke-dashoffset: var(--lauf-spur-strich);
  }
  to {
    stroke-dasharray: var(--lauf-spur-strich);
    stroke-dashoffset: 0;
  }
}

@keyframes cs-sweep {
  0% {
    transform: translateY(calc(var(--lauf-scheibe) / -2));
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  88% {
    opacity: 1;
  }
  100% {
    transform: translateY(calc(var(--lauf-scheibe) / 2));
    opacity: 0;
  }
}

@keyframes cs-dots {
  0%,
  20% {
    opacity: 0.25;
  }
  50% {
    opacity: 1;
  }
  80%,
  100% {
    opacity: 0.25;
  }
}

.schritte {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.schritt {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--raum-fliess);
}

/* NUR DER LAUFENDE SCHRITT TRAEGT EINEN KREIS — er IST der Kreisel. Haken und
   Kreuz stehen frei, wie der Entwurf sie zeichnet (Artboards 08 bis 10); der
   Ring um den Haken war eine Erfindung der Testversion. */
.schritt__zeichen {
  width: var(--schritt-zeichen);
  height: var(--schritt-zeichen);
  flex: none;
  border-radius: var(--radius-pille);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* DER ERLEDIGTE SCHRITT IST GANZ GRUEN, NICHT NUR SEIN HAKEN (WI-0112).
   Der Entwurf setzt die Zeile auf `font-size:15px;color:#c8dba2` — auf
   Artboard 08 („Fahrzeug im Bild gefunden", „Kennzeichen unkenntlich
   gemacht"), auf 09 („Foto sofort gelöscht") und auf 25 („Code angenommen",
   „Jonas ist online"). Die App faerbte nur das Zeichen und liess die Schrift
   im Fliesston stehen; beim MISSLUNGENEN Schritt darunter faerbt sie die
   ganze Zeile — dieselbe Zeile, zwei Regeln. §11 fuehrt beide Toene:
   --cs-good fuer das Zeichen, --cs-good-soft fuer die Schrift. */
.schritt[data-stand='fertig'] {
  color: var(--gruen-text);
}

.schritt[data-stand='fertig'] .schritt__zeichen {
  color: var(--gruen-icon);
}

.schritt[data-stand='offen'] .schritt__zeichen {
  border: var(--karte-rand) solid var(--feld-rand);
}

/* DER LAUFENDE SCHRITT IST DIE AUSSAGE DER SEITE (WI-0188). Der Entwurf setzt
   ihn auf beiden Warteseiten gleich — `font-weight:700;color:#f5ead8` auf 08
   („Modell wird erkannt") und auf 25 („Warten auf sein Ja") —, waehrend die
   erledigten darueber im leiseren Salbei stehen. Die App liess ihn im
   Fliesston und in 400: damit sah der Schritt, auf den gerade gewartet wird,
   leiser aus als die, die schon fertig sind. */
.schritt[data-stand='aktiv'] {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

/* Der LAUFENDE Schritt ist der Kreisel — hier gehoert der Ring hin, und nur
   hier (HANDOFF §6: der eingebettete 20-px-Kreisel ist neben den beiden ganzen
   Seiten die einzige Ladebehandlung). */
.schritt[data-stand='aktiv'] .schritt__zeichen {
  border: var(--karte-rand) solid var(--color-accent);
  border-top-color: transparent;
  animation: dreh var(--halo-dauer) linear infinite;
}

/* Der misslungene Schritt (Artboards 09 und 10): Kreuz in der Warnfarbe,
   Text kraeftiger — er ist die Aussage der Seite, nicht eine Fussnote. */
.schritt[data-stand='warn'] {
  color: var(--warn-icon);
  font-weight: var(--gewicht-kraeftig);
}

.schritt[data-stand='warn'] .schritt__zeichen {
  color: var(--warn-icon);
}

.schritt[data-stand='offen'] {
  color: var(--raum-text-schwach);
}

@keyframes dreh {
  to {
    transform: rotate(360deg);
  }
}

/* --------------------------------------------------------------------------
 * Auswahl
 * ------------------------------------------------------------------------ */

.vorschlaege {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Der zweizeilige Block ueber der Vorschlagsliste (Artboard 11): Marke und Typ
   sind unabhaengig voneinander falsch, also stehen sie als zwei eigene Zeilen
   da. `min-height` und nicht `height` — der Wert ist die TREFFERFLAECHE, nicht
   ein Deckel (Designspec 10.3 Punkt 3). */
.korrekturzeilen {
  border-radius: var(--radius-lg);
  background: var(--cs-fill-1);
}

.korrekturzeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--btn-hoehe);
  padding: 0 var(--space-4);
  border-bottom: var(--tableiste-randbreite) solid var(--cs-line-1);
}

.korrekturzeile:last-child {
  border-bottom: 0;
}

/* Die Beschriftung ist das „board eyebrow" aus HANDOFF §12 — 11px, 800, in
   Versalien, in der Spaltenbreite des Entwurfs. */
.korrekturzeile > span:first-child {
  width: var(--kachel-foto);
  flex: none;
  color: var(--raum-text-etikett);
  font-family: var(--font-heading);
  font-size: var(--schrift-label);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-versal);
  text-transform: uppercase;
}

/* Marke und Typ stehen im Grad der Ueberschriftenskala, in dem der Entwurf sie
   zeichnet — es ist derselbe wie bei den Markenzeilen auf 11b. */
.korrekturzeile strong {
  flex: 1;
  min-width: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h4);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Die Wege auf 11b und 11c. Beide sehen aus wie ein Textweg und sind auch
   einer — die Trefferflaeche kommt aus der Zeilenhoehe darueber. Seit
   WI-0176 traegt auch die Typ-Zeile diesen Weg (HANDOFF §17: „gleiche
   Behandlung wie die Marke"); die frueher dort stehende stumme Beschriftung
   `unten wählen` ist damit ersatzlos weg. */
.korrekturzeile__weg {
  flex: none;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--color-accent-300);
  font-family: var(--font-body);
  font-size: var(--schrift-h6);
  font-weight: var(--gewicht-kraeftig);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
 * Markenwahl (Artboard 11b)
 * ------------------------------------------------------------------------ */

/* Dieselbe Pille wie jedes andere Eingabefeld der App (.feld) — die Lupe sitzt
   davor, das Feld selbst traegt keinen eigenen Rahmen mehr. */
.markensuche {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--btn-hoehe);
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
}

.markensuche__lupe {
  flex: none;
  color: var(--raum-text-schwach);
}

.markensuche input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--btn-schrift);
}

.markensuche input::placeholder {
  color: var(--raum-text-schwach);
}

/* „Naheliegend" ueber den vier ersten Marken (Artboard 11b). Sie erbte bis
   WI-0340 die Textfarbe des Bildschirms, weil `h6` keine eigene fuehrt — der
   Entwurf zeichnet sie im Etikettton wie jede andere Abschnittsmarke. */
.markenliste__titel {
  margin: 0;
  color: var(--raum-text-etikett);
}

.markenliste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.markenzeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-lg);
  background: transparent;
  color: var(--raum-text);
  text-align: left;
  font-family: var(--font-body);
  cursor: pointer;
}

.markenzeile strong {
  flex: 1;
  min-width: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h4);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.markenzeile__zahl {
  flex: none;
  color: var(--raum-text-meta);
  font-size: var(--schrift-klein);
}

/* Die gewaehlte Marke traegt denselben Akzentrahmen wie der gewaehlte
   Vorschlag auf Artboard 11 — eine Auswahl sieht ueberall gleich aus. */
.markenzeile--gewaehlt {
  border-width: var(--vorschlag-wahl-rand);
  border-color: var(--color-accent);
  background: var(--vorschlag-wahl-flaeche);
}

.markenzeile__haken {
  flex: none;
  color: var(--color-accent);
}

/* `11b-marke-leer`: der gestrichelte Block nennt beim Namen, was fehlt, und
   der Weg nach vorn steht unten als HAUPTAKTION — die Suche kennt nur den
   Katalog, das Eintippen kennt alles. */
.markenleer {
  padding: var(--space-4);
  border: var(--karte-rand) dashed var(--feld-rand);
  border-radius: var(--radius-lg);
}

.markenleer__titel {
  margin: 0 0 var(--space-1);
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

.markenleer__text {
  margin: 0;
  color: var(--raum-text-meta);
  font-size: var(--schrift-klein);
}

/* --------------------------------------------------------------------------
 * Typenwahl (Artboard 11c) — WI-0176
 *
 * Derselbe Aufbau wie 11b eine Stufe darueber, und bewusst dieselben
 * Bauteile: die Suchpille (.markensuche), der leere Zustand (.markenleer),
 * die Fehlerzeile (.fehlerbox) und die Skelette (.skelett) stehen schon in
 * dieser Datei. Hier steht nur, was es sonst nirgends gibt — die Zeile mit
 * Baujahrsspanne und Klasse und der Salbei-Chip daran.
 * ------------------------------------------------------------------------ */

/* Die Liste ROLLT, der Rest des Bildschirms nicht: der Entwurf setzt sie auf
   `flex:1;min-height:0;overflow:auto` und haelt die Hauptaktion unten fest
   (Designspec 10.3 Punkt 1). Ohne `min-height:0` waechst ein Flex-Kind an
   seinem Inhalt und schiebt den Aktionsblock aus dem Bild. */
.typenliste {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Der Entwurf blendet die letzte Zeile am unteren Rand aus
     (`mask-image:linear-gradient(#000 calc(100% - 14px),transparent)`). Das
     ist keine Zierde: es sagt „hier geht es weiter", ohne eine Bildlaufleiste
     zu zeichnen, die auf dem Telefon ohnehin niemand sieht. */
  mask-image: linear-gradient(
    var(--qr-dunkel) calc(100% - var(--space-3)),
    transparent
  );
  -webkit-mask-image: linear-gradient(
    var(--qr-dunkel) calc(100% - var(--space-3)),
    transparent
  );
}

.typzeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  flex: none;
  padding: var(--space-3) var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-lg);
  background: transparent;
  color: var(--raum-text);
  text-align: left;
  font-family: var(--font-body);
  cursor: pointer;
}

.typzeile__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.typzeile__name {
  font-family: var(--font-heading);
  font-size: var(--schrift-h5);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.typzeile__reihe {
  color: var(--raum-text-meta);
  font-size: var(--schrift-klein);
}

/* Der gewaehlte Typ traegt denselben Akzentrahmen wie die gewaehlte Marke auf
   11b und der gewaehlte Vorschlag auf 11 — eine Auswahl sieht ueberall gleich
   aus. */
.typzeile--gewaehlt {
  border-width: var(--vorschlag-wahl-rand);
  border-color: var(--color-accent);
  background: var(--vorschlag-wahl-flaeche);
}

/* „Vorschlag" — in Salbei und NICHT in Terracotta: der Chip sagt, woher die
   Zeile kommt, er ist keine Aktion (Designspec Kap. 9). */
.typzeile__chip {
  flex: none;
  padding: var(--space-1) var(--space-3);
  border: var(--tableiste-randbreite) solid var(--gruen-rand);
  border-radius: var(--radius-pille);
  background: var(--gruen-flaeche);
  color: var(--gruen-text);
  font-size: var(--schrift-label);
  font-weight: var(--gewicht-fett);
}

/* `11c-laden`: fuenf Umrisse in der Hoehe einer Zeile. Kein Kreisel, kein
   Schimmern — der Entwurf sagt beides ausdruecklich ab. */
.skelett--typzeile {
  flex: none;
  height: var(--typzeile-skelett-hoehe);
  border-radius: var(--radius-lg);
}

/* `11c-fehler`: der ruhige Kasten unter der bernsteinfarbenen Zeile. Er sagt,
   was jetzt geht — und nimmt den Platz ein, an dem sonst die Liste steht,
   damit die beiden Knoepfe unten bleiben, wo der Daumen sie sucht. */
.typenhinweis {
  flex: none;
  padding: var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-lg);
  background: var(--feld-flaeche);
}

.vorschlag {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  padding: var(--space-3);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-family: var(--font-body);
  cursor: pointer;
}

/* Der vorgewaehlte Vorschlag (Artboard 11): 2 px Terracotta und die
   Akzent-Tinte als Flaeche. VORGEWAEHLT IST NICHT UEBERSPRUNGEN — die beiden
   anderen Zeilen und der Weg zum Eintippen bleiben unveraendert daneben
   stehen (Produktspec 4.3). */
.vorschlag--gewaehlt {
  border-width: var(--vorschlag-wahl-rand);
  border-color: var(--color-accent);
  background: var(--vorschlag-wahl-flaeche);
}

.vorschlag__bild {
  width: var(--vorschlag-silhouette-b);
  height: var(--vorschlag-silhouette-h);
  flex: none;
}

.vorschlag__text {
  flex: 1;
  min-width: 0;
}

/* Zwei ZEILEN, nicht zwei Woerter (Artboard 11): der Name oben, die Klasse
   darunter. Als Inline-Spannen liefen sie bis WI-0068 in einer Zeile
   zusammen — „VW Golf VII · Kompakt" statt Name und Zeile darunter. */
.vorschlag__name {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--schrift-h4);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.vorschlag__reihe {
  display: block;
  color: var(--raum-text-meta);
  font-size: var(--schrift-klein);
}

.konfidenz {
  flex: none;
  border-radius: var(--radius-pille);
  padding: var(--space-1) var(--space-3);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-fett);
  background: var(--feld-flaeche);
  color: var(--raum-text-gedaempft);
}

.konfidenz--erster {
  background: var(--konfidenz-flaeche);
  color: var(--konfidenz-text);
}

/* --------------------------------------------------------------------------
 * Wurf
 * ------------------------------------------------------------------------ */

/* SENKRECHTE VERANKERUNG STATT MITTE (WI-0097, Artboard 13).
 *
 * Die Spalte stand mit `justify-content: center` als Ganzes in der Mitte —
 * damit sass die Augenbraue „NEUE KARTE" zu tief und der Knopfblock endete
 * rund 135 px ueber der Bildkante. Der Entwurf verankert stattdessen:
 * Augenbraue oben, Karte im flexiblen Mittelteil, Aktionsblock unten
 * (HANDOFF §4.4 und Designspec Kap. 9 — „uebernommen wird die vertikale
 * Verankerung, nicht der Pixelversatz").
 *
 * `margin-top: auto` am Aktionsblock schiebt genau den Rest nach unten. Das
 * ist die gleiche Verankerung, die auch auf einem hoeheren Geraet stimmt:
 * waechst der Bildschirm, waechst der Mittelteil. */
.wurf {
  background: var(--wurf-raum);
  align-items: center;
  justify-content: flex-start;
  flex: 1;
  gap: var(--space-3);
}

.wurf .karte-buehne {
  flex: 1;
  display: flex;
  align-items: center;
  margin-block: var(--space-3);
}

.wurf .knopfreihe {
  margin-top: auto;
}

.wurf__kopf {
  text-transform: uppercase;
  letter-spacing: var(--laufweite-wurf);
  font-size: var(--schrift-h6);
  font-weight: var(--gewicht-fett);
  color: var(--raum-text-etikett);
}

/* Die Stufen-Pille des Wurfs ist am 29.08.2026 ersatzlos entfallen
   (Designspec Kap. 6 und 8). Sie stand als Wort neben einer Karte, die
   dieselbe Seltenheit bereits als Punktzeile und als Farbe traegt. */

/* --------------------------------------------------------------------------
 * Der Wiederfund — Artboards 13c und 13d (WI-0212)
 *
 * Beide Artboards teilen alles bis zu den Kacheln und trennen sich erst
 * darunter. Das ist hier genauso: EINE Regelmenge, und was sich am gesperrten
 * Zustand unterscheidet, haengt an `[data-doppelfund-stand='gesperrt']`.
 * ------------------------------------------------------------------------ */

/* --------------------------------------------------------------------------
 * Der gleiche Typ als eigene Karte — Artboard 13c (WI-0283, HANDOFF §25)
 *
 * Oben zentriert: Karte mit Zaehler, Titel, zwei Saetze. Darunter die beiden
 * Kacheln ueber die volle Breite, unten der Aktionsblock. Dieselbe Gestalt wie
 * der alte Wiederfund — und ein anderer Inhalt: hier wird gefeiert, nicht
 * abgewunken.
 * ------------------------------------------------------------------------ */

/* DER FUSSFREIRAUM IST HIER NICHT DER ALLGEMEINE — dieselbe Korrektur, die
   `konto`/`geraetewechsel` schon tragen und die WI-0281 fuer die
   Anmeldebildschirme gezogen hat. `--buehne-unten` haelt 90 px fuer die
   schwebende Tableiste frei (Designspec Kap. 9), und auf `karte_neu` steht sie
   nicht: der Bildschirm fehlt in `TABLEISTE_SICHTBAR` (app.js), weil er aus der
   Fundstrecke kommt und nicht aus der Navigation.

   GEMESSEN, nicht geschaetzt: mit den 90 px ergab 13c auf dem Brett
   26 + 682 + 90 = 798 px und rollte um 5 px — bei 708 px Inhalt, also allein
   aus dem Freiraum fuer eine Leiste, die es hier nicht gibt. Das ist genau der
   Leerraum, den Designspec Kap. 10.3 Punkt 3 verbietet, und der Test
   `Daumen gleicher_typ` in tests/e2e/daumen.spec.js haelt beides fest.

   ES IST EINE LUECKE IM ENTWURF: IMPLEMENTATION-HANDOFF.md fuehrt fuer `13c`
   nur die Texte, keine Geometrie. Genommen ist die Stufe, die dieselbe Lage an
   den Kontobildschirmen schon traegt (`--space-6`), statt einer eigens
   ausgedachten Zahl — gemeldet, nicht gefuellt. */
.app__buehne[data-bildschirm='karte_neu'] {
  padding-bottom: var(--space-6);
}

.duplikat {
  align-items: center;
  text-align: center;
}

/* `position: relative` liegt am Kopf und nicht an der Karte, damit der Zaehler
   ueber ihren Rand hinausragen kann, ohne die Flaeche zu vergroessern. */
.duplikat__kopf {
  position: relative;
  flex: none;
  margin-bottom: var(--duplikat-karte-unten);
}

.duplikat__karte {
  width: var(--duplikat-karte-breite);
  height: var(--duplikat-karte-hoehe);
  border-radius: var(--duplikat-karte-radius);
  background: var(--cs-surface-card);
  /* Der Ring traegt die Seltenheitsfarbe DIESER Karte. Sie kommt als `--r-g`
     vom Bauteil (public/js/design.js) und damit aus der `--cs-r-*`-Skala —
     dieselbe Quelle wie Kopfbalken und Gruppenkreis, nie ein zweiter Ton. */
  box-shadow: 0 0 0 var(--duplikat-karte-ring) var(--r-g, var(--cs-r-common));
}

.duplikat__zaehler {
  position: absolute;
  top: var(--duplikat-zaehler-oben);
  right: var(--duplikat-zaehler-rechts);
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--duplikat-zaehler-hoehe);
  height: var(--duplikat-zaehler-hoehe);
  padding: 0 var(--duplikat-zaehler-seite);
  border-radius: var(--radius-pille);
  background: var(--duplikat-zaehler-flaeche);
  box-shadow: var(--shadow-md);
  color: var(--duplikat-zaehler-text);
  font-family: var(--font-heading);
  font-size: var(--duplikat-zaehler-schrift);
}

.duplikat__titel {
  margin: 0 0 var(--space-2);
}

.duplikat__text {
  margin: 0 0 var(--space-1);
}

.duplikat__werte {
  margin: 0 0 var(--duplikat-werte-unten);
  font-size: var(--schrift-hinweis);
  color: var(--raum-text-schwach);
}

/* Die Kacheln stehen LINKSBUENDIG ueber die volle Breite — der Kopf darueber
   bleibt zentriert. Genau so zeichnet der Entwurf es. */
.duplikat__kacheln {
  align-self: stretch;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--duplikat-fuge);
  text-align: left;
}

/* DIE KNOEPFE STEHEN UEBER DIE VOLLE SPALTE (Artboard: `left:22px;
   right:22px`). Ohne diese Zeile zieht `align-items: center` des Kopfes sie
   auf ihre Textbreite zusammen. */
.duplikat__aktionen {
  align-self: stretch;
}

/* SPALTE UND NICHT BLOCK: fehlt einer Kachel die Datumszeile, streckt das
   Raster beide auf dieselbe Hoehe, und die Datenflaeche nimmt sich den Rest,
   statt ein Loch zu lassen. */
.duplikat__kachel {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-md);
  background: none;
}

/* Die NEUE Karte traegt den Akzentring — sie ist die, die eben entstanden ist.
   Der Ring liegt als Schatten INNEN, damit die Kachel nicht waechst und das
   Raster verrutscht. */
.duplikat__kachel[data-duplikat-kachel='neue'] {
  border-color: transparent;
  box-shadow: inset 0 0 0 var(--duplikat-ring) var(--color-accent);
}

.duplikat__bild {
  display: block;
  position: relative;
  height: var(--duplikat-bild-hoehe);
  flex: none;
  overflow: hidden;
  background: var(--foto-flaeche);
}

.duplikat__bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.duplikat__daten {
  display: block;
  flex: 1;
  min-width: 0;
  padding: var(--duplikat-daten-oben) var(--duplikat-daten-seite) var(--duplikat-daten-seite);
  background: var(--fotowahl-daten-flaeche);
}

.duplikat__rolle {
  display: block;
  font-size: var(--duplikat-rolle-schrift);
  font-weight: var(--gewicht-fett);
  color: var(--raum-fliess);
}

.duplikat__kachel[data-duplikat-kachel='neue'] .duplikat__rolle {
  color: var(--duplikat-rolle-neu);
}

/* EINZEILIG MIT ELLIPSE, NIE ZWEI ZEILEN (HANDOFF §5.5b). Fehlt Datum oder
   Ort, entsteht die Zeile gar nicht erst — kein `—`, kein `unbekannt`. */
.duplikat__wann {
  display: block;
  min-width: 0;
  font-size: var(--duplikat-wann-schrift);
  color: var(--raum-text-schwach);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.doppelfund {
  align-items: center;
  text-align: center;
}

/* Die Karte oben mit dem Zaehler an ihrer Ecke. `position: relative` liegt
   hier und nicht an der Karte selbst, damit der Zaehler ueber ihren Rand
   hinausragen kann, ohne die Flaeche zu vergroessern. */
.doppelfund__kopf {
  position: relative;
  flex: none;
  margin-bottom: var(--doppelfund-karte-unten);
}

.doppelfund__karte {
  width: var(--doppelfund-karte-breite);
  height: var(--doppelfund-karte-hoehe);
  border-radius: var(--radius-md);
  background: var(--cs-surface-card);
  /* Der Ring traegt die Seltenheitsfarbe DIESER Karte. Sie kommt als `--r-g`
     vom Bauteil (public/js/design.js) — dieselbe Quelle wie Kopfbalken und
     Gruppenkreis, nie ein zweiter Ton. */
  box-shadow: 0 0 0 var(--doppelfund-karte-ring) var(--r-g, var(--cs-r-common));
}

.doppelfund__zaehler {
  position: absolute;
  top: var(--doppelfund-zaehler-oben);
  right: var(--doppelfund-zaehler-rechts);
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--doppelfund-zaehler-hoehe);
  height: var(--doppelfund-zaehler-hoehe);
  padding: 0 var(--doppelfund-zaehler-seite);
  border-radius: var(--radius-pille);
  background: var(--doppelfund-zaehler-flaeche);
  box-shadow: var(--shadow-md);
  color: var(--doppelfund-zaehler-text);
  font-family: var(--font-heading);
  font-size: var(--doppelfund-zaehler-schrift);
}

.doppelfund__titel {
  margin: 0 0 var(--space-2);
}

.doppelfund__text {
  margin: 0 0 var(--space-1);
}

.doppelfund__text strong {
  color: var(--raum-text);
}

/* Der Satz, der die Enttäuschung abfängt. Der Entwurf setzt ihn auf 13 px und
   in den schwächsten Textton — leiser als der Satz darüber, weil er die Regel
   nennt und nicht die Nachricht. 13 px liegt zwischen den Stufen des Handoffs
   (12 / 13,5); genommen ist die nächste. */
.doppelfund__fest {
  margin: 0 0 var(--space-4);
  font-size: var(--schrift-hinweis);
  color: var(--raum-text-schwach);
}

/* Ab hier steht alles LINKSBUENDIG, ueber die volle Breite — der Kopf
   darueber bleibt zentriert. Genau so zeichnet der Entwurf es. */
.doppelfund__fotos {
  align-self: stretch;
  text-align: left;
}

/* DIE KNOEPFE STEHEN UEBER DIE VOLLE SPALTE (beide Artboards: `left:22px;
   right:22px`). Ohne diese Zeile zieht `align-items: center` des Kopfes sie
   auf ihre Textbreite zusammen — gemessen waren das auf 13c 72 px Seitenrand
   statt der 23 px, die der Entwurf zeichnet. */
.doppelfund__aktionen {
  align-self: stretch;
}

.doppelfund__frage {
  margin: 0 0 var(--space-1);
}

.doppelfund__grenze {
  margin: 0 0 var(--doppelfund-fuge);
  font-size: var(--schrift-klein);
  color: var(--raum-text-schwach);
}

.doppelfund__raster {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--doppelfund-fuge);
}

/* SPALTE UND NICHT BLOCK — dieselbe Begruendung wie bei den Kacheln von 14b:
   fehlt einer Kachel die Datumszeile, streckt das Raster beide auf dieselbe
   Hoehe, und die Datenflaeche nimmt sich den Rest, statt ein Loch zu lassen. */
.doppelfund__kachel {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-md);
  background: none;
  text-align: left;
}

.doppelfund__kachel[data-aktion] {
  cursor: pointer;
}

/* Der Akzentring der gewaehlten Kachel liegt als Schatten INNEN, damit die
   Kachel nicht um zweieinhalb Pixel waechst und das Raster verrutscht. */
.doppelfund__kachel[data-gewaehlt='ja'] {
  border-color: transparent;
  box-shadow: inset 0 0 0 var(--doppelfund-ring) var(--color-accent);
}

.doppelfund__bild {
  display: block;
  position: relative;
  height: var(--doppelfund-bild-hoehe);
  flex: none;
  overflow: hidden;
  background: var(--foto-flaeche);
}

.doppelfund__bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.doppelfund__daten {
  display: block;
  flex: 1;
  min-width: 0;
  padding: var(--doppelfund-daten-oben) var(--doppelfund-daten-seite)
    var(--doppelfund-daten-seite);
  background: var(--fotowahl-daten-flaeche);
}

.doppelfund__rolle {
  display: block;
  font-size: var(--doppelfund-rolle-schrift);
  font-weight: var(--gewicht-fett);
  color: var(--raum-fliess);
}

.doppelfund__kachel[data-gewaehlt='ja'] .doppelfund__rolle {
  color: var(--doppelfund-rolle-gewaehlt);
}

/* EINZEILIG MIT ELLIPSE, NIE ZWEI ZEILEN (HANDOFF §5.5b). Fehlt Datum oder
   Ort, entsteht die Zeile gar nicht erst — kein `—`, kein `unbekannt`. */
.doppelfund__wann {
  display: block;
  min-width: 0;
  font-size: var(--doppelfund-wann-schrift);
  color: var(--raum-text-schwach);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.doppelfund__haken {
  position: absolute;
  top: var(--doppelfund-haken-rand);
  right: var(--doppelfund-haken-rand);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--doppelfund-haken-scheibe);
  height: var(--doppelfund-haken-scheibe);
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--btn-text);
  font-size: var(--doppelfund-haken-schrift);
  font-weight: var(--gewicht-fett);
}

/* --- Nur der gesperrte Zustand (13d) --- */

.doppelfund[data-doppelfund-stand='gesperrt'] {
  --doppelfund-bild-hoehe: 96px;
}

/* Das noch nicht waehlbare Bild steht gedaempft da — es ist gespeichert und
   wartet, und genau das soll man sehen (HANDOFF §8.1). */
.doppelfund[data-doppelfund-stand='gesperrt'] .doppelfund__kachel[data-doppelfund-kachel='neu'] {
  opacity: var(--doppelfund-gesperrt-deckkraft);
}

.doppelfund__gesperrt {
  margin: var(--doppelfund-hinweis-oben) 0 0;
  padding: var(--doppelfund-hinweis-polster-oben) var(--doppelfund-hinweis-polster-seite);
  border: var(--doppelfund-hinweis-rand);
  border-radius: var(--doppelfund-hinweis-radius);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
  color: var(--raum-text-meta);
}

/* „ein Fund" steht kräftiger. Das Artboard zeichnet #e6dcc9; §11 führt diesen
   Ton nicht und hat --cs-text-3 (#d8ccb8) daneben — die nächstliegende Stufe,
   gemeldet statt erfunden. Dieselbe Regel wie beim Datum auf 14b. */
.doppelfund__gesperrt strong {
  color: var(--cs-text-3);
}

.knopfreihe {
  display: flex;
  gap: var(--space-3);
  width: 100%;
}

.knopfreihe > * {
  flex: 1;
}

/* Der Datenblock von Artboard 27 (die Zustimmung zur Eroberung): Decks,
 * Groesse, Serie als Paare nebeneinander.
 *
 * ER WAR BIS v3 AUCH DIE METAZEILE UNTER DER KARTE (Artboards 14 und 15). Die
 * ist ersatzlos entfallen und als Abschnitt `Eckdaten` in die Detailansicht
 * gewandert (§17) — was von ihr blieb, ist diese eine Zeile hier und die
 * Spaltenfuge, die sie sich mit den Eckdaten teilt. */
.datenblock {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--datenblock-fuge);
  margin: 0;
  font-size: var(--schrift-klein);
}

.datenblock dt {
  color: var(--raum-text-schwach);
  font-size: var(--schrift-winzig);
}

.datenblock dd {
  margin: 0;
  color: var(--raum-fliess);
}

/* Die Hinweiszeile unter der Karte (Artboards 14 und 15) — seit v3 auf beiden
   dieselbe, einzeilig und ZENTRIERT: `Doppeltipp zeigt die Karte im
   Vollbild.` Ohne sie waere der Doppeltipp unauffindbar; die Karte traegt
   kein Zeichen dafuer.

   Bis v2 standen hier zwei verschiedene, linksbuendige Saetze. Der eine
   versprach den Tipp als Weg zur Besitzerkette — den es so nicht mehr gibt —,
   der andere war der Herkunftsabsatz und steht jetzt dort, wo die Kette
   steht: in der Detailansicht (16). */
.kartenseite__hinweis {
  align-self: stretch;
  text-align: center;
  margin: 0;
}

/* Der Aktionsblock steht seit v3 auf ZWEI Ebenen (§17): die durchgehende
   Pille ueber der bestehenden Reihe, mit einer eigenen Fuge dazwischen. */
.kartenseite__aktionen {
  align-self: stretch;
  gap: var(--space-3);
  /* Beide Ebenen tragen denselben Grad, und zwar den der Artboards 14/15
     (WI-0129). Ueberschrieben wird das Token, nicht die Regel der beiden
     Knopfformen — so bleibt `.btn--details` weiterhin dieselbe Pille und
     `.btn--ghost` derselbe Ghost, nur eine halbe Stufe kleiner, wie der
     Entwurf sie hier zeichnet. */
  --btn-schrift-ghost: var(--kd-aktion-schrift);
}

/* --------------------------------------------------------------------------
 * Die Kartenseite (WI-0055)
 * ------------------------------------------------------------------------ */

/* Ueber der Karte eine schmale Zeile, in der rechts das Schliessen-Kreuz
   sitzt — der Notausgang nach Gewohnheit. Er steht bewusst NICHT im unteren
   Drittel: der Hauptweg zurueck bleibt die Tableiste (Designspec Kap. 10.3),
   dieses Kreuz ist die zweite, ruhige Moeglichkeit. Die Zeile liegt ausserhalb
   der Wischflaeche, damit sie beim Blaettern stehen bleibt. */
.kartenseite {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Bezugsrahmen fuer die Loeschabfrage (WI-0070) — sie liegt UEBER dieser
     Seite, nicht daneben. */
  position: relative;
}

/* Ein Bildschirm hinter einem Schleier (HANDOFF §6 Zeile 17): verwischt und
   abgedunkelt. Er bleibt lesbar genug, um zu erkennen, um welche Karte es
   gerade geht — und tritt weit genug zurueck, dass die Frage vorn steht. */
/* Zwei Namen, EINE Regel: die Kartenseite hinter der Loeschabfrage (Artboard
   17) und der Kontobildschirm hinter der Abmeldefrage (Artboard 45, WI-0099)
   treten gleich weit zurueck. Der Entwurf zeichnet beide Male dasselbe —
   deshalb steht die Angabe hier einmal und nicht zweimal. */
/* Und seit WI-0165 ein dritter Name an derselben Regel: `45b` hinter der
   getippten Bestaetigung (`45c`). Der Entwurf zeichnet dort dieselbe Lage —
   verwischte Liste, Schleier, Blatt — wie auf 17 und 45. */
.kartenseite--zurueck,
.konto--zurueck,
.loeschfolgen--zurueck {
  filter: blur(var(--schleier-unschaerfe));
  opacity: var(--schleier-deckkraft);
  pointer-events: none;
}

.kartenseite__kopf {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: flex-end;
  min-height: var(--btn-hoehe-ghost);
}

/* Klein und ruhig: keine Flaeche, kein Rand, nur das Kreuz — Terracotta
   bleibt den Hauptaktionen (Kap. 9). Die Trefferflaeche ist trotzdem die
   volle Knopfhoehe aus Kap. 4, damit der Daumen sie sicher trifft. */
/* DER ENTWURF ZEICHNET EINE SICHTBARE SCHEIBE, KEIN FREISTEHENDES KREUZ
   (WI-0097). Auf `14-card-detail`, `15-card-detail-conquered` und allen drei
   16ern steht das Kreuz in einem 34px-Kreis mit gedaempfter Flaeche und
   feinem Rand. Die App hatte es transparent gesetzt; auf einem dunklen
   Bildschirm war damit nur ein Strichpaar zu sehen, das je nach Untergrund
   verschwand — und die Trefferflaeche war unsichtbar.

   Die Trefferflaeche bleibt die volle Knopfhoehe (44px, Designspec Kap. 2:
   grosse Tippziele). Sichtbar ist davon der 34px-Kreis in der Mitte — das ist
   der uebliche Weg, ein kleines Zeichen mit einem grossen Ziel zu versehen,
   und keine zweite Groesse. */
.kartenseite__schliessen {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--btn-hoehe-ghost);
  height: var(--btn-hoehe-ghost);
  padding: calc((var(--btn-hoehe-ghost) - var(--kreuz-scheibe)) / 2);
  border: 0;
  background: transparent;
  color: var(--ghost-text);
  cursor: pointer;
}

.kartenseite__schliessen > * {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: var(--space-2);
  border: var(--kreuz-rand);
  border-radius: var(--radius-pille);
  background: var(--kreuz-flaeche);
}

/* --------------------------------------------------------------------------
 * Karte löschen (WI-0070, Artboards 17/18)
 * ------------------------------------------------------------------------ */

/* Der Weg zur Bestaetigung: ein Symbolknopf UNTEN RECHTS AUF DER KARTE
   (HANDOFF §6 Zeile 14/15). Er sitzt bewusst nicht in der Knopfreihe neben
   „Korrigieren" — Loeschen repariert keine falsche Erkennung, und die beiden
   Wege duerfen nicht verschwimmen (Spec 4.4a).

   Die Karte ist in der Buehne zentriert; die Verschiebung rechnet deshalb von
   der Mitte an ihre rechte Kante und von dort um die eigene Breite zurueck. */
.karte-buehne__loeschen {
  position: absolute;
  /* Auf der Hoehe der Kartennummer, nicht darueber: der Entwurf setzt den
     Kreis in die freie Zeile UNTER der Werteliste (Artboard 14). Die Karte
     der App ist gedraengter als der Prototyp — sitzt der Kreis zu hoch,
     verdeckt er die Einheit der letzten Wertezeile. */
  bottom: var(--space-1);
  left: 50%;
  transform: translateX(calc(var(--kd-breite) / 2 - 100% - var(--space-3)));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--loeschknopf-groesse);
  height: var(--loeschknopf-groesse);
  padding: 0;
  border: var(--ghost-rand);
  border-color: var(--feld-rand);
  border-radius: var(--radius-pille);
  background: var(--loeschknopf-flaeche);
  /* Terracotta bleibt den Hauptaktionen (Designspec Kap. 9) — und die
     Hauptaktion dieser Abfrage ist „Behalten", nicht das Loeschen. */
  color: var(--ghost-text);
  cursor: pointer;
}

.ikone--papierkorb {
  width: var(--icon-loeschen);
  height: var(--icon-loeschen);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Der Schleier ueber dem verdeckten Bildschirm, und darauf das unten
   verankerte Blatt (HANDOFF §6 Zeile 17). */
/* `fixed`, nicht `absolute`: der Schleier gehoert dem BILDSCHIRM, nicht dem
   Inhaltskasten der Kartenseite. Der hoert oberhalb der schwebenden Leiste auf
   (--karte-fuss) — ein Blatt darin haette rund hundert Pixel Luft unter sich
   gehabt, statt wie im Entwurf unten zu sitzen. */
/* DIE LAGE, IN DER EIN BLATT VON UNTEN LIEGT (Artboards 17 und 20).
   Schleier ueber allem, das Blatt am unteren Rand. Sie gehoert keinem der
   beiden Blaetter allein — die Loeschabfrage und das Filterblatt liegen
   gleich, sie sehen darin nur verschieden aus. */
.blattlage {
  position: fixed;
  inset: 0;
  z-index: 2;
  /* Systemraender (WI-0417): JEDES Blatt in dieser Lage — Filter,
     Loeschabfrage, Abmelden, Konto loeschen, Nachrichten —
     steht ueber dem Home-Indikator und unter der Statusleiste. Der Schleier
     ist absolut gesetzt und deckt weiter den ganzen Schirm. */
  padding-top: var(--sicher-oben);
  padding-bottom: var(--sicher-unten);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.blattlage__schleier {
  position: absolute;
  inset: 0;
  background: var(--schleier-flaeche);
}

/* DAS FILTERBLATT HAT SEINEN EIGENEN SCHLEIER (WI-0112). §11 fuehrt neben
   --cs-scrim einen zweiten Ton und schreibt seinen Ort daneben: „filter
   sheet". Die App hatte fuer beide Lagen denselben genommen, und --cs-scrim-soft
   stand als eines der Token da, die der Handoff ausschreibt und niemand
   benutzt. Der Unterschied ist klein und gewollt: unter der Loeschabfrage
   soll der Bildschirm weiter zuruecktreten als unter dem Filter, bei dem man
   sehen will, was der Filter gerade tut. */
.blattlage[data-filterlage] .blattlage__schleier {
  background: var(--cs-scrim-soft);
}

.loeschen__blatt {
  position: relative;
  margin: 0 var(--space-4) var(--space-6);
  padding: var(--space-6);
}

.loeschen__titel {
  margin: 0;
}

/* Der gruene Hinweis traegt den Satz, ohne den diese Abfrage nicht stehen
   duerfte: derselbe Fund gibt dieselbe Karte zurueck (HANDOFF §7 Regel 2). */
.loeschen__wurf {
  margin: 0;
  line-height: var(--zeilenhoehe-fliess);
}

/* Der benannte Grund einer Absage — etwa eine Karte in einer laufenden
   Partie. Er faerbt sich wie jede andere Warnung, nicht wie ein Absturz. */
.loeschen__grund {
  margin: 0;
  color: var(--warn-icon);
}

/* --------------------------------------------------------------------------
 * Die Karte (Kap. 6)
 * ------------------------------------------------------------------------ */

.karte-buehne {
  perspective: var(--perspektive);
  display: flex;
  justify-content: center;
  position: relative;
}

/* Die Wischflaeche (WI-0034/0035) — im Vollbild die Buehne, auf der
   Kartenseite seit WI-0051 der ganze Block darum. Beide bewegen sich gleich,
   deshalb haengen die Regeln am Merkmal und nicht mehr an der Klasse.
   `pan-y` teilt die Zustaendigkeit auf: senkrecht scrollt weiter der Browser,
   waagerecht blaettert die App. Ohne diese Zeile scrollte die Seite waehrend
   des Wischens mit. */
[data-wisch] {
  touch-action: pan-y;
  transition: transform var(--wisch-dauer) ease-out;
}

/* Solange der Finger liegt, folgt die Flaeche ihm ohne Nachlauf; erst beim
   Loslassen federt sie in die Ruhelage zurueck. */
[data-wisch][data-wischt] {
  transition: none;
}

/* --------------------------------------------------------------------------
 * Die maximierte Karte (WI-0035)
 * ------------------------------------------------------------------------ */

/* Sie legt sich ueber alles: keine Knoepfe, kein Datenblock, keine Tableiste —
   nur die Karte und der Weg zurueck. `overflow: hidden` ist hier kein
   Schoenheitsmittel, sondern die Bildkante, an der die gewischte Karte
   wirklich verschwindet. Die Reihenfolge in der Spalte ist die des DOM
   (WI-0050): oben die Karte, darunter der Schliessen-Knopf. */
.kartevoll {
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: var(--raum-verlauf);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--kv-rand);
  padding: var(--kv-rand);
  /* Das Kreuz oben rechts unter die Statusleiste, die Leseregion ueber den
     Home-Indikator (WI-0417). */
  padding-top: calc(var(--kv-rand) + var(--sicher-oben));
  padding-bottom: calc(var(--kv-rand) + var(--sicher-unten));
}

/* Die Schliesszeile (Handoff v2 §17): das 34px-Kreuz rechts, seit v3 der
   Stand links daneben. Sie ersetzt den `Schließen`-Knopf, der bis dahin UNTER
   der Karte stand — und was sie einspart, bekommt die Leseregion darunter. */
.kartevoll__kopf {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: none;
  min-height: var(--btn-hoehe-ghost);
}

.karte-buehne--voll {
  flex: none;
  width: 100%;
  align-items: center;
}

/* --------------------------------------------------------------------------
 * Die maximierte Karte (Artboard 15b, Handoff v3 §17)
 *
 * Das Ziel des Doppeltipps. Sie legt sich wie die Vollbildansicht ueber alles
 * — nur steht darunter nichts als die Positionspunkte: kein Wurf, keine
 * Kette, kein Aktionsblock, keine Tableiste. Wer die Kartenkunde will, nimmt
 * auf 14/15 die Pille `Weitere Kartendetails`.
 *
 * `overflow: hidden` ist wieder die Bildkante, an der die gewischte Karte
 * verschwindet — und zugleich das, was die beiden Nachbarstreifen zu
 * Streifen macht: sie liegen ueber den Rand hinaus und werden hier
 * beschnitten.
 * ------------------------------------------------------------------------ */
.kartemax {
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: var(--raum-verlauf);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--km-rand);
  /* Wie die Vollbildkarte: Kreuz und Punktreihe aus den Systemraendern
     (WI-0417). */
  padding-top: calc(var(--km-rand) + var(--sicher-oben));
  padding-bottom: calc(var(--km-rand) + var(--sicher-unten));
}

/* Die Kopfzeile: Stand links, Kreuz rechts (§17). Dieselbe Hoehe wie die
   Schliesszeile der Vollbildansicht — es ist derselbe Knopf.

   RECHTSBUENDIG, NICHT `space-between`: den Stand nach links schiebt seine
   eigene Aussenfuge (siehe `.kartenstand`). Mit `space-between` waere das
   Kreuz nach links gewandert, sobald der Stand fehlt — und er fehlt jedes
   Mal, wenn die Karte gar nicht in der Garagenliste steht. */
.kartemax__kopf {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: none;
  min-height: var(--btn-hoehe-ghost);
}

/* DIE KOPFZEILE DER REAKTIONEN (WI-0330, 16r-2). Liegt das Reaktionsblatt
   ueber der Karte, ist der Bildschirm `16r-*`, und der zeichnet links nach
   rechts: `‹`-Scheibe, Modellname, Sammelnummer. Kein Zaehler, kein Kreuz —
   die stehen auf 15b, und 15b ist dieser Bildschirm nur mit geschlossenem
   Blatt. Deshalb ist es DIESELBE Zeile mit einem Modifikator und keine
   zweite Kopfzeile daneben. */
.kartemax__kopf--reaktionen {
  justify-content: flex-start;
  gap: var(--space-2);
  /* DIE ZEILE IST SO HOCH WIE DIE SCHEIBE, nicht wie ihre Trefferflaeche.
     Der Entwurf zeichnet 34 px Inhalt, und `inhalt_oben` misst die oberste
     SICHTBARE Kante: mit den 44 px der Trefferflaeche sass die Scheibe 5 px
     tiefer als gezeichnet, und der Merkmalsvergleich meldete das auf allen
     acht `16r-*` (18 statt 13 px, gemessen). */
  min-height: var(--kreuz-scheibe);
}

/* Die Scheibe ist die des Kreuzes (34 px, gedaempfte Flaeche, feiner Rand) —
   nur traegt sie den Winkel nach links. Die 5 px, die ihre 44-px-Trefferflaeche
   rundum ueber die Scheibe hinausragt, nimmt sie als Aussenfuge zurueck: die
   Flaeche bleibt 44 px gross (Designspec Kap. 2), die Scheibe sitzt dort, wo
   der Entwurf sie zeichnet. Dasselbe Verfahren wie an `.freund-zeile__kopf`. */
.kartemax__zurueck {
  margin-inline-start: calc((var(--btn-hoehe-ghost) - var(--kreuz-scheibe)) / -2);
  margin-block: calc((var(--btn-hoehe-ghost) - var(--kreuz-scheibe)) / -2);
}

.kartemax__modell {
  font-size: var(--reaktionen-kopf-modell);
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text-hell);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kartemax__nummer {
  flex: none;
  font-size: var(--reaktion-caption);
  color: var(--raum-text-schwach);
}

/* Die Positionszeile `7 von 14` — auf 15b UND auf 16 dieselbe (§17: „dieselbe
   Zeile wie auf 14/15"), deshalb EINE Klasse fuer beide.

   Die Aussenfuge nach rechts ist es, die den Stand nach links stellt und das
   Kreuz rechts laesst; fehlt der Stand, steht das Kreuz trotzdem rechts. */
.kartenstand {
  margin-inline-end: auto;
  font-size: var(--schrift-klein);
  /* §17 nennt fuer diese Zeile den Ton ausdruecklich: `#8d8272`, also die
     schwaechere der beiden Metastufen (§11 `--cs-text-dim`). Bis WI-0115
     stand hier die hellere — dieselbe Zeile, zwei Toene. */
  color: var(--raum-text-schwach);
}

/* Die Karte selbst sitzt mittig zwischen Kopfzeile und Punktreihe. */
.karte-buehne--max {
  flex: 1;
  width: 100%;
  align-items: center;
  justify-content: center;
}

/* DIE NACHBARKARTEN, die links und rechts ueber den Rand hinausschauen (§17).
   Sie sind Andeutung und kein Bedienelement: 18 px breit, halb durchsichtig,
   und ihr Rand traegt die Seltenheitsfarbe DIESER Nachbarin — deshalb setzt
   das Skript `--r-g` an sie und das Stylesheet keinen festen Ton. */
.kartemax__nachbar {
  position: absolute;
  top: 50%;
  width: var(--km-nachbar-b);
  height: var(--km-hoehe);
  transform: translateY(-50%);
  background: var(--karten-koerper);
  box-shadow: 0 0 0 var(--km-nachbar-rand) var(--r-g);
  opacity: var(--km-nachbar-deckkraft);
  pointer-events: none;
}

.kartemax__nachbar[data-nachbar='links'] {
  left: var(--km-nachbar-versatz);
  border-radius: 0 var(--km-radius) var(--km-radius) 0;
}

.kartemax__nachbar[data-nachbar='rechts'] {
  right: var(--km-nachbar-versatz);
  border-radius: var(--km-radius) 0 0 var(--km-radius);
}

/* Die Positionspunkte unten (§17). Sie zeigen ein Fenster von fuenf, nicht
   die ganze Sammlung — welche fuenf, entscheidet das Skript. */
.kartemax__punkte {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--km-punkt-fuge);
  padding: var(--space-4) 0;
}

.kartemax__punkt {
  width: var(--km-punkt-hoehe);
  height: var(--km-punkt-hoehe);
  border-radius: var(--radius-pille);
  background: var(--km-punkt-ruhe);
}

.kartemax__punkt[data-aktiv='ja'] {
  width: var(--km-punkt-aktiv-b);
  background: var(--color-accent);
}

/* WI-0150 — Die Reaktionen einer Freundeskarte liegen als Blatt UEBER der
   maximierten Karte. Absolute Positionierung nimmt sie aus dem Flex-Fluss:
   Kopf, Foto, Werte und Positionspunkte behalten beim Oeffnen exakt ihre
   Lage.

   WI-0181 — DIE HOEHE STEHT SEITHER FEST (HANDOFF §5.5c): 430 px fuer eine
   Liste, 310 px fuer leer und Fehler, 466 px fuer das Auswahl-Overlay. Vorher
   wuchs das Blatt mit der Liste bis zur Bildschirmhoehe. Der Unterschied ist
   der ganze Sinn des gezeichneten Zustands `16r-reactions-scrolled`: Kopf,
   Griff und Knopf stehen fest, nur die Liste rollt darin — deshalb kann
   nichts unter den Knopf rutschen, und deshalb springt nichts, wenn die
   Liste ankommt. */
.kartemax > .reaktionen--overlay,
.kartemax > .reaktionen__lage {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 2;
  box-sizing: border-box;
}

.kartemax > .reaktionen__lage > .reaktionen {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
}

/* Der Gradientenschleier hebt das Blatt von der Karte ab — er ist der Grund,
   warum die Karte darunter lesbar BLEIBT statt weggeblendet zu werden. */
.kartemax > .reaktionen--overlay::before,
.kartemax > .reaktionen__lage::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 100%;
  height: var(--reaktionen-schleier-hoehe);
  background: var(--reaktionen-schleier);
  pointer-events: none;
}

.kartemax > .reaktionen__lage::before {
  bottom: var(--reaktionen-hoehe-auswahl);
}

/* --------------------------------------------------------------------------
 * Die Leseregion unter der maximierten Karte (Handoff v2 §5.6)
 *
 * SIE ROLLT, UND DAS IST GEZEICHNET. Das Sichtfenster ist 219 px hoch, der
 * fuenfzeilige Fall 299 px — die Kette liegt dann teils unter der Falte, und
 * die Maskenkante von 12 px sagt genau das an. Wer die alte Regel „im Vollbild
 * rollt nichts" geprueft hat, prueft ab v2 das Gegenteil (§17).
 *
 * Die Rollbalken sind ausgeblendet: die Maskenkante ist die Ansage, ein
 * zweiter Streifen daneben waere dieselbe Auskunft ein zweites Mal.
 *
 * DIE ABSCHNITTE STEHEN AN DER LINKEN KANTE DER KARTE (WI-0329, Befund 16-2).
 * Hier stand `padding: 0 var(--wurflage-rand)`, also feste 32 px. Die Karte
 * darueber ist `--kv-breite` breit und mittig in derselben Flaeche, ihre
 * linke Kante liegt damit bei `(100% - --kv-breite) / 2` — gemessen 7 px, und
 * die Abschnitte begannen 32 px weiter innen. Auf dem Schirm waren das rund
 * 25 px Versatz zwischen Karte und dem, was darueber steht: zwei linke
 * Kanten auf einem Bildschirm, der eine Sache erzaehlt.
 *
 * GERECHNET, NICHT ABGESCHRIEBEN. Die Zahl kommt aus der Kartenbreite und
 * geht mit ihr mit — `--kv-breite` ist selbst ein `min()` aus Geraetebreite
 * und freier Hoehe. Eine zweite feste Zahl daneben waere genau der Versatz,
 * der hier gerade behoben wird, sobald die Karte auf einem schmaleren Geraet
 * schrumpft. `max(0px, …)` ist die Schranke fuer den Fall, dass die Karte die
 * ganze Breite nimmt.
 *
 * `--wurflage-fuge` bleibt die senkrechte Fuge und die Maskenkante — nur der
 * seitliche Rand haengt jetzt an der Karte.
 * ------------------------------------------------------------------------ */
.kartevoll__lesen {
  flex: 1;
  align-self: stretch;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--wurflage-fuge);
  padding-block: 0;
  padding-inline: max(0px, calc((100% - var(--kv-breite)) / 2));
  /* Eine Maske liest nur die DECKKRAFT, nie den Farbton — `currentColor`
     ist deshalb hier kein Farbwert, sondern schlicht „ganz deckend", und
     es steht kein roher Wert im Stylesheet. */
  mask-image: linear-gradient(currentColor calc(100% - var(--wurflage-fuge)), transparent);
  -webkit-mask-image: linear-gradient(
    currentColor calc(100% - var(--wurflage-fuge)),
    transparent
  );
  scrollbar-width: none;
}

.kartevoll__lesen::-webkit-scrollbar {
  display: none;
}

/* --------------------------------------------------------------------------
 * `Eckdaten` — der erste Abschnitt der Leseregion (v3 §17, Artboard 16)
 *
 * Er traegt seit v3 die Kunde, die vorher als Metazeile unter der Karte auf
 * 14 und 15 stand: `Gruppe`, `Aufnahmen`, `Fundort`. Kein `Gefunden`-Datum —
 * das steht im Abschnitt darunter und darf sich nicht doppeln.
 *
 * Warum ein `dl` und keine drei `div`: Beschriftung und Wert gehoeren
 * paarweise zusammen, und das sagt ein Definitionsverzeichnis einem
 * Vorleseprogramm, ohne dass es dafuer ein `aria`-Attribut braucht. Das
 * Nebeneinander ist eine Frage der Darstellung, nicht der Bedeutung — also
 * loest es das Stylesheet und nicht der Baum. Jedes Paar sitzt in einem
 * `div`, was der HTML-Standard innerhalb eines `dl` ausdruecklich erlaubt.
 * ------------------------------------------------------------------------ */
.eckdaten__zeile {
  display: grid;
  /* §5.5b: die beiden festen Zellen behalten ihre Breite, der Fundort nimmt
     den Rest. Fehlt er, ist die Zeile zweizellig — `auto auto` bleibt
     gueltig, die dritte Spur entsteht dann gar nicht erst. */
  grid-template-columns: auto auto minmax(0, 1fr);
  gap: var(--datenblock-fuge);
  margin: 0;
  font-size: var(--eckdaten-schrift);
  color: var(--raum-text-meta);
}

.eckdaten__zelle {
  /* Ohne das kann die dritte Zelle nicht schrumpfen, und die Ellipse greift
     nie: eine Rasterzelle hat `min-width: auto`. */
  min-width: 0;
}

.eckdaten__zeile dt {
  color: var(--raum-text-schwach);
  font-size: var(--schrift-abschnitt);
}

/* EINZEILIG, NIE ZWEIZEILIG (§5.5b). Ein langer Fundort wird am ENDE
   zeichenweise beschnitten, Ellipse rechts. Zwei Zeilen sind verboten, weil
   die Zeile dann waechst und die Leseregion schiebt — und es gibt weder
   Kurzinfo noch Aufklappen dazu. */
.eckdaten__zeile dd {
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
 * Der Abschnitt `Fundmarken` im Vollbild (WI-0283, HANDOFF §24.1,
 * Artboard `16-card-fullscreen-marks`)
 *
 * Je Marke eine Zeile: Symbol im Kreis, Name fett, Satz dahinter. Dieselben
 * vier Symbole wie am Foto, nur in der groesseren Scheibe des Abschnitts —
 * und wieder OHNE Seltenheitsfarbe.
 *
 * SIE HIESSEN BIS WI-0329 `markenzeile*` UND SASSEN DESHALB IN EINER PILLE
 * (Befund 16-3). `.markenzeile` gehoert der Markenwahl des Scans (Artboard
 * `11b`, weiter oben in dieser Datei, Zeile ~4831): ein antippbarer Streifen
 * mit `padding`, `border` und `radius: var(--radius-lg)`. WI-0283 hat den
 * Namen fuer die Fundmarke mitbenutzt — die Kaskade hat dann `display`,
 * `align-items` und `gap` ueberschrieben und Polster, Rahmen und Radius der
 * frueheren Regel stehen gelassen. Daraus wurde der Container, den der
 * Entwurf an dieser Stelle nicht zeichnet; `16-card-fullscreen-marks` zeigt
 * eine blanke Inline-Zeile. Dazu setzte `.markenzeile strong` den Namen in
 * der Ueberschriftenfamilie auf h4 (20px) statt auf 12,5px im Fliesstext.
 *
 * Die Zeile heisst jetzt nach ihrem Abschnitt. Wer hier einen Namen
 * hinzufuegt, prueft vorher, ob er in dieser Datei schon jemandem gehoert —
 * zwei Bauteile mit demselben Klassennamen sind kein Stilfehler, sondern eine
 * stille Vererbung zwischen zwei Bildschirmen, die nichts miteinander zu tun
 * haben.
 * ------------------------------------------------------------------------ */

.markenblock__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Inline-Zeile, KEIN Container (§24.1, Artboard 16-card-fullscreen-marks):
   Scheibe, dann Text. Keine Flaeche, kein Rahmen, kein Polster. */
.markenblock__zeile {
  display: flex;
  align-items: center;
  gap: var(--markenzeile-fuge);
}

.markenblock__scheibe {
  width: var(--markenzeile-scheibe);
  height: var(--markenzeile-scheibe);
  flex: none;
  border-radius: 50%;
  background: var(--cs-fill-2);
  border: var(--kreuz-rand);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--raum-text);
}

.markenblock__scheibe .fundmarke__symbol {
  width: var(--markenzeile-symbol);
  height: var(--markenzeile-symbol);
}

.markenblock__text {
  font-size: var(--eckdaten-schrift);
  line-height: 1.35;
  color: var(--raum-text-meta);
}

/* Der Name ist FETT im Fliesstext, nicht eine Ueberschrift: der Entwurf setzt
   `Nachtfund` in derselben Groesse wie den Satz dahinter, nur im kraeftigen
   Schnitt. Familie und Grad stehen hier ausdruecklich, damit kein `strong`
   von irgendwo anders sie wieder bestimmt. */
.markenblock__name {
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text);
}

.wurflage__zeilen,
.kette__zeilen {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.wurflage__zeile {
  display: grid;
  grid-template-columns: var(--wurflage-label) minmax(0, 1fr) var(--wurflage-band);
  gap: var(--space-2);
  align-items: center;
  min-height: var(--wurflage-zeile);
}

.wurflage__label {
  font-size: var(--schrift-klein);
  color: var(--raum-text-gedaempft);
}

.wurflage__spur {
  position: relative;
  display: block;
  height: var(--wurflage-spur);
  border-radius: var(--radius-pille);
  background: var(--balken-spur);
}

/* DREI KANAELE, NIE FARBE ALLEIN (§5.6): die Lage des Markers ist der erste
   und wichtigste, der deutsche Bandname der zweite, die Farbe der dritte. Wer
   Farben nicht unterscheidet, liest die Lage und das Wort. */
.wurflage__marke {
  position: absolute;
  left: var(--lage);
  top: calc((var(--wurflage-marke-h) - var(--wurflage-spur)) / -2);
  width: var(--wurflage-marke-b);
  height: var(--wurflage-marke-h);
  margin-left: calc(var(--wurflage-marke-b) / -2);
  border-radius: calc(var(--wurflage-marke-b) / 2);
  background: var(--band-ton);
  box-shadow: var(--wurflage-marke-schein) var(--band-glow);
}

.wurflage__band {
  text-align: right;
  line-height: var(--zeilenhoehe-eng);
}

.wurflage__bandname {
  display: block;
  font-size: var(--schrift-hinweis-klein);
  font-weight: var(--gewicht-kraeftig);
  color: var(--band-ton);
}

.wurflage__intervall {
  display: block;
  /* HANDOFF §5.6, Spalte 3 der Wurfzeile: `interval font-size: 10.5px;
     color: var(--cs-text-dim)`. Hier stand `--schrift-winzig` (10px) — eine
     halbe Stufe zu klein, und damit lagen die Intervalle auf derselben
     Sprosse wie die Einheiten der Kartenwerte. Gemessen war genau das der
     Grund, aus dem die Groessenleiter von 16 und 16-partial eine Sprosse zu
     viel unterhalb der Kartenwerte fuehrte und die obersten 17px
     herausfielen (WI-0129). Die Zeilenhoehe der Spalte ist 1,25 und die
     Zeile mindestens 30px hoch — die halbe Stufe aendert die Hoehe der
     Leseregion nicht. */
  font-size: var(--schrift-wurf-intervall);
  color: var(--raum-text-schwach);
}

/* Die drei Baender. Die Toene stehen als Tokens des Handoffs da und werden
   hier nur zugewiesen — `Mittelfeld` ist bewusst der ruhigste. */
.wurflage__zeile[data-band='spitze'] {
  --band-ton: var(--cs-good);
  --band-glow: var(--glow-gut);
}

.wurflage__zeile[data-band='mitte'] {
  --band-ton: var(--raum-fliess);
  --band-glow: var(--glow-neutral);
}

.wurflage__zeile[data-band='unten'] {
  --band-ton: var(--warn-icon);
  --band-glow: var(--glow-warn);
}

.wurflage__fest {
  margin: var(--space-2) 0 0;
}

.kette__zeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--schrift-h6);
}

.kette__label {
  width: var(--kette-label);
  flex: none;
  color: var(--raum-text-schwach);
}

.kette__name {
  flex: 1;
  font-weight: var(--gewicht-kraeftig);
}

.kette__datum {
  color: var(--raum-text-gedaempft);
}

/* Der Herkunftsabsatz unter der Zeile `Erobert von` (§17, Artboard 16). Er
   stand bis v3 unter der Karte auf 15 und ist mit der Besitzerkette
   mitgewandert — er erzaehlt dasselbe wie sie. */
.kette__herkunft {
  margin: var(--space-2) 0 0;
}

/* Ausstieg: ab der Schwelle gleitet die Karte sichtbar zur Seite aus dem
   Bild — erst danach wird geblaettert. Seit WI-0051 in beiden Ansichten,
   deshalb am Merkmal `data-wisch` statt an der Vollbild-Buehne. */
[data-wisch][data-fliegt] {
  transition: transform var(--wisch-flug-dauer) ease-in;
}

[data-wisch][data-fliegt='links'] {
  transform: translateX(calc(var(--wisch-flug-weg) * -1));
}

[data-wisch][data-fliegt='rechts'] {
  transform: translateX(var(--wisch-flug-weg));
}

/* Einflug: die naechste Karte kommt von der Gegenseite nach. */
[data-wisch][data-einflug] {
  animation: karte-einflug var(--wisch-flug-dauer) ease-out;
}

[data-wisch][data-einflug='rechts'] {
  --wisch-flug-start: var(--wisch-flug-weg);
}

[data-wisch][data-einflug='links'] {
  --wisch-flug-start: calc(var(--wisch-flug-weg) * -1);
}

@keyframes karte-einflug {
  from {
    transform: translateX(var(--wisch-flug-start));
  }
  to {
    transform: none;
  }
}

.karte {
  /* Ohne Seltenheitsfarbe bleibt die Karte neutral — Kap. 6/7: die Farbe
     kommt erst in Phase 8. Bis dahin gilt die neutrale Vorstufe aus dem
     Token-Block; die Karte muss sie nicht noch einmal setzen. */
  --k-breite: var(--kw-breite);
  --k-hoehe: var(--kw-hoehe);
  --k-radius: var(--kw-radius);
  --k-polster-y: var(--kw-polster-y);
  --k-polster-x: var(--kw-polster-x);
  --k-kreis: var(--kw-kreis);
  --k-kopf: var(--kw-kopf);
  --k-flagge-b: var(--kw-flagge-b);
  --k-flagge-h: var(--kw-flagge-h);
  --k-foto-h: var(--kw-foto-h);
  --k-modell: var(--kw-modell);
  --k-modell-lang: var(--kw-modell-lang);
  --k-land: var(--kw-land);
  --k-label: var(--kw-label);
  --k-label-schrift: var(--kw-label-schrift);
  --k-wert: var(--kw-wert);
  /* Schriftgrade und Balkenhoehe gehoeren zur Kartengroesse: in der
     maximierten Ansicht (WI-0035) wachsen sie mit, sonst stuende grosse
     Karte mit kleiner Schrift da. Seit WI-0097 rechnet auch die Wurfansicht
     ihre Grade aus ihrer Breite — vorher standen dort die globalen Stufen,
     und die Karte schrumpfte auf schmalen Geraeten, ohne dass die Schrift
     mitging. */
  --k-schrift-h5: var(--kw-schrift-h5);
  --k-schrift-h6: var(--kw-schrift-h6);
  --k-gruppe-schrift: var(--kw-gruppe-schrift);
  --k-schrift-winzig: var(--kw-schrift-winzig);
  --k-schrift-mini: var(--kw-schrift-mini);
  --k-balken: var(--kw-balken);

  position: relative;
  width: var(--k-breite);
  height: var(--k-hoehe);
  border-radius: var(--k-radius);
  background: var(--karten-koerper);
  box-shadow: var(--kante-neutral);
  transform-style: preserve-3d;
  transition: transform var(--flip-dauer) var(--flip-kurve),
    opacity var(--erscheinen-dauer) ease, box-shadow var(--zeile-dauer) ease;
  cursor: pointer;
}

/* Die Detailkarte (WI-0038) — dieselbe Karte, auf die freie Hoehe der
   Kartenseite gerechnet. Wie bei der maximierten Ansicht gilt: nur Masse,
   kein eigenes Aussehen. */
.karte--detail {
  --k-breite: var(--kd-breite);
  --k-hoehe: var(--kd-hoehe);
  --k-radius: var(--kd-radius);
  --k-polster-y: var(--kd-polster-y);
  --k-polster-x: var(--kd-polster-x);
  --k-kreis: var(--kd-kreis);
  --k-kopf: var(--kd-kopf);
  --k-flagge-b: var(--kd-flagge-b);
  --k-flagge-h: var(--kd-flagge-h);
  --k-foto-h: var(--kd-foto-h);
  --k-modell: var(--kd-modell);
  --k-modell-lang: var(--kd-modell-lang);
  --k-land: var(--kd-land);
  --k-label: var(--kd-label);
  --k-label-schrift: var(--kd-label-schrift);
  --k-wert: var(--kd-wert);
  --k-schrift-h5: var(--kd-schrift-h5);
  --k-schrift-h6: var(--kd-schrift-h6);
  --k-gruppe-schrift: var(--kd-gruppe-schrift);
  --k-schrift-winzig: var(--kd-schrift-winzig);
  --k-schrift-mini: var(--kd-schrift-mini);
  --k-balken: var(--kd-balken);
}

/* Die maximierte Karte (WI-0035) — dieselbe Karte, auf Bildschirmgroesse
   hochgerechnet. Nur Masse, kein eigenes Aussehen. */
.karte--voll {
  --k-breite: var(--kv-breite);
  --k-hoehe: var(--kv-hoehe);
  --k-radius: var(--kv-radius);
  --k-polster-y: var(--kv-polster-y);
  --k-polster-x: var(--kv-polster-x);
  --k-kreis: var(--kv-kreis);
  --k-kopf: var(--kv-kopf);
  --k-flagge-b: var(--kv-flagge-b);
  --k-flagge-h: var(--kv-flagge-h);
  --k-foto-h: var(--kv-foto-h);
  --k-modell: var(--kv-modell);
  --k-modell-lang: var(--kv-modell-lang);
  --k-land: var(--kv-land);
  --k-label: var(--kv-label);
  --k-label-schrift: var(--kv-label-schrift);
  --k-wert: var(--kv-wert);
  --k-schrift-h5: var(--kv-schrift-h5);
  --k-schrift-h6: var(--kv-schrift-h6);
  --k-gruppe-schrift: var(--kv-gruppe-schrift);
  --k-schrift-winzig: var(--kv-schrift-winzig);
  --k-schrift-mini: var(--kv-schrift-mini);
  --k-balken: var(--kv-balken);
}

/* Die maximierte Karte des Doppeltipps (WI-0114, Artboard 15b) — wieder
   dieselbe Karte, wieder nur Masse. Sie ist die groesste der vier: 353 px
   breit, Fotoband 232 px, Wertezeilen MIT Balken. */
.karte--maximiert {
  --k-breite: var(--km-breite);
  --k-hoehe: var(--km-hoehe);
  --k-radius: var(--km-radius);
  --k-polster-y: var(--km-polster-y);
  --k-polster-x: var(--km-polster-x);
  --k-kreis: var(--km-kreis);
  --k-kopf: var(--km-kopf);
  --k-flagge-b: var(--km-flagge-b);
  --k-flagge-h: var(--km-flagge-h);
  --k-foto-h: var(--km-foto-h);
  --k-modell: var(--km-modell);
  --k-modell-lang: var(--km-modell-lang);
  --k-land: var(--km-land);
  --k-label: var(--km-label);
  --k-label-schrift: var(--km-label-schrift);
  --k-wert: var(--km-wert);
  --k-schrift-h5: var(--km-schrift-h5);
  --k-schrift-h6: var(--km-schrift-h6);
  --k-gruppe-schrift: var(--km-gruppe-schrift);
  --k-schrift-winzig: var(--km-schrift-winzig);
  --k-schrift-mini: var(--km-schrift-mini);
  --k-balken: var(--km-balken);
}

/* DER RAHMEN IST HIER 3 px STATT 2,5, UND DAS GLUEHEN STAERKER (§17). Er ist
   das Erste, was an dieser Ansicht auffaellt, und er traegt die
   Seltenheitsfarbe — deshalb nennt der Entwurf ihn eigens. Es bleibt
   dieselbe Kante wie ueberall, nur eine Stufe kraeftiger; die Farbe kommt
   unveraendert aus `--r-g` / `--r-glow`. */
.karte--maximiert[data-phase='8'] {
  box-shadow: var(--km-kante-gefaerbt);
}

.karte[data-phase='0'] {
  opacity: 0;
  transform: scale(var(--karte-start-skalierung)) rotateY(var(--flip-start));
}

.karte[data-phase='1'] {
  opacity: 1;
  transform: rotateY(var(--flip-start));
}

.karte[data-phase='8'] {
  box-shadow: var(--kante-gefaerbt);
}

.karte__halo {
  position: absolute;
  inset: 0;
  border-radius: var(--k-radius);
  background: var(--halo);
  opacity: 0;
  pointer-events: none;
}

.karte[data-phase='8'] .karte__halo {
  opacity: 1;
  animation: gl-pulse var(--halo-dauer) ease-in-out infinite;
}

@keyframes gl-pulse {
  0%,
  100% {
    opacity: 0.55;
  }
  50% {
    opacity: 1;
  }
}

/* cs-spark / cs-star (Designspec 7.1) — die beiden Bausteine des Aufdeckens
   fuer die hoeheren Seltenheitsstufen. Sie existieren noch nirgends im Repo;
   diese Karte legt sie EINMAL an, wortgetreu nach der Spec, weil die
   Siegesanimation (Kap. 7.2, letzter Absatz) sie WIEDERVERWENDET statt neu zu
   erfinden. Die stufenabhaengigen Aufdeck-Effekte selbst (cs-flash, cs-shock,
   cs-rays-out, cs-shake) sind NICHT Teil dieses Items. */
@keyframes cs-spark {
  0% {
    transform: translateY(0) scale(0.4);
    opacity: 0;
  }
  14% {
    opacity: 1;
  }
  100% {
    transform: translateY(-190px) scale(1);
    opacity: 0;
  }
}

@keyframes cs-star {
  0% {
    transform: scale(0) rotate(0deg);
    opacity: 0;
  }
  22% {
    transform: scale(1.25) rotate(50deg);
    opacity: 1;
  }
  100% {
    transform: scale(0.5) rotate(180deg);
    opacity: 0;
  }
}

.karte__seite {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: var(--k-radius);
  overflow: hidden;
}

.karte__vorderseite {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--k-polster-y) var(--k-polster-x);
}

.karte__rueckseite {
  transform: rotateY(var(--flip-start));
  background: var(--rueckseite-flaeche);
  border: var(--rueckseite-rand) solid var(--cs-back-edge);
  color: var(--cs-back-edge);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
}

.karte__lenkrad {
  width: var(--rueckseite-kreis);
  height: var(--rueckseite-kreis);
}

.karte__serienname {
  text-transform: uppercase;
  letter-spacing: var(--laufweite-serie);
  font-weight: var(--gewicht-fett);
  font-size: var(--k-schrift-h6);
}

.karte__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.karte__gruppe {
  width: var(--k-kreis);
  height: var(--k-kreis);
  flex: none;
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--r-g);
  background: var(--glow-flaeche);
  color: var(--r-g);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-weight: var(--gewicht-fett);
  /* NICHT der Grad des Serienbands daneben (WI-0129): §12 fuehrt Kreis und
     Band als zwei Zeilen mit zwei Groessen — der Kreis in der
     Ueberschriftenfamilie bei 15–18px, das Band im Fliesstext bei
     10,5–12px. Die Herleitung je Kartengroesse steht an
     --kw-gruppe-schrift. */
  font-size: var(--k-gruppe-schrift);
}

.karte__serie {
  flex: 1;
  height: var(--k-kopf);
  border-radius: var(--karte-kopf-radius);
  border: var(--karte-rand) solid var(--r-g);
  background: var(--glow-flaeche);
  color: var(--r-g);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-transform: uppercase;
  letter-spacing: var(--laufweite-serie);
  font-weight: var(--gewicht-fett);
  font-size: var(--k-schrift-h6);
}

.karte__herkunft {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.flagge {
  width: var(--k-flagge-b);
  height: var(--k-flagge-h);
  flex: none;
  display: flex;
  border-radius: var(--space-1);
  overflow: hidden;
}

.flagge > span {
  flex: 1;
}

.karte__land {
  font-family: var(--font-heading);
  /* Der Entwurf setzt das Kuerzel fast so gross wie den Modellnamen daneben
     (21 zu 22 px auf Artboard 13, 18 zu 18 auf 14) — nicht in der kleinen
     Wertestufe, in der es bis WI-0097 stand. */
  font-size: var(--k-land);
  font-weight: var(--gewicht-heading);
  /* Der Entwurf setzt das Kuerzel in den Etikettton (`#a89c88`), nicht in den
     gedaempften Text daneben — Artboards 13b/14/15/15b/16*/16r*. Vor WI-0340
     gab es dafuer kein Token. */
  color: var(--raum-text-etikett);
}

.karte__foto {
  margin: 0 calc(var(--k-polster-x) * -1);
  height: var(--k-foto-h);
  flex: none;
  background: var(--foto-flaeche);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/*
 * DIE LAGE DES AUSSCHNITTS (WI-0127). `object-position` steht hier bewusst mit
 * `50% 50%` — dem Vorgabewert — und wird vom Renderer ueberschrieben, sobald
 * das Foto seine Fahrzeugmitte mitbringt (public/js/card.js
 * `fuelleFotoflaeche`, abgeleitet in `filterchain.objektPosition` aus
 * `FOTOBAENDER`). Ohne gespeicherte Mitte — jedes Foto von vor WI-0127 —
 * bleibt es bei diesem Wert. Wer hier einen anderen setzt, verschiebt jedes
 * Bestandsfoto.
 */
.karte__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Der Vermerk an der Fotoflaeche (HANDOFF §5.1 Zeile 3, Artboards 14/15/16):
   „dein Foto" — oder der Name dessen, der die eroberte Karte gefunden hat.
   Er liegt IN der Fotoflaeche unten rechts, auf einer eigenen dunklen Pille,
   damit er auf jedem Bild lesbar bleibt; die Position ist die einzige Ecke,
   in der weder Silhouette noch Loeschknopf stehen. Fuer das Vorleseprogramm
   ist er gewoehnlicher Text — er sagt etwas, was sonst nirgends steht. */
.karte__fotovermerk {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pille);
  background: var(--foto-vermerk-flaeche);
  font-size: var(--k-schrift-mini);
  color: var(--raum-text-etikett);
}

/* Die Fotoflaeche ist der Bezugsrahmen des Vermerks. */
.karte__foto {
  position: relative;
}

/* --------------------------------------------------------------------------
 * Die Fundmarken (WI-0283, Kartenspec Kap. 8, HANDOFF §24.1)
 *
 * Unten LINKS auf dem Foto, „opposite the photo label bottom right" — und in
 * jeder Ansicht der Karte, weil die Marke zur Karte gehoert und nicht zu einem
 * Bildschirm. Sie traegt keine Seltenheitsfarbe: ihre Farbe bedeutet nichts.
 * ------------------------------------------------------------------------ */

.fundmarken {
  position: absolute;
  left: var(--space-2);
  bottom: var(--space-2);
  z-index: 2;
  display: flex;
  gap: var(--fundmarke-abstand);
}

.fundmarke {
  width: var(--fundmarke-scheibe);
  height: var(--fundmarke-scheibe);
  flex: none;
  /* Die Scheibe ist rund, nicht abgerundet — dieselbe Schreibweise wie an
     jedem anderen Kreis der App (Schliessen-Kreuz, Haken, Gruppenkreis). */
  border-radius: 50%;
  background: var(--fundmarke-flaeche);
  border: var(--fundmarke-rand);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--raum-text);
}

.fundmarke__symbol {
  width: var(--fundmarke-symbol);
  height: var(--fundmarke-symbol);
  flex: none;
  stroke-width: var(--fundmarke-strich);
}

/* --------------------------------------------------------------------------
 * Der Kompaktmodus der Vollbildkarte (Handoff v2 §5.6)
 *
 * Dieselben sechs Kategorien, dieselbe Reihenfolge — zwei Spalten, nur Zahlen,
 * keine Balkenspuren. Was hier an Hoehe frei wird, bekommt die Leseregion
 * darunter. Die Seltenheitsfarbe liest sich weiter an Rand, Gruppenkreis und
 * Kopfbalken; sie geht durch den Wegfall der Balken nicht verloren.
 * ------------------------------------------------------------------------ */
.karte__wertfelder {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2) var(--space-4);
}

.wertfeld {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  border-bottom: var(--karte-hairline);
  padding-bottom: var(--space-1);
}

/* `text-align: left` aus demselben Grund wie bei `.wertzeile__label`
   (WI-0329, Befund 14-6): die Beschriftung haengt an ihrer Spalte, nie an
   dem, was der Bildschirm ringsum vorgibt. */
.wertfeld__label {
  text-align: left;
  font-size: var(--k-label-schrift);
  color: var(--raum-text-gedaempft);
}

.wertfeld__wert {
  font-family: var(--font-heading);
  font-size: var(--k-schrift-h5);
  font-weight: var(--gewicht-heading);
  color: var(--raum-text);
  white-space: nowrap;
}

.silhouette {
  width: 100%;
  height: 100%;
  /* Ausserhalb einer Karte ist das die neutrale Vorstufe (#cfc3ab) — der
     Strich ist damit nie ungueltig, auch auf dem Auswahl-Bildschirm und im
     Scan-Sucher nicht. */
  stroke: var(--r-g);
  fill: none;
}

/* Der Schein gehoert genau an EINE Stelle: an die Silhouette, die in der
   Fotoflaeche der Karte fuer ein fehlendes Foto einspringt (Kap. 6 Punkt 3).
   Weder die Garagenkachel noch die Vorschlagszeile tragen ihn im Entwurf. */
.karte__foto .silhouette {
  filter: var(--silhouette-glow);
}

/* Der Modellname im Kopfbereich (29.08.2026, Kartenspec Kap. 3.3): gross,
   zwischen Flagge und Laenderkuerzel, wo bis dahin das Baujahr stand.
   Was hier NICHT stehen darf, ist eine Kuerzung. Ein Name wie
   `Mercedes-Benz G-Klasse` ist genau das, was ein Spieler zuerst sucht —
   deshalb bricht er um (`overflow-wrap`, kein `nowrap`, kein
   `text-overflow`), und ab der Grenze in card.js faellt er zusaetzlich auf
   den kleineren Grad zurueck. `min-width: 0` ist die Bedingung dafuer, dass
   ein Flex-Kind ueberhaupt umbrechen darf statt seine Nachbarn zu schieben. */
.karte__modell {
  flex: 1;
  min-width: 0;
  /* Mittig zwischen Flagge und Laenderkuerzel — ausgeschrieben und nicht vom
     Bildschirm geerbt, damit die Karte ueberall gleich aussieht. */
  text-align: center;
  font-family: var(--font-heading);
  font-size: var(--k-modell);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
  color: var(--raum-text);
  overflow-wrap: break-word;
  hyphens: auto;
}

.karte__modell[data-lang='ja'] {
  font-size: var(--k-modell-lang);
}

.karte__werte {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1;
}

.wertzeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  opacity: 0;
  transform: translateY(var(--zeile-versatz));
  transition: opacity var(--zeile-dauer) ease, transform var(--zeile-dauer) ease;
}

.wertzeile[data-sichtbar='ja'] {
  opacity: 1;
  transform: none;
}

/* GEMISCHTE SCHREIBUNG, NICHT VERSALIEN (WI-0097).
 *
 * Der Entwurf setzt die sechs Beschriftungen als gewoehnliche Woerter —
 * `Baujahr`, `Gewicht`, `0–100 km/h` — in 11.5 px (Detail) bzw. 12.5 px
 * (Wurf), ohne Sperrung. Die App hatte sie in Versalien mit Laufweite gesetzt;
 * das ist der Stil des KOPFBALKENS (`STRASSENFLOTTE`), und dort bleibt er
 * auch. In der Werteliste kostete er Breite, ohne etwas zu sagen: eine
 * gesperrte Versalzeile braucht rund ein Fuenftel mehr Platz als dasselbe Wort
 * gemischt gesetzt, und `Höchstgeschw.` passte darum nicht in die Spalte.
 *
 * Die eigene Groesse `--k-label-schrift` steht daneben, weil die Beschriftung
 * im Entwurf KLEINER ist als der Wert rechts (11.5 gegen 13) — vorher trugen
 * beide dieselbe Stufe. */
/* LINKSBUENDIG, UND ZWAR AUSDRUECKLICH (WI-0329, Befund 14-6).
 *
 * Der Entwurf setzt die Beschriftung an die linke und den Wert an die rechte
 * Kante ihrer Spalte — eine Haarlinienliste, wie Kartenspec Kap. 2 sie
 * beschreibt. Der Wert hatte sein `text-align: right` immer; die Beschriftung
 * hatte gar keines und erbte damit, was der Bildschirm vorgab. Auf der
 * Kartenseite ist das `.mittig` der Wischflaeche (`text-align: center`), und
 * die sechs Beschriftungen standen in ihrer 88px-Spalte zentriert: die
 * Zeilenanfaenge sprangen von Zeile zu Zeile, weil `Baujahr` und
 * `Höchstgeschw.` verschieden lang sind. Eine Liste ohne gemeinsame linke
 * Kante liest sich nicht als Liste. */
.wertzeile__label {
  width: var(--k-label);
  flex: none;
  text-align: left;
  font-size: var(--k-label-schrift);
  color: var(--raum-text-gedaempft);
}

.wertzeile__abwaerts {
  color: var(--karte-abwaerts);
}

/* Derselbe Pfeil, derselbe Ton, ausserhalb der Karte: die Regel-Einblendung
   des ersten Duells (Kartenspec 3.1) erklaert damit die Umkehrregel von
   Baujahr und 0–100 km/h (WI-0319: nur noch der erste von vier Punkten —
   die anderen drei sind keine Vergleichsrichtung), liegt aber in einem
   Blatt und nicht in einer Wertezeile — ein eigener Klassenname, damit sie
   sich nicht auf das Flex-Layout der Kartenzeile verlaesst, das hier gar
   nicht da ist. */
.duell-regel__pfeil {
  color: var(--karte-abwaerts);
}

.wertzeile__spur {
  flex: 1;
  height: var(--k-balken);
  border-radius: var(--radius-pille);
  background: var(--balken-spur);
  overflow: hidden;
}

.wertzeile__balken {
  display: block;
  height: 100%;
  width: var(--balken);
  border-radius: var(--radius-pille);
  background: var(--balken-fuellung);
  box-shadow: var(--balken-glow);
}

/* Altbestand: eine Karte, die vor der Umstellung auf das Gewicht aufgedeckt
   wurde, zeigt ihre eingefrorene Zeile (Hubraum bzw. Batterie) mit Wert und
   Einheit — aber ohne Balken. Der Balken ist ein Vergleichsmass, und die
   Kategorie gibt es nicht mehr. Die leere Spur bleibt stehen, damit die Zeile
   dieselbe Hoehe hat wie die vier darunter. */
.wertzeile[data-altbestand='ja'] .wertzeile__balken {
  display: none;
}

.wertzeile__wert {
  width: var(--k-wert);
  flex: none;
  text-align: right;
  font-family: var(--font-heading);
  font-size: var(--k-schrift-h5);
  font-weight: var(--gewicht-heading);
  color: var(--raum-text);
}

/* Die Einheit hinter einem Wert („kg", „PS", „km/h") — der Entwurf faerbt sie
   im Etikettton, die Beschriftung links davon (`.wertzeile__label`,
   `.wertfeld__label`) dagegen in `#b5a992`. Die zwei Toene liegen 13 Punkte je
   Kanal auseinander und sind zwei Rollen, nicht eine Stufe (HANDOFF §18.1). */
.wertzeile__einheit {
  font-family: var(--font-body);
  font-size: var(--k-schrift-mini);
  font-weight: var(--gewicht-halb);
  color: var(--raum-text-etikett);
}

/* Links die Nummer, direkt daneben Abzeichen und Marke „EROBERT" — so
   zeichnet der Entwurf sie (Artboards 14 und 16: `Nr. 012` bzw. `Nr. 021 ·
   EROBERT`). Ohne Beiwerk steht die Nummer allein links, wie bisher; ein
   `space-between` haette die Marke an die rechte Kante geschoben, wo der
   Loeschknopf sitzt.

   DIE ZEILE BRICHT AUSDRUECKLICH NICHT UM (WI-0329): seit die Nummer NEBEN
   dem Abzeichen „Werte geschätzt" steht statt an seiner Stelle, koennen auf
   einer geschaetzten eroberten Karte drei Teile in dieser Zeile liegen. Sie
   darf davon nicht zweizeilig werden — die Kartenhoehe ist gerechnet
   (--kd-*), und eine zweite Zeile schoebe den Loeschknopf auf die
   Werteliste. Die Nummer haelt ihre Breite, der Rest weicht zurueck. */
.karte__fuss {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  /* 11 px im Entwurf (Artboards 13-16), nicht die globale Ministufe. */
  font-size: var(--k-schrift-winzig);
  color: var(--raum-text-schwach);
}

/* Die laufende Sammelnummer (Produktspec 4.4, Artboards 13-16). Sie steht
   ganz links und wird nie gekuerzt: `Nr. 012` ist die Auskunft, die diese
   Karte in der Sammlung verortet. */
.karte__nummer {
  flex: none;
}

/* Das Abzeichen „Werte geschätzt" (Spec 6.2a Regel 3, 6.2d Regel 5). Es sagt
   dem Spieler, dass die Zahlen dieser Karte nicht belegt sind, und hat seit
   WI-0329 seinen EIGENEN Platz neben der Nummer statt an ihrer Stelle.

   Es traegt KEINE eigene Farbe und keine Flaeche: der Entwurf zeichnet es an
   dieser Stelle gar nicht (gemeldete Brettluecke), und ein erfundener Ton
   waere genau das, was Designspec Kap. 9 verbietet. Reisst die Zeile, weicht
   dieser Teil zurueck — nicht die Nummer. */
.karte__geschaetzt {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Die Marke „EROBERT" (Kartenspec Kap. 8, Artboard 15). Sie steht NEBEN der
   Nummer in derselben Fussleiste — eine Auskunft, keine Zierde, und sie
   verdraengt nichts: eine Karte kann zugleich geschaetzte Werte tragen. Auf
   der Rueckseite steht sie nicht (Kartenspec Kap. 10). */
.karte__erobert {
  border-radius: var(--radius-pille);
  background: var(--erobert-marke);
  color: var(--erobert-marke-text);
  font-weight: var(--gewicht-fett);
  padding: var(--space-1) var(--space-2);
}

/* Rechts in der Fussleiste stand bis zum 29.08.2026 die Stufen-Pille
   (`SELTEN ◆`). Sie ist entfallen (Designspec Kap. 6): die Seltenheit ist
   spielbar und steht deshalb in der Werteliste — als Punktzeile — und als
   Farbe an Kopfbalken und Gruppenkreis. Sonst nirgends. */

/* --------------------------------------------------------------------------
 * Garage
 * ------------------------------------------------------------------------ */

/* Kopfzeile der Garage: Ueberschrift links, Filter und Konto rechts daneben.
 *
 * Staging-Rueckmeldung #11: neben der Ueberschrift blieb der halbe Bildschirm
 * leer, waehrend Filterzeile und Konto-Knopf zwei volle Zeilen zwischen den
 * Gruppen-Chips und dem Raster belegten. Beides steht jetzt in dieser einen
 * Zeile — das Raster rueckt um zwei Zeilen nach oben. Die Zeile bricht NICHT
 * um: die Ueberschrift darf schrumpfen, die Bedienelemente behalten ihre
 * Trefferflaeche aus --btn-hoehe-ghost. */
/* DIE DICHTE DES STAPELS (WI-0098). `.gestapelt` setzt ueberall
   `--space-3` (13,2 px) zwischen die Bloecke. Der Entwurf setzt in der Garage
   6 px unter die Ueberschrift, 8 px unter die Zaehlerzeile und 16–18 px unter
   Balken und Chipreihe — die Reihenfolge stimmte also, die Luft nicht. Der
   Unterschied kostete zusammen rund eine Kachelreihe. */
.gestapelt--garage {
  flex: 1;
  min-height: 0;
  gap: var(--space-2);
}

.gestapelt--garage .fortschritt {
  margin-bottom: var(--space-1);
}

/* WI-0394 — „Nach oben": VORLAEUFIG, im Entwurf nicht gezeichnet (Rob,
   21.10.2026; Luecke fuer HANDOFF.md, Garage). Zurueckhaltender Zweitstil wie
   die Tableiste, rechts UEBER ihr — `--buehne-unten` ist ihr Freiraum. */
.garage__nach-oben {
  position: fixed;
  right: var(--tableiste-unten);
  bottom: calc(var(--buehne-unten) + var(--space-2));
  /* Ueber den Home-Indikator, wie die Leiste darunter (WI-0417). */
  margin-bottom: var(--sicher-unten);
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--tableiste-knopf);
  height: var(--tableiste-knopf);
  padding: 0;
  border: var(--tableiste-randbreite) solid var(--tableiste-randfarbe);
  border-radius: var(--radius-pille);
  background: var(--tableiste-flaeche);
  backdrop-filter: var(--tableiste-blur);
  box-shadow: var(--shadow-lg);
  color: var(--raum-fliess);
  cursor: pointer;
}

.garage__nach-oben[hidden] {
  display: none;
}

.garage__nach-oben .ikone {
  width: var(--schrift-h4);
  height: var(--schrift-h4);
}

@media print {
  .garage__nach-oben {
    display: none;
  }
}

.garage__kopf {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-2);
  justify-content: space-between;
}

/* Die eine Zeile ueber dem Balken: Kartenzahl und Katalogfortschritt in
   „Body small" (§12, 13–14,5 px). Sie stand bis WI-0098 als zwei Zeilen um
   den Balken herum. Seit WI-0313 nennt sie das Sammelziel
   (`1 Quartett komplett · 12 Modelle`), und der Katalogstand ist der Balken. */
.garage__zeile {
  margin: 0;
  /* Sie darf schrumpfen, nicht der Ringstreifen daneben: der Streifen ist ein
     Trefferziel mit festem Mass, der Satz ist Text und kann kuerzen. */
  flex: 1;
  min-width: 0;
  font-size: var(--garage-meta);
}

/* --------------------------------------------------------------------------
 * DIE FORTSCHRITTSZEILE — TEXT LINKS, FUENF SELTENHEITSRINGE RECHTS
 * (HANDOFF §1506 und §4.5c, Artboards 18/19/19b; WI-0313).
 *
 * „The rarity filter does not add a second [row]. It rides on the line that is
 * already there: the progress line … becomes a flex row, text left, five
 * rarity dots right." Vorher war der Streifen in der App gar nicht gebaut; was
 * hier NICHT entstehen durfte, ist eine zweite Steuerzeile im Kopf — auf
 * 393 px kostet jede Zeile eine Reihe Kacheln.
 * ------------------------------------------------------------------------ */
.garage__fortschrittszeile {
  display: flex;
  align-items: center;
  gap: var(--fortschrittszeile-luecke);
}

/* Der Streifen IST das Trefferziel, nicht der einzelne Ring (§4.5c): die Zeile
   haelt ihre 44 px, auch wenn ein Ring nur 20 px gross ist. */
.stufenringe {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--stufenringe-luecke);
  min-height: var(--stufenringe-zeile);
}

.stufenring {
  flex: none;
  width: var(--stufenring);
  height: var(--stufenring);
  padding: 0;
  border: var(--stufenring-rand) solid var(--stufenring-farbe);
  border-radius: var(--radius-pille);
  /* „no fill" — der Ring ist ein Ring. Ausgefuellt waere er von einem
     Seltenheitsring einer Karte nicht zu unterscheiden (§4.5c). */
  background: transparent;
  opacity: var(--stufenring-aus);
  cursor: pointer;
}

.stufenringe--deckbau {
  --stufenring: var(--stufenring-deckbau);
  --stufenringe-luecke: var(--stufenringe-luecke-deckbau);
}

.stufenring--an {
  width: var(--stufenring-an);
  height: var(--stufenring-an);
  background: color-mix(in srgb, var(--stufenring-farbe) 22%, transparent);
  opacity: 1;
}

/* DIE FUENF FARBEN KOMMEN AUSSCHLIESSLICH AUS DER `--cs-r-*`-TABELLE
   (§11, Designspec Kap. 9 „The rarity colour comes EXCLUSIVELY from the
   --cs-r-* table"). Sie stehen hier und nicht im Markup, damit kein Bauteil
   sich seinen eigenen Ton ausdenkt — und in der Reihenfolge von §11, die
   §4.5c fuer den Streifen ausdruecklich nennt. */
.stufenring[data-stufenring='haeufig'] {
  --stufenring-farbe: var(--cs-r-common);
}
.stufenring[data-stufenring='ungewoehnlich'] {
  --stufenring-farbe: var(--cs-r-uncommon);
}
.stufenring[data-stufenring='selten'] {
  --stufenring-farbe: var(--cs-r-rare);
}
.stufenring[data-stufenring='episch'] {
  --stufenring-farbe: var(--cs-r-epic);
}
.stufenring[data-stufenring='legendaer'] {
  --stufenring-farbe: var(--cs-r-legendary);
}

/* WI-0221 — DER BENANNTE FEHLERZUSTAND: die Antwort trug die Facetten nicht,
   aus denen die Filterzahlen kommen. Er steht in derselben Groesse wie die
   Zeile darueber und in der Zustandsfarbe fuer „Achtung" — kein Kasten, kein
   Symbol: es ist ein Satz, den man lesen soll, und keine Meldung, die man
   wegklickt. Farben und Abstaende kommen aus den Tokens (§11). */
.garage__hinweis {
  margin: 0;
  color: var(--warn-icon);
  font-size: var(--garage-meta);
}

.garage__aktionen {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
}

.garage__titel {
  font-family: var(--font-heading);
  font-size: var(--garage-titel);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Konto in der Kopfzeile als SCHEIBE (Artboards 18, 19, 21): 38 px rund, mit
   dem Anfangsbuchstaben des Spielers in der Ueberschriftenschrift. Sie kostet
   ein Viertel der Breite der frueheren Wortpille — und genau die Breite
   brauchen Ueberschrift und Filterpille daneben auf 393 px. */
.kontoscheibe {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--kontoscheibe);
  height: var(--kontoscheibe);
  padding: 0;
  border: var(--ghost-rand);
  border-color: var(--cs-accent-glow);
  border-radius: var(--radius-pille);
  background: var(--kontoscheibe-flaeche);
  color: var(--color-accent-400);
  cursor: pointer;
}

.kontoscheibe__anfang {
  font-family: var(--font-heading);
  font-size: var(--schrift-h5);
  font-weight: var(--gewicht-heading);
  line-height: 1;
}

.fortschritt {
  height: var(--fortschritt-hoehe);
  border-radius: var(--radius-pille);
  background: var(--balken-spur);
  overflow: hidden;
}

.fortschritt__balken {
  display: block;
  height: 100%;
  width: var(--balken);
  border-radius: var(--radius-pille);
  background: var(--color-accent);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--feld-rand);
  background: var(--feld-flaeche);
  color: var(--raum-text-gedaempft);
  font-family: var(--font-body);
  font-size: var(--schrift-klein);
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
}

/* DIE GRUPPENREIHE DER GARAGE (Artboards 18/19/21, HANDOFF §12 „Chip" und §13
   „Chip row gap"). Sechs Chips passen dort auf die Hoehe, auf der die App zwei
   zeigte — der Unterschied ist 11 statt 12 px Schrift und 6 statt 8,8 px
   Luecke. Beides steht hier und nicht auf `.chips`/`.chip`, damit die
   Chipreihen anderer Bildschirme unveraendert bleiben. */
/* WI-0313 — EIN FESTES 3x3-RASTER STATT EINER UMBRECHENDEN REIHE (§5.5b7).
   `display:flex;flex-wrap:wrap` von `.chips` darueber machte die Reihe so
   lang, wie die Sammlung breit ist: eine Klasse stand jede Woche woanders.
   Das Raster ist der eigentliche Nutzen dieses Bedienelements — „the point of
   this control is that a child learns where their classes live". */
.chips--gruppen {
  display: grid;
  grid-template-columns: repeat(var(--chip-raster-spalten), 1fr);
  gap: var(--chips-luecke);
}
.chips--gruppen .chip {
  /* Zweizeilige Zelle: Klassenname oben, Zaehler unten. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0;
  min-width: 0;
  height: var(--chip-zelle-hoehe);
  padding: var(--chip-zelle-polster);
  border-radius: var(--chip-zelle-radius);
  font-size: var(--chip-schrift);
  /* SEIT WI-0213 SIND DIE CHIPS KNOEPFE (Artboard 19b: sie filtern). Ein
     `<button>` erbt die Zeilenhoehe NICHT — ohne diese Zeile waere die Reihe
     beim Wechsel des Elements um ein Pixel gewandert, und die Gruppenanzeige
     sollte sich gerade NICHT veraendern. */
  line-height: var(--zeilenhoehe-fliess);
}

/* Der Klassenname: eine Zeile, abgeschnitten statt umgebrochen —
   `Nutzfahrzeug` ist das laengste Wort und muss in 94 px Innenbreite passen,
   ohne die Zelle zu dehnen (sie ist 39 px hoch und zweizeilig belegt). */
.chips--gruppen .chip__klasse {
  max-width: 100%;
  overflow: hidden;
  font-size: var(--chip-klasse-schrift);
  line-height: var(--chip-klasse-zeile);
  /* 700 an der angefangenen und der leeren Klasse, 800 an der vollen — so
     zeichnet es das Artboard, und es ist dieselbe Aussage wie die Farbe: die
     volle Klasse tritt vor. */
  font-weight: var(--gewicht-kraeftig);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.chips--gruppen .chip--vollstaendig .chip__klasse,
.chips--gruppen .chip--gefiltert .chip__klasse {
  font-weight: var(--gewicht-fett);
}

/* DIE ZAHL AUF DEM CHIP steht in einem eigenen Feld, damit sie ihre Farbe
   behalten kann, wenn der Rahmen um sie herum eine andere traegt: Salbei
   heisst „ein Quartett ist voll", Terrakotta heisst „danach wird gefiltert".
   Zwei Aussagen, zwei Farben — §5.5b7 verlangt ausdruecklich, dass die eine
   die andere nicht schluckt. Sonst erbt sie alles vom Chip. */
.chip__zaehler {
  color: inherit;
}

/* Die zweite Zeile der Zelle: die `n×`-Pille und der Bruch daneben, 4 px
   Luecke und KEIN Pluszeichen (WI-0313, am Artboard gemessen). */
.chips--gruppen .chip__zaehler {
  display: flex;
  align-items: center;
  gap: var(--chip-zaehler-luecke);
  font-size: var(--chip-zaehler-schrift);
  line-height: var(--chip-zaehler-zeile);
  font-weight: var(--gewicht-fett);
}

/* Die Vielfachheit als Pille — sie sagt nicht „fertig", sondern WIE OFT. */
.chips--gruppen .chip__mal {
  border-radius: var(--radius-pille);
  padding: var(--chip-mal-polster);
  background: var(--chip-mal-flaeche);
  color: var(--chip-mal-text);
}


/* Die sechs Farben liegen in EINER Reihe — sie tragen keine Beschriftung, nur
   die Scheibe. Die Luecke ist die kleine der Leiter: sechs Scheiben zu 52 px
   plus fuenf Luecken muessen auf 393 px nebeneinander passen, sonst faellt die
   sechste allein in eine zweite Zeile und der Satz „Sechs Farben" darueber
   stimmt optisch nicht mehr. */
.chips--farben {
  gap: var(--space-1);
}

.chips--farben .chip {
  padding: 0;
  border: none;
  background: transparent;
}

/* Die gewaehlte Farbe traegt den staerkeren Rand aus dem Entwurf; der Chip
   selbst bleibt farblos, damit die Avatarfarbe nirgends auf eine Flaeche
   ausserhalb ihres Kreises gerät (§4.5b). */
.chips--farben .chip[aria-pressed='true'] .avatar {
  border-width: var(--avatar-rand-stark);
}

/* Die Altersstufen sind auf 02 volle Zeilen, keine Reihe kleiner Pillen.
   `margin-bottom: auto` schiebt die Aktionsgruppe darunter ans untere Ende —
   Designspec Kap. 10.3 Punkt 1 und 3: Hauptaktion im unteren Drittel, und
   keine leere Flaeche darunter. */
.chips--gestapelt {
  flex-direction: column;
  align-items: stretch;
  margin-bottom: auto;
}

.chips--gestapelt .chip {
  justify-content: flex-start;
  min-height: var(--anmeldung-zeile);
  padding: var(--space-2) var(--space-4);
}

/* `.chip--rest` STAND HIER — der Restchip der Gruppenreihe (`n Klassen
   offen`) und der `Filter löschen`-Knopf daneben. Beide sind mit WI-0313
   fort: das Raster zeigt jetzt alle neun Klassen, also auch die leeren, und
   eine zehnte Zelle, die die leeren ZAEHLT, steht auf keinem Artboard. Die
   gestrichelte Behandlung ist nicht verloren — sie sitzt seitdem an der
   leeren Klasse selbst (`.chips--gruppen .chip--klasse-leer`). */

/* DIE AVATARSCHEIBE (HANDOFF §4.5b, Artboard 01b; WI-0171).
   Sie ersetzt den Buchstaben-Platzhalter des Zeichensatzes aus WI-0090: der
   Avatar wird ERZEUGT und nicht nachgeliefert — Anfangsbuchstabe des
   Spitznamens auf einer getoenten Scheibe. Es gibt deshalb nichts mehr, auf
   das dieses Feld warten muesste.
   Die Groesse kommt aus dem Modifikator, nicht von hier: dieselbe Scheibe
   steht auf 01b mit 112 px und im Kopf einer fremden Sammlung mit 44 px. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--avatar-kopf);
  height: var(--avatar-kopf);
  border-radius: var(--radius-pille);
  border: var(--avatar-rand) solid var(--avatar-sand-rand);
  background: var(--avatar-sand-ton);
  color: var(--avatar-sand);
  font-family: var(--font-heading);
  font-size: var(--avatar-kopf-glyphe);
  font-weight: var(--gewicht-heading);
  line-height: 1;
}

/* Die sechs Toene, je Farbe der Dreiklang aus §4.5b. Der Klassenname traegt
   den Wert, den auch die Datenbank speichert — so gibt es zwischen
   gespeicherter Farbe und Darstellung keine zweite Uebersetzungstabelle. */
.avatar--5fa39b {
  border-color: var(--avatar-tuerkis-rand);
  background: var(--avatar-tuerkis-ton);
  color: var(--avatar-tuerkis);
}
.avatar--d97ea0 {
  border-color: var(--avatar-rose-rand);
  background: var(--avatar-rose-ton);
  color: var(--avatar-rose);
}
.avatar--7f9ede {
  border-color: var(--avatar-kornblume-rand);
  background: var(--avatar-kornblume-ton);
  color: var(--avatar-kornblume);
}
.avatar--d9b24a {
  border-color: var(--avatar-senf-rand);
  background: var(--avatar-senf-ton);
  color: var(--avatar-senf);
}
.avatar--a98cd9 {
  border-color: var(--avatar-flieder-rand);
  background: var(--avatar-flieder-ton);
  color: var(--avatar-flieder);
}
.avatar--c9c0a8 {
  border-color: var(--avatar-sand-rand);
  background: var(--avatar-sand-ton);
  color: var(--avatar-sand);
}

/* Die Groessen der Leiter aus §4.5b. */
.avatar--gross {
  width: var(--avatar-gross);
  height: var(--avatar-gross);
  border-width: var(--avatar-rand-stark);
  font-size: var(--avatar-gross-glyphe);
}
.avatar--wahl {
  width: var(--avatar-wahl);
  height: var(--avatar-wahl);
  font-size: var(--avatar-wahl-glyphe);
}
.avatar--mittel {
  width: var(--avatar-mittel);
  height: var(--avatar-mittel);
  font-size: var(--avatar-mittel-glyphe);
}
.avatar--kopf {
  width: var(--avatar-kopf);
  height: var(--avatar-kopf);
  font-size: var(--avatar-kopf-glyphe);
}
/* Die Scheibe der Gegnerzeile von Artboard 22 (WI-0330, 22-3): 34 px, Glyphe
   15 px. Die Breite ist DASSELBE Mass, das die Zeile schon fuehrt — sie steht
   nicht zweimal da. */
.avatar--duellzeile {
  width: var(--duell-offen-zeichen);
  height: var(--duell-offen-zeichen);
  font-size: var(--duell-offen-zeichen-glyphe);
}
/* Die zwei Duellstufen (WI-0188): 48 px auf der Einsatzfrage (27), 40 px an
   der Gegnerzeile des Auftakts (28a). */
.avatar--bestaetigung {
  width: var(--avatar-bestaetigung);
  height: var(--avatar-bestaetigung);
  font-size: var(--avatar-bestaetigung-glyphe);
}
.avatar--auftakt {
  width: var(--avatar-auftakt);
  height: var(--avatar-auftakt);
  font-size: var(--avatar-auftakt-glyphe);
}
/* Die zwei kleinen Stufen des Reaktionsblatts (§5.5c): 30 px an einer
   obersten Zeile, 24 px an einer Antwort. Der Groessenunterschied IST die
   Ebenenauskunft — zusammen mit dem Einzug sagt er, was Antwort auf was ist. */
.avatar--reaktion {
  width: var(--avatar-reaktion);
  height: var(--avatar-reaktion);
  font-size: var(--avatar-reaktion-glyphe);
}
.avatar--antwort {
  width: var(--avatar-antwort);
  height: var(--avatar-antwort);
  font-size: var(--avatar-antwort-glyphe);
}

.chip--vollstaendig {
  border-color: var(--gruen-rand);
  background: var(--gruen-flaeche);
  color: var(--gruen-text);
}

/* --------------------------------------------------------------------------
 * DIE DREI BEHANDLUNGEN DER SAMMLUNG AM KLASSENCHIP (§5.5b7; WI-0313).
 *
 * Sie stehen NUR unter `.chips--gruppen`: `.chip--vollstaendig` darueber
 * tragen auch die Bereitschaftspille im Duell und die Zeile auf 45e, und die
 * gehoeren anderen Artboards. Die Werte sind an den Artboards 19 und 19b
 * gemessen, nicht aus der Prosa abgeschrieben.
 *
 *   salbei, 1 px Rand      → mindestens ein Quartett dieser Klasse ist voll
 *   gedaempft, 1 px Rand   → angefangen, noch kein Quartett voll
 *   gestrichelt, stumm     → noch keine Karte dieser Klasse (`0/4`)
 *
 * Die vierte Behandlung — Terrakotta fuer „danach wird gefiltert" — liegt
 * weiter unten und ueberschreibt alle drei, aber nur an Rahmen und Flaeche:
 * sie beschreibt die ANSICHT, die drei hier beschreiben die SAMMLUNG.
 * ------------------------------------------------------------------------ */
.chips--gruppen .chip {
  border-color: var(--chip-offen-rand);
  background: var(--chip-offen-flaeche);
  color: var(--chip-offen-name);
}

.chips--gruppen .chip .chip__zaehler {
  color: var(--chip-offen-zahl);
}

.chips--gruppen .chip--vollstaendig {
  border-color: var(--chip-voll-rand);
  background: var(--chip-voll-flaeche);
  color: var(--chip-voll-name);
}

.chips--gruppen .chip--vollstaendig .chip__zaehler {
  color: var(--chip-voll-zahl);
}

/* Die leere Klasse steht da und ist stumm — sie ist eine Einladung, keine
   Meldung ueber Leere. Gestrichelt wie der frueher hier stehende Restchip:
   dieselbe Aussage („hier liegt noch nichts"), jetzt an der Klasse selbst,
   die sie betrifft. */
.chips--gruppen .chip--klasse-leer {
  border-style: dashed;
  border-color: var(--chip-leer-rand);
  background: transparent;
  color: var(--chip-leer-name);
}

.chips--gruppen .chip--klasse-leer .chip__zaehler {
  color: var(--chip-leer-zahl);
}

/* Die Einsatzpille „Eroberung" — auf dem Brett, im Deckbau, im Ergebnis und
   an jeder eroberten Karte. Immer derselbe Ton, immer dieselbe Form. */
.chip--eroberung {
  border-color: var(--erobert-rand);
  background: var(--erobert-flaeche);
  color: var(--erobert-text);
  font-weight: var(--gewicht-fett);
}

.chip[aria-pressed='true'] {
  border-color: var(--color-accent);
  color: var(--color-accent-300);
}

/* --------------------------------------------------------------------------
 * DER GEFILTERTE KLASSENCHIP (Artboard 19b, HANDOFF §5.5b7)
 *
 * Er steht bewusst HIER — nach `.chip--vollstaendig` und nach
 * `.chip[aria-pressed]`: er ueberschreibt beide, und zwar nur an Rahmen und
 * Flaeche. Zwei Klassen im Wahlteil halten ihn dabei auf derselben Staerke
 * wie `.chip[aria-pressed='true']`; die Reihenfolge in der Datei entscheidet,
 * und die ist damit die Aussage: „gefiltert" schlaegt „gedrueckt".
 *
 * WAS ER NICHT ANFASST, IST DIE ZAHL DARIN. Salbei sagt, dass ein Quartett
 * dieser Klasse voll ist — eine Eigenschaft der SAMMLUNG. Terrakotta sagt,
 * dass nach ihr gefiltert wird — eine Eigenschaft der ANSICHT. Beides auf
 * dieselbe Flaeche zu legen macht aus zwei Signalen eines; GAR-2 verlangt
 * genau deshalb, dass die salbeifarbene `n×`-Auskunft INNERHALB des
 * Akzentrahmens salbeifarben bleibt.
 * ------------------------------------------------------------------------ */
.chips--gruppen .chip--gefiltert {
  border-width: var(--chip-gefiltert-rand);
  border-style: solid;
  border-color: var(--color-accent);
  background: var(--chip-gefiltert-flaeche);
  color: var(--raum-text);
  font-weight: var(--gewicht-fett);
}

.chips--gruppen .chip--gefiltert .chip__zaehler {
  color: var(--chip-gefiltert-zahl);
}

/* Die salbeifarbene Auskunft bleibt salbei, auch im Akzentrahmen: sie gehoert
   der Sammlung, der Rahmen der Ansicht (§5.5b7 verlangt es ausdruecklich). */
.chips--gruppen .chip--vollstaendig.chip--gefiltert .chip__zaehler {
  color: var(--chip-voll-zahl);
}

/* Die Regel fuer `.ikone` im gefilterten vollen Chip stand hier und ist mit
   WI-0313 fort: der Haken ist fort. Das Artboard zeichnet an der vollen
   Klasse die `n×`-Pille, und die sagt dasselbe genauer. */

/* Die Zeile unter dem gefilterten Raster — sie sagt, was der Klasse zum
   naechsten Quartett fehlt (Artboard 19b). Sie steht am Ende des Bildschirms
   und nicht zwischen Chips und Raster: sie ist das Fazit, nicht die
   Ueberschrift. */
.garage__quartett {
  margin: var(--space-3) var(--space-1) 0;
}

.punkt {
  width: var(--punkt);
  height: var(--punkt);
  border-radius: var(--radius-pille);
  background: var(--r-g);
}

/* --------------------------------------------------------------------------
 * Garagenfilter — eine Zeile, die sich zur Ankreuzliste aufklappt.
 *
 * Vorher standen Marken und Stufen als Chipwolke in der Garage: auf einem
 * schmalen Handy waren das fuenf Reihen zwischen Fortschritt und Raster
 * (Staging-Rueckmeldung #8). Zugeklappt ist es jetzt eine Zeile — und seit
 * Rueckmeldung #11 steht diese Zeile nicht mehr ueber dem Raster, sondern in
 * der Kopfzeile neben der Ueberschrift.
 * ------------------------------------------------------------------------ */

.filterblock {
  position: relative;
  display: flex;
  flex: none;
  flex-direction: column;
}

.filterblock__knopf {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--btn-hoehe-ghost);
  padding: var(--space-1) var(--space-3);
  border: var(--ghost-rand);
  border-radius: var(--radius-pille);
  background: transparent;
  color: var(--ghost-text);
  font-family: var(--font-body);
  /* 13 px statt 15: die Pille steht im Entwurf in „Body small" (§12), und auf
     393 px entscheidet sie mit darueber, ob Ueberschrift, Filter und Konto in
     EINE Zeile passen. */
  font-size: var(--garage-filter-schrift);
  white-space: nowrap;
  cursor: pointer;
}

/* Ist ein Haken gesetzt, traegt die Pille die Akzentfarbe und nennt die Zahl
   (`Filter · 1`, Artboard 19). Zugeklappt und ungefiltert bleibt sie die
   ruhige Ghost-Pille aus Artboard 18. */
.filterblock__knopf[data-gefiltert='ja'] {
  border-color: var(--cs-accent-glow);
  background: var(--garage-filter-flaeche);
  color: var(--color-accent-400);
}

.filterblock__marke {
  font-weight: var(--gewicht-fett);
}

/* Was gerade angehakt ist, steht am zugeklappten Knopf — sonst waere der
   Filter unsichtbar und das Raster unerklaerlich kurz. */
.filterblock__stand {
  flex: 0 1 auto;
  margin-left: auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-klein);
}

/* DAS FILTERBLATT (Artboard 20) — ein Blatt von unten ueber die ganze
   Breite, nicht mehr ein Menue an der Pille.
   Der Entwurf zeichnet `border-radius:32px 32px 0 0` und `left/right:0`: es
   sitzt auf der unteren Kante auf, es schwebt nicht. */
.filterblatt {
  position: relative;
  border-bottom: 0;
  border-left: 0;
  border-right: 0;
  border-radius: var(--radius-karte) var(--radius-karte) 0 0;
  gap: var(--space-3);
  max-height: 80vh;
  overflow-y: auto;
}

.filterblatt__kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.filterblatt__kopf h3 {
  margin: 0;
}

/* „Alle zurücksetzen" ist im Entwurf reiner Text in der Akzentfarbe, kein
   Knopf mit Rand — es raeumt auf, es handelt nicht. */
.filterblatt__zuruecksetzen {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--color-accent-400);
  font-family: var(--font-body);
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-fett);
  cursor: pointer;
}

.filterblatt__abschnitt {
  margin: 0;
  color: var(--raum-text-etikett);
  font-family: var(--font-body);
  font-size: var(--schrift-abschnitt);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-versal);
  text-transform: uppercase;
}

.filterblatt__gruppe {
  display: flex;
  flex-direction: column;
}

/* Der Fussknopf bleibt STEHEN, auch wenn die Liste laenger ist als das Blatt.
   Mit vielen Marken rutschte er sonst unter die Falz — und die eine Aktion,
   die das Blatt wieder schliesst, waere nur nach dem Blaettern zu erreichen
   (Designspec 10.3 Punkt 1 und 2). Der Schleier darueber verhindert, dass
   die letzte Zeile hart unter ihm abgeschnitten wirkt. */
.filterblatt > .btn {
  position: sticky;
  bottom: 0;
  flex: none;
  margin-top: var(--space-1);
  box-shadow: var(--btn-glow), var(--filterblatt-fussschatten);
}

.filterliste__eintrag {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* 44 px — die Trefferflaeche des Entwurfs, und dieselbe Zahl, mit der
     Designspec 10.3 jede Zeile misst. */
  min-height: var(--filterblatt-zeile);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--raum-fliess);
  font-family: var(--font-body);
  font-size: var(--schrift-fliess);
  text-align: left;
  cursor: pointer;
}

.filterliste__text {
  flex: 1;
}

/* Die Trefferzahl rechts. Sie steht gedaempft: sie ist eine Auskunft, kein
   zweiter Wert, der mit der Beschriftung um Aufmerksamkeit ringt. */
.filterliste__zahl {
  margin-left: auto;
  color: var(--raum-text-schwach);
  font-size: var(--schrift-hinweis);
}

.filterliste__eintrag[aria-checked='true'] {
  color: var(--raum-text);
  font-weight: var(--gewicht-fett);
}

.kaestchen {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--filterblatt-kaestchen);
  height: var(--filterblatt-kaestchen);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--filterblatt-kaestchen-radius);
  background: transparent;
  color: var(--btn-text);
}

/* Angehakt ist das Kaestchen GEFUELLT, nicht nur umrandet — im Entwurf sitzt
   der Haken auf Terracotta. Ein Haken auf durchsichtigem Grund ist auf einem
   dunklen Bildschirm im Sonnenlicht kaum zu sehen. */
.filterliste__eintrag[aria-checked='true'] .kaestchen {
  border-color: var(--color-accent);
  background: var(--color-accent);
}

/* DER RUNDE KNOPF DER FUNDZEIT (Artboard 20c, HANDOFF §5.5b5).
   Er ist rund, weil genau EINER gewaehlt werden kann — die Zeitraeume liegen
   ineinander, zwei Haken haetten keine Bedeutung. Die Form ist die Regel; ein
   eckiges Kaestchen mit Einfachauswahl dahinter waere ein Versprechen, das
   die Liste nicht haelt. Gefuellt ist er ein Punkt im Ring, kein Haken:
   derselbe Unterschied noch einmal. */
.radio {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--filterblatt-kaestchen);
  height: var(--filterblatt-kaestchen);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: transparent;
}

.filterliste__eintrag[aria-checked='true'] .radio {
  border-width: var(--chip-gefiltert-rand);
  border-color: var(--color-accent);
}

.radio__punkt {
  width: var(--radio-punkt);
  height: var(--radio-punkt);
  border-radius: var(--radius-pille);
  background: var(--color-accent);
}

/* --------------------------------------------------------------------------
 * DIE BEIDEN ZUSAMMENGEKLAPPTEN ZEILEN IM FILTERBLATT (Artboard 20)
 *
 * `Marke  alle ›` und `Fundzeit  alle ›` — nebeneinander, jede eine Pille mit
 * Namen links, Stand und Winkel rechts. Sie standen bis WI-0213 als
 * ausgeklappte Ankreuzliste im Blatt; eine Liste, die mit der Sammlung
 * waechst, schiebt dort alles unter die Falz.
 * ------------------------------------------------------------------------ */
.filterblatt__paar {
  display: flex;
  gap: var(--space-3);
}

.filterzeile {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: var(--filterblatt-zeile);
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: transparent;
  color: var(--raum-fliess);
  font-family: var(--font-body);
  font-size: var(--schrift-zeile);
  text-align: left;
  cursor: pointer;
}

.filterzeile[disabled] {
  cursor: default;
  opacity: var(--stumpf-deckkraft);
}

.filterzeile__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.filterzeile__stand {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--raum-text-schwach);
}

.ikone--pfeil {
  width: var(--pfeil-glyphe);
  height: var(--pfeil-glyphe);
}

/* Der Winkel nach links in der Zurueck-Scheibe von `16r-*` (WI-0330). Er
   steht in derselben Scheibe wie das Kreuz und bekommt deshalb keine eigene
   Groesse — die kommt von `.kartenseite__schliessen > *`. */
.ikone--zurueck {
  stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
 * DIE WERTE IM FILTERBLATT (Artboards 20/20v, WI-0424)
 *
 * Fuenf Zeilen untereinander, je 48 px. Ein gesetzter Bereich faerbt die
 * Zeile wie ein gefilterter Chip und schreibt den Bereich in Akzentfarbe.
 * ------------------------------------------------------------------------ */
.filterblatt__werte {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.filterzeile--wert {
  flex: none;
  min-height: var(--btn-hoehe);
}

.filterzeile--wert[data-aktiv='ja'] {
  border-color: var(--wertebereich-saeule-an);
  background: var(--chip-gefiltert-flaeche);
  color: var(--raum-text);
  font-weight: var(--gewicht-fett);
}

.filterzeile--wert[data-aktiv='ja'] .filterzeile__stand {
  color: var(--color-accent-400);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
 * DIE BEREICHSSEITE (Artboard 20w, WI-0424)
 *
 * Zwei native Regler liegen uebereinander auf einer Bahn. Die Regler selbst
 * sind durchsichtig und lassen Klicks durch; nur ihre Griffe fangen den
 * Finger. So bleiben Tastatur und Bildschirmleser beim Browser.
 * ------------------------------------------------------------------------ */
.wertebereich__kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.wertebereich__zurueck {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--filterblatt-zeile);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--raum-fliess);
  font-family: var(--font-body);
  font-size: var(--schrift-zeile);
  font-weight: var(--gewicht-fett);
  cursor: pointer;
}

.wertebereich__zurueck .ikone {
  width: var(--pfeil-glyphe);
  height: var(--pfeil-glyphe);
}

.wertebereich__aktionen {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.wertebereich__alle,
.wertebereich__fertig {
  min-height: var(--filterblatt-zeile);
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  font-weight: var(--gewicht-fett);
  cursor: pointer;
}

.wertebereich__alle {
  color: var(--raum-text-schwach);
  font-size: var(--schrift-hinweis);
}

.wertebereich__fertig {
  color: var(--color-accent-400);
  font-size: var(--schrift-zeile);
}

.wertebereich__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h3);
}

.wertebereich__satz {
  margin: 0;
}

.wertebereich__saeulen {
  display: flex;
  align-items: flex-end;
  gap: var(--space-1);
  height: var(--wertebereich-saeulen);
  padding: 0 calc(var(--wertebereich-griff) / 2);
}

.wertebereich__saeule {
  flex: 1;
  border-radius: var(--wertebereich-saeule-radius);
  background: var(--wertebereich-saeule-aus);
}

.wertebereich__saeule[data-im-bereich='ja'] {
  background: var(--wertebereich-saeule-an);
}

.wertebereich__schiene {
  position: relative;
  height: var(--wertebereich-schiene);
}

.wertebereich__bahn {
  position: absolute;
  top: 50%;
  left: calc(var(--wertebereich-griff) / 2);
  right: calc(var(--wertebereich-griff) / 2);
  height: var(--wertebereich-spur);
  margin-top: calc(var(--wertebereich-spur) / -2);
  border-radius: var(--radius-pille);
  background: var(--wertebereich-saeule-aus);
}

.wertebereich__fuellung {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: var(--radius-pille);
  background: var(--color-accent);
}

.wertebereich__regler {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  background: transparent;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.wertebereich__regler::-webkit-slider-runnable-track {
  background: transparent;
}

.wertebereich__regler::-moz-range-track {
  background: transparent;
}

.wertebereich__regler::-webkit-slider-thumb {
  width: var(--wertebereich-griff);
  height: var(--wertebereich-griff);
  border: var(--wertebereich-griff-rand);
  border-radius: var(--radius-pille);
  background: var(--color-accent);
  box-shadow: var(--wertebereich-griff-schatten);
  pointer-events: auto;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.wertebereich__regler::-moz-range-thumb {
  box-sizing: border-box;
  width: var(--wertebereich-griff);
  height: var(--wertebereich-griff);
  border: var(--wertebereich-griff-rand);
  border-radius: var(--radius-pille);
  background: var(--color-accent);
  box-shadow: var(--wertebereich-griff-schatten);
  pointer-events: auto;
  cursor: pointer;
}

.wertebereich__regler:focus-visible::-webkit-slider-thumb {
  outline: var(--chip-gefiltert-rand) solid var(--color-accent-400);
}

.wertebereich__grenzen {
  display: flex;
  justify-content: space-between;
  padding: 0 calc(var(--wertebereich-griff) / 2);
  font-variant-numeric: tabular-nums;
}

.wertebereich__felder {
  display: flex;
  gap: var(--space-2);
}

.wertebereich__feld {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-2) var(--space-4);
  border: var(--karte-rand) solid var(--wertebereich-saeule-aus);
  border-radius: var(--wertebereich-feld-radius);
  background: var(--wertebereich-feld-flaeche);
}

.wertebereich__feldname {
  color: var(--raum-text-schwach);
  font-size: var(--schrift-abschnitt);
}

.wertebereich__feldwert {
  font-size: var(--wertebereich-feldwert);
  font-weight: var(--gewicht-fett);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
 * DIE BEIDEN WAHLBILDSCHIRME (Artboards 20b und 20c)
 *
 * DIE SCHRUMPFREGEL, AUF JEDER EBENE (HANDOFF §5.5b4/§8.1): eine Spalte mit
 * fester Hoehe braucht GENAU EIN Kind mit `flex: 1`, `min-height: 0` UND
 * `overflow-y: auto`. Zwei von drei scheitern lautlos.
 *
 * Auf 20b gibt es davon ZWEI Ebenen, und genau daran ist es schon einmal
 * gescheitert: `.wahlspalten` ist der Bereich neben der A–Z-Schiene,
 * `.wahlspalte__liste` die Liste darin. Der Bereich allein reicht nicht — die
 * Liste darin hatte `flex: 1` mit dem voreingestellten `min-height: auto` und
 * kein `overflow`, konnte also weder schrumpfen noch rollen: die Marken ab
 * `Volvo` liefen auf 952 px in einem 793-px-Rahmen und waren unerreichbar,
 * und die Schiene daneben zeigte ins Leere. Das scrollende Kind ist das
 * INNERSTE, das den unbegrenzten Inhalt haelt.
 * ------------------------------------------------------------------------ */
.wahlseite {
  flex: 1;
  min-height: 0;
  gap: var(--space-2);
}

.wahlseite__kopf {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.wahlseite__kopf h2 {
  margin: 0;
  font-size: var(--wahlseite-titel);
}

.wahlseite__fertig {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--color-accent-300);
  font-family: var(--font-body);
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-kraeftig);
  cursor: pointer;
}

.wahlseite__unterzeile {
  flex: none;
  margin: 0;
  color: var(--raum-text-schwach);
  font-size: var(--schrift-klein);
}

.wahlsuche {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--filterblatt-zeile);
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
}

.wahlsuche input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--schrift-zeile);
}

.wahlsuche input::placeholder {
  color: var(--raum-text-schwach);
}

.wahlsuche .ikone--lupe {
  flex: none;
  width: var(--lupe-glyphe);
  height: var(--lupe-glyphe);
  color: var(--raum-text-schwach);
}

/* Ebene 1: der Bereich neben der Schiene. */
.wahlspalten {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: var(--space-2);
  overflow: hidden;
}

/* Ebene 2 — und auf 20c die einzige: die Liste selbst. ALLE DREI, sonst
   scheitert sie lautlos. */
.wahlspalte__liste {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

/* Jede Zeile behaelt ihre Hoehe, auch wenn die Liste laenger ist als ihr
   Fenster — sonst quetscht der Flexbaum die 44-px-Trefferflaeche zusammen,
   die Designspec 10.3 fuer JEDE Zeile verlangt. */
.wahlspalte__liste > * {
  flex: none;
}

.wahlspalte__strich {
  height: var(--haarlinie);
  margin-top: var(--space-2);
  background: var(--cs-line-2);
}

/* Die Buchstabenueberschrift ueber jeder Gruppe (Artboard 20b): einbreite
   Schrift, damit A, I und W gleich viel Platz nehmen und die Reihe der
   Ueberschriften eine Spalte bildet. */
.wahlspalte__buchstabe {
  margin: 0;
  padding: var(--space-3) 0 var(--space-1);
  color: var(--raum-text-schwach);
  font-family: var(--font-einbreit);
  font-size: var(--schrift-abschnitt);
  font-weight: var(--gewicht-kraeftig);
  letter-spacing: var(--laufweite-buchstabe);
}

.wahlspalte__fuss {
  padding-top: var(--space-4);
}

/* DIE A–Z-SCHIENE (Artboard 20b). Sie traegt IMMER alle 26 Buchstaben — eine
   Schiene, die ihre Laenge aendert, ist keine. Vorhandene sind hell und
   tippbar, fehlende stumpf und stumm. */
.wahlschiene {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: var(--schiene-breite);
  padding-top: var(--space-1);
}

.wahlschiene__glyphe {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--raum-text-schwach);
  font-family: var(--font-einbreit);
  font-size: var(--schiene-schrift);
  font-weight: var(--gewicht-kraeftig);
  line-height: var(--schiene-zeile);
  cursor: pointer;
}

.wahlschiene__glyphe[data-vorhanden='nein'] {
  color: var(--schiene-stumm);
  cursor: default;
}

.raster {
  display: grid;
  grid-template-columns: repeat(var(--kachel-spalten), 1fr);
  gap: var(--raster-luecke);
}

/* WI-0328: die Hoehe ist ein MASS und keine Folge des Namens — siehe
   --kachel-hoehe im Token-Block. Bei langem wie bei kurzem Modellnamen stehen
   damit alle Kacheln einer Reihe gleich hoch, und `overflow: hidden` (schon
   vorher da, fuer die Rundung) ist die zweite Haelfte der Zusage: was nicht
   hineinpasst, waechst nicht nach unten heraus. */
.kachel {
  position: relative;
  height: var(--kachel-hoehe);
  border-radius: var(--kachel-radius);
  border: 0;
  padding: 0;
  overflow: hidden;
  background: var(--kachel-flaeche);
  color: var(--raum-text);
  font-family: var(--font-body);
  text-align: center;
  cursor: pointer;
}

.kachel__streifen {
  /* Ein <span> ist von Haus aus inline: ohne diese Zeile bleibt die Hoehe
     wirkungslos und der Streifen ist auch mit gueltiger Farbe nicht zu sehen
     (WI-0048, am Referenzbild gemessen). Derselbe Grund wie beim Wertbalken. */
  display: block;
  height: var(--kachel-streifen);
  background: var(--balken-fuellung);
}

.kachel__foto {
  height: var(--kachel-foto);
  background: var(--foto-flaeche);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/*
 * Die Miniatur der eigenen Aufnahme (WI-0030): formatfuellend zugeschnitten.
 * `cover` schneidet ab, `fill` wuerde das Auto in die Breite ziehen — dieselbe
 * Regel wie auf der Fotoflaeche der Karte.
 */
/*
 * DIE LAGE DES AUSSCHNITTS (WI-0127). `object-position` steht hier bewusst mit
 * `50% 50%` — dem Vorgabewert — und wird vom Renderer ueberschrieben, sobald
 * das Foto seine Fahrzeugmitte mitbringt (public/js/card.js
 * `fuelleFotoflaeche`, abgeleitet in `filterchain.objektPosition` aus
 * `FOTOBAENDER`). Ohne gespeicherte Mitte — jedes Foto von vor WI-0127 —
 * bleibt es bei diesem Wert. Wer hier einen anderen setzt, verschiebt jedes
 * Bestandsfoto.
 */
.kachel__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Die Beschriftung der Kachel: Modellname, darunter der Generationscode
   (HANDOFF §5.3). Linksbuendig wie im Entwurf — zentriert stand der Name
   ueber einer Silhouette, die selbst nicht zentriert ist. */
.kachel__text {
  display: block;
  /* Zwei Zeilen, immer — auch auf einer Karte ohne verlaessliche Generation,
     die die zweite Zeile gar nicht baut (WI-0117). Ohne dieses Mass waere
     eine solche Kachel um eine Zeilenhoehe niedriger als ihre Nachbarin
     (WI-0328). */
  height: var(--kachel-beschriftung);
  padding: var(--kachel-polster);
  text-align: left;
}

/* EINE ZEILE MIT AUSLASSUNG — FUER BEIDE ZEILEN (WI-0328).
 *
 * Das Brett zeichnet `Audi A3` ueber `8V`: Modellname oben, kurzes Kuerzel
 * darunter, je einzeilig. Umbrechen durften beide, und genau daran hing die
 * wandernde Kachelhoehe. Abgeschnitten wird mit `…` und nicht hart: eine
 * Auslassung sagt, dass da mehr steht; ein glatter Schnitt sieht aus wie ein
 * falscher Name. Der vollstaendige Name bleibt im Knopf und wird vorgelesen.
 *
 * Dass ein Generationscode ueberhaupt zu lang werden kann, ist ein Befund am
 * KATALOG und nicht an der Kachel — hier wird er nur nicht mehr zur Hoehe. */
.kachel__name,
.kachel__generation {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kachel__name {
  font-size: var(--kachel-name);
  line-height: var(--zeilenhoehe-heading);
}

.kachel__generation {
  font-size: var(--kachel-generation);
  line-height: var(--zeilenhoehe-heading);
  color: var(--raum-text-schwach);
}

.kachel__neu,
.kachel__erobert {
  position: absolute;
  /* Der Entwurf setzt die Ecken-Chips auf `top: 14px` — also UNTER den
     9-px-Streifen, nicht auf ihn. Sonst verdeckt das Abzeichen genau die
     Farbe, die es begleiten soll. */
  top: calc(var(--kachel-streifen) + var(--space-1));
  right: var(--space-1);
  border-radius: var(--radius-pille);
  font-size: var(--kachel-abzeichen);
  font-weight: var(--gewicht-fett);
  padding: 0 var(--space-1);
}

.kachel__neu {
  background: var(--color-accent);
  color: var(--btn-text);
}

/* „EROBERT" in derselben Violettmarke wie die Einsatzpille und das Abzeichen
   der Detailansicht — eine eroberte Karte sieht ueberall gleich aus. */
.kachel__erobert {
  background: var(--erobert-marke);
  color: var(--erobert-marke-text);
}

/* Sind beide da — frisch erobert —, rueckt „NEU" unter „EROBERT", statt es
   zu ueberdecken. */
.kachel__erobert ~ .kachel__neu {
  top: calc(var(--kachel-streifen) + var(--space-1) + var(--kachel-abzeichen) + var(--space-3));
}

/* WI-0222 — DIE MARKIERUNG FUER EINE NOCH NICHT GESEHENE REAKTION.
   VORLAEUFIG: der Entwurf zeichnet an der Garagenkachel KEINE Markierung fuer
   Reaktionen (HANDOFF §5.5b, §17 kennen nur Streifen, EROBERT und NEU). Gebaut
   ist deshalb das, was der Entwurf an anderer Stelle fuer dieselbe Aussage
   hergibt — die Zaehlerpille aus §4.3, Zeichen fuer Zeichen: 20px hoch,
   Pillenradius, 11.5px/800, Auskunftsgruen auf dem Raumgrund. Kommt dafuer
   eine Vorlage, ersetzt sie diese Regel; erfunden wird hier nichts, was der
   Entwurf anders zeichnet.
   SIE SITZT LINKS, weil rechts schon EROBERT und NEU stehen — eine eroberte
   Karte mit einer frischen Reaktion haette sonst drei Abzeichen in einer Ecke.
   TERRACOTTA BLEIBT AKTIONSFARBE: dies ist eine Auskunft, kein Knopf, und es
   traegt deshalb denselben Auskunftston wie der Zaehler am Reiter. Eine
   Seltenheitsfarbe kommt hier nicht vor; die traegt der Streifen daneben. */
.kachel__reaktion {
  position: absolute;
  top: calc(var(--kachel-streifen) + var(--space-1));
  left: var(--space-1);
  min-width: var(--zaehler-seite);
  height: var(--zaehler-seite);
  padding: 0 var(--zaehler-polster);
  border-radius: var(--radius-pille);
  background: var(--zaehler-flaeche);
  color: var(--zaehler-text);
  font-size: var(--zaehler-schrift);
  font-weight: var(--gewicht-fett);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.skelett {
  border-radius: var(--kachel-radius);
  background: var(--skelett-flaeche);
  height: var(--start-kreis);
}

.leerzustand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  text-align: center;
  padding: var(--space-6) 0;
}

/* ARTBOARD 21 — DIE LEERE GARAGE.
   Sie nimmt die Hoehe, die da ist, statt oben zu kleben: der Entwurf setzt
   den Block mittig in 520 px und den Knopf an den unteren Rand. Das ist
   Designspec 10.3 Punkt 1 und Punkt 3 in einem Bild — die Hauptaktion im
   unteren Drittel, kein Loch darunter. */
.leerzustand--garage {
  flex: 1;
  justify-content: center;
  gap: var(--space-3);
  /* Seitlich nur ein Haar: der Entwurf setzt den Knopf auf `left/right: 26`,
     die Buehne haelt schon 22 — zusammen sind es die 26 des Artboards. Der
     Text darunter ist enger, aber ueber seine eigene Breite, nicht ueber das
     Polster (sonst rueckte der Knopf mit). */
  padding: var(--space-4) var(--space-1) 0;
}

.leerzustand--garage .fliess {
  max-width: var(--leer-textbreite);
  color: var(--raum-text-gedaempft);
}

/* Der gestrichelte Rahmen mit der grauen Silhouette darin. Er ist KEINE
   Fehlerflaeche: nichts daran ist rot, nichts ruft. Er zeigt, wo die erste
   Karte liegen wird. */
.leerzustand__rahmen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--leer-rahmen-b);
  height: var(--leer-rahmen-h);
  margin-bottom: var(--space-3);
  border: var(--karte-rand) dashed var(--feld-rand);
  border-radius: var(--radius-lg);
}

/* Die Silhouette darin bleibt grau — der Rahmen erbt keine Seltenheitsfarbe,
   weil es hier noch keine Karte und damit keine Stufe gibt. */
.leerzustand__rahmen .silhouette {
  width: var(--leer-silhouette-b);
  height: auto;
  stroke: var(--raum-text-schwach);
  fill: none;
  opacity: var(--leer-silhouette-deckkraft);
}

.leerzustand__einladung {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h3);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Der Knopf steht unten, nicht direkt unter dem Text (§10.3 Punkt 1). */
.leerzustand--garage .btn {
  margin-top: auto;
}

/* Der Leerzustand als GESTRICHELTER Kasten (Artboard 21 und 23): eine
   Einladung mit einem Rahmen darum, kein Loch in der Seite. Er ist
   linksbuendig — zwei Zeilen Fliesstext liest man nicht zentriert. */
.leerzustand--gestrichelt {
  align-items: stretch;
  text-align: left;
  padding: var(--space-4);
  border: var(--karte-rand) dashed var(--feld-rand);
  border-radius: var(--radius-karte);
  gap: var(--space-1);
}

.leerzustand__titel {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

/* --------------------------------------------------------------------------
 * Die Sammlung eines Freundes (Artboard 40)
 *
 * Dasselbe Raster wie die Garage, ein anderer Kopf: Zeichen, Name im Genitiv,
 * darunter Karten- und Modellzahl, rechts der Rueckweg. Kein
 * Fortschrittsbalken und keine Gruppenreihe — das sind eigene Sammelziele und
 * gehoeren nicht in die Sammlung eines anderen.
 * ------------------------------------------------------------------------ */

.freund-sammlung__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.freund-sammlung__namen {
  flex: 1;
  min-width: 0;
}

.freund-sammlung__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h3);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.freund-sammlung__zeile {
  margin: 0;
  font-size: var(--garage-meta);
}

/* Die Scheibe des Freundes in der Groesse des Entwurfs (44 px) — groesser als
   in einer Liste, weil sie hier die Ueberschrift traegt. Seit WI-0171 ist es
   die Avatarscheibe aus §4.5b, die diese Groesse als eigene Stufe fuehrt. */
.freund-sammlung__kopf .avatar {
  width: var(--freund-zeichen);
  height: var(--freund-zeichen);
}

.freund-sammlung__zurueck {
  flex: none;
}

/* Der Bildschirm nimmt die Hoehe, die da ist (Designspec 10.3 Punkt 3): das
   Blatt „Sag was Nettes" sitzt auf der unteren Kante auf, wie der Entwurf es
   zeichnet, statt direkt unter der letzten Kachelreihe zu haengen und
   darunter eine halbe Seite frei zu lassen. */
.freund-sammlung {
  flex: 1;
  min-height: 0;
}

/* Artboard 40 (WI-0424): die Gruppenwahl ueber dem Raster. Die Pille ist
   dieselbe wie im Deckbau (`btn btn--fuellen`), die Liste dieselbe
   `.gruppenliste`; neu ist nur, dass beide links ueber dem Raster stehen. */
.freund-sammlung__filter {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.freund-sammlung__gruppenliste {
  align-self: stretch;
  /* Im stehenden Band darf die offene Liste das Raster nicht ganz verdecken. */
  max-height: 50vh;
  overflow-y: auto;
}

.freund-sammlung .reaktionen {
  margin: auto calc(var(--space-4) * -1) calc(var(--space-4) * -1);
  border-bottom: 0;
  border-left: 0;
  border-right: 0;
  border-radius: var(--radius-karte) var(--radius-karte) 0 0;
}

.fehlerbox {
  border: var(--karte-rand) solid var(--warn-flaeche);
  border-radius: var(--radius-md);
  background: var(--warn-flaeche);
  color: var(--raum-text);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
}

/* --------------------------------------------------------------------------
 * Konto, Sitzung und Wiederherstellungscode (Spec 4.1)
 *
 * Der Code wird von Hand abgeschrieben. Deshalb steht er gross, in gleich
 * breiten Ziffern und mit weiter Laufweite: die Gruppen sollen sich einzeln
 * lesen lassen, ohne dass jemand Zeichen zusammenzieht.
 * ------------------------------------------------------------------------ */

.code {
  display: block;
  font-family: var(--font-heading);
  font-variant-numeric: tabular-nums;
  font-size: var(--schrift-h3);
  font-weight: 700;
  letter-spacing: var(--laufweite-versal);
  color: var(--raum-text);
  background: var(--feld-flaeche);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  width: 100%;
  overflow-wrap: anywhere;
  user-select: all;
}

/* --------------------------------------------------------------------------
 * Der Kontobereich — Artboards 43, 44 und 45 (WI-0099, Produktspec 4.1b)
 *
 * Die Anordnung IST die Aussage: der Gerätewechsel steht oben in „Dein
 * Zugang", die beiden Wege hinaus stehen unten, durch eine Haarlinie
 * abgesetzt, und der zerstoerendste von beiden ist der leiseste. Wer die
 * Reihenfolge aendert, aendert die Regel — nicht nur das Aussehen.
 * ------------------------------------------------------------------------ */

/* DER FUSSFREIRAUM IST HIER NICHT DER ALLGEMEINE. `--buehne-unten` haelt 90 px
   fuer die schwebende Leiste frei (Designspec Kap. 9) — und HANDOFF §4.3
   zeichnet die Leiste auf KEINEM Kontobildschirm. Neunzig leere Pixel unter
   „Fertig" waeren genau der Leerraum, den Kap. 10.3 Punkt 3 verbietet. */
.app__buehne[data-bildschirm='konto'],
.app__buehne[data-bildschirm='konto_sprache'],
.app__buehne[data-bildschirm='geraetewechsel'] {
  padding-bottom: var(--space-6);
}

.kontoseite {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
}

.konto {
  flex: 1;
  gap: var(--space-4);
}

.konto__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Das Zeichen des Spielers, wie die Kontoscheibe der Garage-Kopfzeile — nur
   groesser, weil es hier der Kopf des Bildschirms ist und kein Knopf. */
.konto__zeichen {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--konto-zeichen);
  height: var(--konto-zeichen);
  border: var(--karte-rand) solid var(--cs-accent-glow);
  border-radius: var(--radius-pille);
  background: var(--cs-accent-tint);
  color: var(--konto-zeichen-glyphe);
  font-family: var(--font-heading);
  font-size: var(--schrift-h4);
  font-weight: var(--gewicht-heading);
  line-height: 1;
}

.konto__kopftext {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.konto__name {
  margin: 0;
  overflow-wrap: anywhere;
}

.konto__stand {
  margin: 0;
}

.konto__gruppe {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.konto__zeilen {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* EINE ZEILE IST EIN KNOPF, nicht eine Zeile mit einem Knopf darin: die volle
   Flaeche ist 56 px hoch und mit einem Daumen zu treffen (Designspec Kap.
   10.3 Punkt 1). */
.konto__zeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--konto-zeile);
  padding: var(--space-2) var(--space-4);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--raum-text);
  /* Ein `button` erbt die Schrift NICHT von selbst — ohne diese Zeile stuende
     die Zeile in Arial, und der Merkmalsvergleich meldet genau das. */
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
}

/* Die eine Zeile, die der Entwurf hervorhebt: der Gerätewechsel. Er ist der
   Weg, den die Leute wirklich wollen — deshalb traegt er als einziger eine
   Flaeche (Artboard 43). */
.konto__zeile--betont {
  background: var(--feld-flaeche);
  border-color: var(--feld-rand);
}

/* HIER STANDEN `.konto__zeile--wert`, `.konto__zeile-wert` und
   `.konto__daten` — das Aussehen der beiden Auskunftszeilen „Spitzname" und
   „Farbe" (WI-0022). ENTFERNT MIT WI-0331 (Befund 43-5): das Brett zeichnet
   die Zeilen nicht, das Bauteil dazu ist fort, und eine Regel ohne Bauteil
   ist der naechste `.ikone--geraet`-Fall (siehe oben). `--konto-wert-zeile`
   ist mit ihnen gegangen.

   EINE ZEILE, DIE EINEN STAND SAGT UND KEINEN WEG OEFFNET (WI-0331,
   Befund 43-4, Artboard 43, „Fotos für die Erkennung freigeben"). Sie sieht
   aus wie eine Kontozeile und ist keine: kein Zeiger, kein Griff. Der Rand
   kommt aus `.konto__zeile`, hier steht nur, was anders ist. */
.konto__zeile--auskunft {
  cursor: default;
}

/* Haken und Wort rechts, wie das Brett sie setzt: gruen, in der kleinen
   Schrift der Zeile, und der Haken in der Groesse des Zeilenzeichens. */
.konto__freigabe {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
}

.konto__freigabe-wort {
  color: var(--gruen-text);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-kraeftig);
}

.ikone--freigabe {
  flex: none;
  width: var(--konto-haken);
  height: var(--konto-haken);
  color: var(--gruen-icon);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.konto__zeile-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.konto__zeile-titel {
  font-size: var(--schrift-zeile);
  font-weight: var(--gewicht-kraeftig);
  line-height: var(--zeilenhoehe-fliess);
}

.konto__zeile-unter {
  font-size: var(--schrift-klein);
  color: var(--raum-text-schwach);
  line-height: var(--zeilenhoehe-fliess);
}

/* Das Wort vor dem Winkel (WI-0287, Artboard 43: `Ändern`). Terracotta, weil
   es die AKTION der Zeile benennt — der Titel dieser Zeile ist die Adresse
   selbst und sagt von sich aus nicht, was ein Tipp bewirkt. Es ist der
   gezeichnete Ton (`--color-accent-300`) und bleibt damit Aktionsfarbe. */
.konto__zeile-marke {
  flex: none;
  color: var(--color-accent-300);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-kraeftig);
}

.konto__winkel {
  flex: none;
  color: var(--raum-text-schwach);
  font-size: var(--schrift-fliess);
}

/* DER WERT DER SPRACHZEILE (WI-0357, Artboard 43). Er steht vor dem Winkel
   wie `Ändern` in der Adresszeile, ist aber KEINE Aktion, sondern ein Stand —
   deshalb nicht Terracotta, sondern der gedaempfte Ton des Bretts. */
.konto__zeile[data-konto-sprache] .konto__zeile-marke {
  color: var(--raum-text-gedaempft);
}

/* DER STAND IN DER ZEILE „Scans" (WI-0426, Artboard 43) — wie die
   Sprachzeile ein Stand und keine Aktion. */
.konto__zeile[data-konto-scans] .konto__zeile-marke {
  color: var(--raum-text-gedaempft);
  font-variant-numeric: tabular-nums;
}

/* --- 43s / 43t: die Kontoseite Scans (WI-0426) --- */
.konto-scans__titel {
  margin: 0 0 var(--konto-scans-titel-unten);
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--konto-scans-titel);
  line-height: var(--zeilenhoehe-heading);
  letter-spacing: var(--laufweite-heading);
  color: var(--cs-text);
}

.konto-scans__stand {
  display: flex;
  align-items: baseline;
  gap: var(--konto-scans-fuge);
  margin-bottom: var(--konto-scans-kasten-unten);
  padding: var(--konto-scans-kasten-polster);
  border-radius: var(--radius-lg);
  background: var(--konto-scans-kasten-flaeche);
  border: var(--konto-scans-strich) solid var(--konto-scans-kasten-rand);
}

.konto-scans__zahl {
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--konto-scans-zahl);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--cs-text);
}

.konto-scans__platzhalter {
  display: inline-block;
  width: var(--konto-scans-zahl);
  height: var(--zaehler-hoehe-quer);
  border-radius: var(--radius-pille);
  background: var(--zaehler-platzhalter);
}

.konto-scans__wort {
  font-size: var(--konto-scans-wort);
  font-weight: 700;
  color: var(--text-hell);
}

.konto-scans__regel {
  margin: 0 0 var(--konto-scans-regel-unten);
  font-size: var(--konto-scans-regel);
  line-height: var(--konto-scans-regel-zeile);
  color: var(--cs-text-2);
}

.konto-scans__abschnitt {
  margin: 0 0 var(--konto-scans-abschnitt-unten);
  font-size: var(--schrift-abschnitt);
  font-weight: 800;
  letter-spacing: var(--konto-scans-abschnitt-laufweite);
  text-transform: uppercase;
  color: var(--cs-label);
}

.konto-scans__anderswo {
  padding: var(--konto-scans-anderswo-polster);
  border-radius: var(--konto-scans-anderswo-rundung);
  border: var(--konto-scans-strich) dashed var(--cs-line-3);
}

.konto-scans__anderswo p {
  margin: 0;
  font-size: var(--schrift-zeile);
  line-height: var(--konto-scans-regel-zeile);
  color: var(--cs-text-2);
}

/* --- 43s: der Kasten „Scan-Paket" in der App (WI-0427) --- */
.konto-scans__paket {
  padding: var(--konto-scans-anderswo-polster);
  border-radius: var(--konto-scans-anderswo-rundung);
  background: var(--konto-scans-paket-flaeche);
  border: var(--karte-rand) solid var(--cs-line-2);
}

.konto-scans__paket-titel {
  margin: 0 0 var(--konto-scans-paket-fuge);
  font-size: var(--konto-scans-paket-titel);
  font-weight: 700;
  color: var(--cs-text);
}

.konto-scans__paket-text {
  margin: 0 0 var(--konto-scans-paket-vor-knopf);
  font-size: var(--konto-scans-paket-text);
  line-height: var(--konto-scans-paket-zeile);
  color: var(--cs-text-dim);
}

/* --- 50–50g: das Kaufblatt (WI-0427) ---
   In der gemeinsamen Blattlage; das Brett setzt die Karte 20 px vom Rand und
   26 px ueber den unteren Rand, ueber die gedimmte Tab-Leiste. */
.kaufblatt {
  margin: 0 var(--kaufblatt-rand-aussen) var(--kaufblatt-unten);
  padding: var(--kaufblatt-polster);
  border-radius: var(--kaufblatt-rundung);
  gap: var(--kaufblatt-fuge);
  position: relative;
}

.kaufblatt__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--kaufblatt-titel);
  line-height: var(--zeilenhoehe-heading);
  color: var(--cs-text);
}

.kaufblatt__text {
  margin: 0;
  font-size: var(--kaufblatt-text);
  line-height: var(--kaufblatt-zeile);
  color: var(--cs-text-2);
}

.kaufblatt__fakten {
  display: flex;
  flex-direction: column;
  gap: var(--kaufblatt-fakt-fuge);
  margin: 0;
  padding: 0;
  list-style: none;
}

.kaufblatt__fakt {
  display: flex;
  align-items: center;
  gap: var(--kaufblatt-fakt-fuge);
  font-size: var(--schrift-zeile);
  font-weight: 700;
  color: var(--text-hell);
}

.ikone--kaufblatt-haken {
  flex: none;
  width: var(--kaufblatt-haken);
  height: var(--kaufblatt-haken);
  color: var(--cs-good);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* WI-0437 — Fussnote unter dem Kaufknopf; gleiche Tokens wie .konto-scans__regel. */
.kaufblatt__echtes-geld {
  margin: 0;
  font-size: var(--konto-scans-regel);
  line-height: var(--konto-scans-regel-zeile);
  color: var(--cs-text-2);
  text-align: center;
}

.kaufblatt__knoepfe {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* WI-0439 — zwei Pakete gleichrangig nebeneinander: gleiche Breite, gleiches Gewicht. */
.kaufblatt__pakete {
  display: flex;
  gap: var(--space-2);
}

.kaufblatt__pakete > .btn {
  flex: 1 1 0;
  min-width: 0;
}

.kaufblatt__paket {
  flex-direction: column;
  gap: var(--space-1);
}

.kaufblatt__paket-scans,
.kaufblatt__paket-preis {
  display: block;
}

/* 50h/50a — der beschaeftigte Kaufknopf: blasse Akzentflaeche, Kreisel. */
.kaufblatt__laeuft {
  background: var(--kaufblatt-laeuft-flaeche);
  box-shadow: none;
  cursor: progress;
}

/* 50e und 50g — ein Satz in einem Kasten statt einer Meldung daneben. */
.kaufblatt__fehler,
.kaufblatt__aus {
  margin: 0;
  padding: var(--kaufblatt-kasten-polster);
  border-radius: var(--kaufblatt-kasten-rundung);
  font-size: var(--kaufblatt-kasten-schrift);
  font-weight: 700;
  line-height: var(--kaufblatt-zeile);
}

.kaufblatt__fehler {
  background: var(--kaufblatt-fehler-flaeche);
  border: var(--karte-rand) solid var(--kaufblatt-fehler-rand);
  color: var(--cs-warn);
}

.kaufblatt__aus {
  background: var(--kaufblatt-aus-flaeche);
  border: var(--karte-rand) solid var(--kaufblatt-aus-rand);
  color: var(--text-hell);
}

/* 50b/50c/50d — der Kreis oben. */
.kaufblatt__zeichen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--kaufblatt-zeichen);
  height: var(--kaufblatt-zeichen);
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid transparent;
}

.kaufblatt__zeichen .ikone {
  width: var(--kaufblatt-zeichen-ikone);
  height: var(--kaufblatt-zeichen-ikone);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.kaufblatt__zeichen--gut {
  background: var(--kaufblatt-gut-flaeche);
  border-color: var(--kaufblatt-gut-rand);
  color: var(--cs-good);
}

.kaufblatt__zeichen--akzent {
  background: var(--kaufblatt-akzent-flaeche);
  border-color: var(--kaufblatt-akzent-rand);
  color: var(--color-accent);
}

.kaufblatt__zeichen--ruhig {
  background: var(--kaufblatt-ruhig-flaeche);
  border-color: var(--kaufblatt-ruhig-rand);
  color: var(--cs-text-3);
}

.kaufblatt--50c {
  align-items: center;
  text-align: center;
}

.kaufblatt__plus {
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--kaufblatt-plus);
  line-height: 1;
  color: var(--cs-text);
}

/* 07ld — quer liegt das Blatt in der Mitte (HANDOFF: „centred sheet"). */
.app__buehne[data-ausrichtung='quer'] .blattlage[data-kaufblatt] {
  justify-content: center;
  align-items: center;
}

.app__buehne[data-ausrichtung='quer'] .kaufblatt {
  width: var(--kaufblatt-quer-breite);
  max-width: calc(100% - var(--kaufblatt-rand-aussen) * 2);
  margin: 0;
}

/* --- 43h: die Sprachwahl (WI-0357, HANDOFF §28, P-3) ---
   Zurueck, Titel, Einleitung, drei Wahlzeilen, Fusszeile. Die Zeilen sind
   Knoepfe mit `role="radio"`; die gewaehlte ist in der Akzentfarbe getoent,
   und das sagt `aria-checked`, nicht eine zweite Klasse. */
.sprachwahl {
  gap: var(--space-2);
}

.sprachwahl__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

.sprachwahl__text {
  margin: 0 0 var(--space-4);
  color: var(--raum-fliess);
}

.sprachwahl__liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.sprachwahl__zeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--sprachwahl-zeile);
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--raum-text);
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
}

.sprachwahl__zeile[aria-checked='true'] {
  border-color: var(--cs-accent-glow);
  background: var(--cs-accent-tint);
}

.sprachwahl__zeile .radio {
  border-width: var(--chip-gefiltert-rand);
  border-color: var(--raum-text-schwach);
}

.sprachwahl__zeile[aria-checked='true'] .radio {
  border-color: var(--color-accent);
}

.sprachwahl__zeile .radio__punkt {
  width: var(--sprachwahl-punkt);
  height: var(--sprachwahl-punkt);
}

.sprachwahl__zeile-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}

.sprachwahl__name {
  font-size: var(--schrift-fliess);
  font-weight: var(--gewicht-kraeftig);
}

.sprachwahl__unter {
  color: var(--raum-text-schwach);
  font-size: var(--schrift-klein);
}

.sprachwahl__fuss {
  margin: var(--space-4) 0 0;
  color: var(--raum-text-schwach);
  font-size: var(--schrift-klein);
  line-height: var(--zeilenhoehe-fliess);
}

/* --- 43b, 43c: die Anmeldeadresse wechseln (WI-0287) ---

   Das Geruest ist das von `00b` (siehe `.postfach`): der Inhalt waechst von
   oben, der Aktionsblock haengt am Fuss (`.anmeldefuss`). Hier stehen nur die
   zwei Stuecke, die es dort nicht gibt. */
.kontoemail {
  flex: 1;
  gap: var(--space-3);
}

.kontoemail__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h2);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-heading);
}

/* Die geltende Adresse unter „Jetzt". Dieselbe Pille wie ein Feld, aber KEIN
   Feld: hier ist nichts zu tippen, und ein Feld, das nichts annimmt, ist eine
   Falle. Der Entwurf zeichnet sie eine Spur leiser als das Eingabefeld
   darunter — das sagt die gedaempfte Schriftfarbe. `anywhere` statt
   Abschneiden: eine halbe Mailadresse ist an dieser Stelle schlimmer als eine
   zweite Zeile. */
.kontoemail__jetzt {
  display: flex;
  align-items: center;
  min-height: var(--btn-hoehe);
  margin: 0;
  padding: 0 var(--space-4);
  border: var(--karte-rand) solid var(--feld-rand);
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
  color: var(--raum-text-gedaempft);
  font-size: var(--btn-schrift);
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
 * DER SCHALTER „Ort beim Fund speichern" (Artboard 43, WI-0116)
 *
 * Die ganze ZEILE ist der Schalter, nicht ein Kaestchen darin: dieselbe 56 px
 * hohe Trefferflaeche wie jede andere Kontozeile (Designspec 10.3 Punkt 1).
 * Die Pille rechts zeigt den Stand — was sie sagt, sagt `aria-checked`
 * daneben, und deshalb braucht sie keinen Text.
 * ------------------------------------------------------------------------ */
.konto__schalter {
  flex: none;
  display: flex;
  align-items: center;
  width: var(--konto-schalter-b);
  height: var(--konto-schalter-h);
  padding: var(--konto-schalter-polster);
  border-radius: var(--radius-pille);
  /* Aus: die ruhige Flaeche der uebrigen Felder. An: Terracotta — der
     Schalter IST die Aktion, und das ist die eine Aktionsfarbe (Designspec
     Kap. 9). */
  background: var(--feld-flaeche);
  justify-content: flex-start;
}

.konto__zeile--schalter[aria-checked='true'] .konto__schalter {
  background: var(--color-accent);
  justify-content: flex-end;
}

.konto__schalter-knopf {
  width: var(--konto-schalter-knopf);
  height: var(--konto-schalter-knopf);
  border-radius: var(--radius-pille);
  background: var(--cs-on-accent);
}

.konto__zeile .ikone--geraet {
  color: var(--color-accent-400);
}



/* DASSELBE BRIEFZEICHEN, ANDERER ORT (WI-0287, Artboard 43).
   Im Hinweiskasten von `00b` steht es gedaempft und in der Kastengroesse; in
   der Adresszeile von `43` zeichnet das Brett es gruen und so gross wie die
   anderen Zeilenzeichen. Es ist derselbe Pfad (`briefIkone`) — die Regel hier
   setzt nur, was die Zeile braucht, statt ein zweites Zeichen zu erfinden. */
.konto__zeile .ikone--brief {
  width: var(--konto-ikone);
  height: var(--konto-ikone);
  color: var(--gruen-icon);
}

/* DAS TABLETZEICHEN DER GERAETEWECHSEL-ZEILE (Artboard 43).

   HIER STAND EINE WAAGRECHTE LINIE UEBER DEM ZEICHEN, UND SIE WAR EIN
   SCHREIBFEHLER (WI-0331, Befund 43-3). Die Regel hiess bis WI-0302
   `.ikone--geraet, .ikone--zugang { … }`; WI-0302 hat die Zeile „Weg zurück"
   aus dem Produkt genommen (HANDOFF §24.2) und dabei den ZWEITEN Selektor
   samt Block geloescht — das Komma hinter dem ersten blieb stehen. Damit hing
   `.ikone--geraet` am naechsten Block, der folgte: `.konto__fuss`. Das
   Tabletzeichen bekam dessen `border-top` (die Haarlinie ueber den beiden
   Wegen hinaus), dessen `padding-top` und `display: flex` — und verlor
   gleichzeitig seine eigene Groesse.

   Es ist deshalb KEINE Trennlinie und war nie eine: der Entwurf zeichnet an
   dieser Stelle nur das Symbol. Was hier steht, ist der Block von WI-0099,
   jetzt mit genau einem Selektor. */
.ikone--geraet {
  flex: none;
  width: var(--konto-ikone);
  height: var(--konto-ikone);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* DIE BEIDEN WEGE HINAUS. Der Entwurf setzt sie unter eine Haarlinie, ohne
   Flaeche und ohne Rand — sie sind keine Aktionen, die eingeladen werden
   wollen. Und das Loeschen ist leiser als das Abmelden: die Reihenfolge und
   die Abstufung sind die ganze Warnung, die dieser Block traegt. */
.konto__fuss {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-top: var(--space-2);
  border-top: var(--karte-rand) solid var(--blatt-rand);
}

.konto__ausgang {
  display: flex;
  align-items: center;
  min-height: var(--konto-ausgang);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--raum-text-gedaempft);
  font-family: var(--font-body);
  font-size: var(--schrift-zeile);
  text-align: left;
  cursor: pointer;
}

.konto__ausgang--leise {
  color: var(--raum-text-schwach);
}

/* DIE ZEILE, HINTER DER NOCH ETWAS KOMMT (WI-0164, Artboard 43).
   Der Entwurf setzt den Winkel nur ans Loeschen, nicht ans Abmelden: das
   Abmelden oeffnet ein Blatt an Ort und Stelle, das Loeschen fuehrt auf einen
   eigenen Bildschirm (45b). Der Winkel sagt genau diesen Unterschied — und er
   sagt zugleich, dass hier noch nichts passiert. */
.konto__ausgang--weiter {
  gap: var(--space-2);
  justify-content: space-between;
}

.konto__ausgang--weiter .ikone--winkel {
  flex: none;
  width: var(--konto-winkel);
  height: var(--konto-winkel);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* DER HERAUSGEGEBENE RUECKWEG — derselbe Kasten auf 43, 44 und 45. */
.rueckweg {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
}

.rueckweg__hinweis {
  margin: 0;
  line-height: var(--zeilenhoehe-fliess);
}

.rueckweg--laedt {
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
}

.rueckweg--fehler {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-3);
  border-color: var(--gruen-rand);
}

.rueckweg__text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.rueckweg__titel {
  margin: 0;
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-kraeftig);
  line-height: var(--zeilenhoehe-fliess);
}

.rueckweg--fehler .ikone--warn {
  flex: none;
  width: var(--icon-mittel);
  height: var(--icon-mittel);
}

/* --- Artboard 44: der Gerätewechsel --- */

 /* Der Bildschirm nimmt die volle Buehnenhoehe — nur so kann „Fertig" unten
   verankert bleiben (HANDOFF §4.4: der Aktionsblock steht am Fuss). */
.geraetewechsel {
  flex: 1;
}

/* Die Ueberschrift ist zweizeilig, das Kreuz sitzt daneben — deshalb
   `flex-start` und nicht `center` (Handoff v2 §17, Zeile
   `44-account-device-switch`). */
.geraetewechsel__kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.geraetewechsel__titel {
  margin: 0;
}

/* Die Adresskarte: Etikett und Adresse, die Adresse in der Titelschrift.
   Lange Adressen brechen um, statt aus dem Kasten zu laufen. */
.geraetewechsel__adresse {
  border-radius: var(--geraetewechsel-adresse-radius);
  background: var(--cs-fill-1);
  border: 1px solid var(--cs-line-2);
  padding: var(--space-4) var(--space-4);
}

.geraetewechsel__adresse .abschnitt {
  margin-bottom: var(--space-2);
  line-height: 1.2;
}

.geraetewechsel__adresswert {
  font-family: var(--font-heading);
  font-size: var(--geraetewechsel-adresse-schrift);
  line-height: 1.2;
  letter-spacing: 0.02em;
  color: var(--cs-text);
  overflow-wrap: anywhere;
}

.geraetewechsel__schritte {
  list-style: none;
  margin: 0 0 var(--space-1);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.geraetewechsel__schritt {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--geraetewechsel-schritt-hoehe);
  font-size: var(--geraetewechsel-schritt-schrift);
  color: var(--cs-text);
}

.geraetewechsel__nummer {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--geraetewechsel-nummer);
  height: var(--geraetewechsel-nummer);
  border-radius: 50%;
  background: var(--geraetewechsel-nummer-flaeche);
  border: 1.5px solid var(--geraetewechsel-nummer-rand);
  font-size: var(--geraetewechsel-nummer-schrift);
  font-weight: 800;
  color: var(--geraetewechsel-nummer-text);
}

/* „Fertig" ist der bestaetigende Weg und bleibt unten verankert (HANDOFF
   §4.4): der Aktionsblock steht am Fuss, nicht dort, wo der Text aufhoert. */
.geraetewechsel__fuss {
  margin-top: auto;
  padding-top: var(--space-4);
}

/* --------------------------------------------------------------------------
 * ARTBOARD 45b — DIE FOLGEN DER KONTOLOESCHUNG (WI-0164, HANDOFF §5.5f)
 *
 * Eine volle Seite und kein Blatt: Kopf mit Kreuz, zwei Listen, der Ausweg
 * als Schlusszeile und der Aktionsblock unten verankert — dieselbe Geometrie
 * wie der Gerätewechsel (44), weil beide dasselbe sind: eine AUSKUNFT mit
 * einem Weg heraus, nicht eine Frage mit zwei Knoepfen.
 * ------------------------------------------------------------------------ */
.loeschfolgen {
  flex: 1;
}

/* Wie auf 44: die Ueberschrift kann zweizeilig werden, das Kreuz sitzt
   daneben — deshalb `flex-start`. */
.loeschfolgen__kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.loeschfolgen__titel {
  margin: 0;
}

.loeschfolgen__verluste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Der Ton der Verlustzeilen: der Warnton, aufgehellt. Er steht als
   ABLEITUNG und nicht als Wert — die vier Zeilen sind die einzige Stelle im
   Produkt, die ihn braucht, und wenn der Handoff den Warnton bewegt, gehen
   sie mit. */
.loeschfolgen__verlust {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
  color: var(--verlust-text);
}

.loeschfolgen__punkt {
  flex: none;
  width: var(--verlust-punkt);
  height: var(--verlust-punkt);
  border-radius: var(--radius-pille);
  background: var(--warn-icon);
}

/* Der Schlusssatz zeigt auf das mildere Abmelden. Er ist LEISER als der
   Fliesstext darueber — er soll nicht mit den zwei Listen konkurrieren,
   sondern nach ihnen gelesen werden. */
.loeschfolgen__ausweg {
  margin: 0;
  color: var(--raum-text-schwach);
}

.loeschfolgen__ausweg strong {
  color: var(--raum-text-hell);
  font-weight: var(--gewicht-kraeftig);
}

/* Der Aktionsblock bleibt unten verankert (HANDOFF §4.4), wie „Fertig" auf
   44. Was hier oben steht, ist der MILDE Weg — die Reihenfolge ist die ganze
   Aussage dieses Bildschirms (DEL-2). */
.loeschfolgen__fuss {
  margin-top: auto;
  padding-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Die Seite traegt das Bestaetigungsblatt von `45c` NEBEN ihrem Inhalt
   (WI-0165) — genau wie `.kontoseite` das Abmeldeblatt. Ohne `position:
   relative` haette die Blattlage keinen Bezug, und ohne `flex: 1` stuende der
   Aktionsblock von `45b` nicht mehr am Fuss. */
.loeschseite {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
}

/* --- Artboard 45: die Bestätigung vor dem echten Abmelden --- */

/* Dieselbe Geometrie traegt die getippte Bestaetigung der Kontoloeschung
   (Artboard 45c, WI-0165). Sie bekommt KEINEN eigenen Blattstil — ein zweites
   Blatt, das anders aussieht, waere ein zweiter Pfad. Der Unterschied liegt in
   der Knopfreihenfolge und im Feld, nicht in der Flaeche. */
.abmelden__blatt,
.kontoloeschen__blatt {
  position: relative;
  margin: 0 var(--space-4) var(--space-6);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.abmelden__titel {
  margin: 0;
}

.abmelden__blatt .geraetewechsel__adresse {
  border-radius: var(--abmelden-adresse-radius);
  padding: var(--abmelden-adresse-polster) var(--space-4);
  /* Brett: 14 px unter dem Satz (Blattabstand 12), 20 px über den Knöpfen. */
  margin: 2px 0 var(--space-2);
}

.abmelden__blatt .geraetewechsel__adresse .abschnitt {
  margin-bottom: var(--abmelden-adresse-etikett-abstand);
}

.abmelden__blatt .geraetewechsel__adresswert {
  font-size: var(--abmelden-adresse-schrift);
  line-height: var(--abmelden-adresse-zeile);
}

/* --- Artboard 45c: die getippte Bestätigung (WI-0165) --- */

/* Der Entwurf setzt das Feld DICHT unter seine Versalzeile und laesst darunter
   den Elternsatz folgen; die Gruppe ist damit enger als der Blattabstand um
   sie herum. */
.kontoloeschen__feldgruppe {
  gap: var(--space-2);
}

/* DAS FELD IST HOEHER ALS JEDES ANDERE IM PRODUKT — 52 px statt 48. Der
   Entwurf zeichnet das so, und es ist kein Versehen: das hier ist das einzige
   Feld, dessen Inhalt eine ganze Sammlung kostet, und es soll sich unter dem
   Daumen anders anfuehlen als die Codeeingabe auf 23.

   DER RAND TRAEGT DEN WARNTON, nicht den ruhigen Feldrand — dieselbe Farbe wie
   der zerstoerende Knopf darunter, damit Feld und Folge sichtbar zusammen
   gehoeren. Er steht als ABLEITUNG aus --warn-icon und nicht als Wert: bewegt
   der Handoff den Warnton, geht er mit. */
.feld--bestaetigung {
  min-height: var(--bestaetigung-hoehe);
  border-color: var(--bestaetigung-rand);
  font-family: var(--font-heading);
  font-size: var(--bestaetigung-schrift);
}

/* --------------------------------------------------------------------------
 * ARTBOARD 45d — DER LAUFZUSTAND DER KONTOLOESCHUNG (WI-0166, HANDOFF §5.5f)
 *
 * Mittig auf der ganzen Seite, ohne Kopfzeile und ohne Aktionsblock: der
 * Entwurf zentriert Ring, Ueberschrift und die beiden Zeilen im leeren Raum.
 * Es gibt hier keinen Fuss, weil es keinen Knopf gibt — und keinen Knopf,
 * weil es nichts abzubrechen gibt (DEL-4).
 * ------------------------------------------------------------------------ */
.loeschlauf {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
}

/* Der Ring traegt den Bogen ueber sich und die Glyphe in sich. `position:
   relative` ist deshalb Bedingung und nicht Geschmack. */
.loeschlauf__ring {
  position: relative;
  flex: none;
  width: var(--loeschlauf-ring);
  height: var(--loeschlauf-ring);
  border-radius: var(--radius-pille);
  border: var(--loeschlauf-ring-rand) solid var(--loeschlauf-ring-farbe);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-6);
}

/* Der drehende Bogen: ein Kreis, von dem nur die obere Kante Farbe hat. Er
   liegt um die Randstaerke NACH AUSSEN versetzt, damit er den ruhigen Ring
   ueberdeckt statt daneben zu laufen. */
.loeschlauf__bogen {
  position: absolute;
  inset: calc(var(--loeschlauf-ring-rand) * -1);
  border-radius: var(--radius-pille);
  border: var(--loeschlauf-bogen) solid transparent;
  border-top-color: var(--warn-icon);
  /* Der Entwurf nennt den Lauf `cs-spin`. Die App hat ihn laengst — unter dem
     Namen `kreisel-dreht`, Zeile fuer Zeile derselbe („to { rotate(360deg) }").
     Ein zweiter Keyframe mit gleichem Inhalt waere ein zweiter Halter
     derselben Bewegung; genommen wird der vorhandene. */
  animation: kreisel-dreht var(--loeschlauf-dauer) linear infinite;
}

.loeschlauf__glyphe {
  width: var(--loeschlauf-glyphe);
  height: var(--loeschlauf-glyphe);
  stroke-width: var(--loeschlauf-strich);
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--warn-icon);
}

.loeschlauf__titel {
  margin: 0;
  font-size: var(--loeschlauf-titel-schrift);
}

.loeschlauf__umfang {
  margin: 0;
  font-size: var(--loeschlauf-umfang-schrift);
}

.loeschlauf__bleib {
  margin: 0;
  font-size: var(--loeschlauf-bleib-schrift);
  color: var(--raum-text-schwach);
}

/* --------------------------------------------------------------------------
 * ARTBOARD 45e — DER ABSCHLUSS DER KONTOLOESCHUNG (WI-0167)
 *
 * Dieselbe Buehne wie `45d`: mittig auf der ganzen Seite, ohne Kopfzeile.
 * Anders ist, dass hier wieder etwas zu tun ist — Balken und Knopf stehen im
 * Block mit, nicht am unteren Rand verankert. Der Entwurf zentriert die ganze
 * Saeule (`justify-content:center`), und das ist an dieser Stelle kein
 * Widerspruch zur Regel „Aktionen in die untere Haelfte" (Designspec 10.3):
 * es steht nur EINE Aktion da, sie ist die Fortsetzung dessen, was der Balken
 * darueber ohnehin tut, und der Bildschirm ist nach vier Sekunden vorbei.
 * ------------------------------------------------------------------------ */
.loeschfertig {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
}

/* Der Salbeikreis. Er hat KEINEN Bogen und dreht sich nicht — der Lauf ist
   vorbei, und ein zweiter Kreisel hier saehe aus, als ginge es weiter. */
.loeschfertig__ring {
  flex: none;
  width: var(--loeschfertig-ring);
  height: var(--loeschfertig-ring);
  border-radius: var(--radius-pille);
  border: var(--loeschfertig-ring-rand) solid var(--loeschfertig-ring-farbe);
  background: var(--loeschfertig-ring-flaeche);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-6);
}

.loeschfertig__glyphe {
  width: var(--loeschfertig-glyphe);
  height: var(--loeschfertig-glyphe);
  stroke-width: var(--loeschfertig-strich);
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--gruen-icon);
}

.loeschfertig__titel {
  margin: 0;
  font-size: var(--loeschfertig-titel-schrift);
}

.loeschfertig__dank {
  margin: 0 0 var(--space-3);
  font-size: var(--loeschfertig-dank-schrift);
}

/* Der Balken zieht ueber die volle Breite — er ist das Mass der Wartezeit,
   und ein zentrierter Stummel waere keines. */
.loeschfertig__balken {
  align-self: stretch;
  height: var(--loeschfertig-balken);
  border-radius: var(--radius-pille);
  background: var(--loeschfertig-balken-spur);
  overflow: hidden;
}

/* Ohne Lauf steht er VOLL da — genau wie beim Rundenauftakt (28d/28e) und aus
   demselben Grund: `cs-startbar` zieht von 0 auf 100 %, also ist 100 % der
   Ausgangswert. Andersherum saehe eine leere Spur bei abgeschalteter Bewegung
   aus wie etwas, das haengt — und hier haengt nichts, die Frist laeuft in
   JavaScript weiter. */
.loeschfertig__balkenlauf {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: var(--radius-pille);
  /* Der Entwurf schreibt `background: var(--color-accent)` aus — dieselbe
     Quelle, die §16 bindet und die die Hauptaktion darunter traegt. Nicht
     --cs-accent: der ist wertgleich, aber die App ruft durchgaengig
     --color-accent ab (tests/design.test.js, WI-0112). */
  background: var(--color-accent);
  animation: cs-startbar var(--loeschfertig-balken-dauer) linear forwards;
}

.loeschfertig__gleich {
  margin: var(--space-1) 0 var(--space-4);
  font-size: var(--loeschfertig-gleich-schrift);
  color: var(--raum-text-schwach);
}

.loeschfertig__fuss {
  align-self: stretch;
}

/* --------------------------------------------------------------------------
 * ARTBOARD 45f — DER FEHLER MIT DEM VOLLSTAENDIGEN KONTO (WI-0166)
 *
 * Dieselbe Geometrie wie `45b` und 44: Kopf mit Kreuz oben, Inhalt darunter,
 * Aktionsblock am Fuss verankert. Neu sind die beiden Bloecke dazwischen —
 * der amberne mit der Zusicherung und der leise mit dem Weg von Hand.
 * ------------------------------------------------------------------------ */
.loeschfehler {
  flex: 1;
}

.loeschfehler__kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.loeschfehler__titel {
  margin: 0;
  font-size: var(--loeschfehler-titel-schrift);
}

/* Der Block, der die Nachricht traegt. Amber, aber leiser als eine Warnung:
   er beruhigt, er alarmiert nicht. */
.loeschfehler__block {
  border-radius: var(--loeschfehler-radius);
  background: var(--loeschfehler-flaeche);
  border: 1px solid var(--loeschfehler-rand);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* DIE ERSTE ZEILE IST DIE NACHRICHT — groesser, heller und kraeftiger als der
   Satz darunter, der sie nur begruendet. Der Entwurf setzt sie fett; das ist
   hier keine Betonung, sondern die Leserichtung. */
.loeschfehler__zusicherung {
  margin: 0;
  font-size: var(--loeschfehler-schrift-zusicherung);
  line-height: var(--zeilenhoehe-fliess);
  font-weight: var(--gewicht-kraeftig);
  color: var(--loeschfehler-zusicherung-text);
}

.loeschfehler__text {
  margin: 0;
  font-size: var(--schrift-hinweis);
}

/* Der zweite Block zeigt auf den Wunschkanal. Er ist neutral — er traegt
   keinen Warnton, weil er keine Nachricht ueber das Konto macht, sondern
   einen Weg nennt. */
.loeschfehler__weg {
  border-radius: var(--loeschfehler-weg-radius);
  background: var(--cs-fill-1);
  border: 1px solid var(--cs-line-2);
  padding: var(--space-3) var(--space-4);
}

.loeschfehler__weg .hinweis {
  margin: 0;
  font-size: var(--loeschfehler-schrift-weg);
  color: var(--raum-text-gedaempft);
}

/* Wie auf `45b`: der Aktionsblock steht am Fuss (HANDOFF §4.4). Oben der
   Weg, den der Entwurf als Hauptaktion setzt — hier ist es der zweite
   Versuch, denn das Konto ist ja noch da. */
.loeschfehler__fuss {
  margin-top: auto;
  padding-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* --------------------------------------------------------------------------
 * Wunschkanal (Spec 12.1)
 *
 * Eigener Bereich, dieselben Bauteile wie ueberall: .chip fuer Art und Filter,
 * .btn fuer die Aktionen, .leerzustand/.fehlerbox/.skelett fuer die vier
 * Listenzustaende. Hier steht nur, was es sonst nirgends gibt.
 * ------------------------------------------------------------------------ */

/* Der Wunschkanal nimmt die volle Hoehe, damit „Abschicken" am FUSS steht
   und nicht dort, wo der Text zufaellig aufhoert (HANDOFF §4.4, wie auf 44).
   Ohne das blieben auf einem 793-px-Geraet gut hundert Pixel unter dem Knopf
   frei — Designspec Kap. 10.3 Punkt 3. */
.wunsch,
.bilanz {
  flex: 1;
}

/* Der Entwurf zeichnet die Felder OHNE Karte darum (Artboard 46): die
   Artenreihe, das Beschreibungsfeld und der Bildkasten liegen direkt auf dem
   Raum. Die Gruppe bleibt trotzdem eine — durch den Abstand, nicht durch
   einen Rahmen. */
.wunsch__formular {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Ein mehrzeiliges Feld ist keine Pille — sonst schneidet der Radius die
   erste und letzte Zeile an. */
.feld--flaeche {
  min-height: var(--wunsch-flaeche-hoehe);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  line-height: var(--zeilenhoehe-fliess);
  resize: vertical;
}

.feld--datei {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--schrift-klein);
}

.wunsch__anhang {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Der Anhang ist ein BELEG, kein Schmuckbild: er wird VOLLSTAENDIG gezeigt.
   `cover` schnitt einem hochkanten Handyfoto oben und unten genau das weg, was
   der Melder zeigen wollte. Die Groesse ergibt sich jetzt aus dem Bild selbst
   — in der Breite auf die Karte begrenzt, in der Hoehe auf das Token. Was
   zuerst anschlaegt, entscheidet das Bild: hochkant die Hoehe, quer die
   Breite. `align-self` verhindert, dass die Spalte das Bild in die Breite
   zieht (Flex-Kinder werden sonst gedehnt). */
.wunsch__anhang-bild {
  align-self: center;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--wunsch-anhang-hoehe);
  object-fit: contain;
  border-radius: var(--radius-md);
  background: var(--foto-flaeche);
}

.wunsch__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Eine Meldung ist eine Haarlinienkarte ohne Fuellung (Artboard 47) — nur die
   eine, die etwas vom Melder WILL, traegt Farbe (siehe unten). Eine gefuellte
   Flaeche an jeder Meldung liesse die Liste wie einen Stapel Knoepfe aussehen
   und naehme der einen wichtigen ihre Aussage. */
.wunsch__eintrag {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--blatt-rand);
  border-radius: var(--radius-karte);
}

/* „kannst du testen" ist die einzige Zeile, die etwas vom Melder will — sie
   traegt den Erfolgston, in der Flaeche wie in der Pille (Artboard 47). */
.wunsch__eintrag:has(.stand-pille[data-stand-wert='review']) {
  border-color: var(--gruen-rand);
  border-width: var(--karte-rand);
  background: var(--gruen-flaeche);
}

/* Eine Absage tritt zurueck (Artboard 47: `opacity: .75`). Sie bleibt lesbar
   — nur nicht mehr so laut wie das, was noch laeuft. */
.wunsch__eintrag:has(.stand-pille[data-stand-wert='rejected']) {
  opacity: var(--wunsch-abgesagt-deckkraft);
}

.stand-pille[data-stand-wert='rejected'] {
  border-color: var(--warn-flaeche);
  background: var(--warn-flaeche);
  color: var(--warn-icon);
}

.wunsch__kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Der Stand in Klartext. Bewusst NICHT in der Aktionsfarbe: er ist eine
   Auskunft, kein Knopf. */
.stand-pille {
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--feld-rand);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-size: var(--schrift-h6);
  font-weight: var(--gewicht-fett);
  text-transform: uppercase;
  letter-spacing: var(--laufweite-versal);
  padding: var(--space-1) var(--space-3);
}

/* „kannst du testen" ist die einzige Zeile, die etwas vom Melder will. */
.stand-pille[data-stand-wert='review'] {
  border-color: var(--gruen-rand);
  background: var(--gruen-flaeche);
  color: var(--gruen-text);
}

.verlauf {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.verlauf__eintrag {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-left: var(--space-3);
  border-left: var(--wunsch-verlauf-strich) solid var(--feld-rand);
}

.verlauf__eintrag[data-quelle='factory'] {
  border-left-color: var(--color-accent);
}

.wunsch__antwortfeld {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.wunsch__antwortfeld .feld--flaeche {
  min-height: var(--wunsch-antwort-hoehe);
}

/* Die beiden Test-Knoepfe stehen seit WI-0052 an JEDER Meldung, direkt ueber
   dem Freitextfeld — dort, wo der Melder ohnehin hinsieht, wenn er etwas
   sagen will. Was schon gedrueckt wurde, steht gedrueckt da; der Zustand kommt
   aus der Akzentrampe (Designspec Kap. 7.4). Gruen ist eine Auskunftsfarbe und
   wird nie ein Knopf. */
.wunsch__antwortfeld .knopfreihe .btn[aria-pressed='true'] {
  border-color: var(--color-accent);
  color: var(--color-accent-300);
}

/* --- Artboards 46 und 47: die Kopfzeile mit dem Schliesskreuz (WI-0100) ---

   Handoff v2 §17 haengt an BEIDE Wunschkanal-Bildschirme ein 34-px-Kreuz
   rechts neben die Ueberschrift. Es ist dieselbe Scheibe wie auf der
   Kartenseite (`--kreuz-*`) und bekommt deshalb KEINEN eigenen Stil — ein
   zweites Kreuz, das anders aussieht, waere ein zweiter Pfad.

   `flex-start` wie auf 44: die Ueberschrift kann umbrechen, das Kreuz bleibt
   dann trotzdem an der Oberkante stehen und wandert nicht in die Mitte. */
.wunsch__kopfzeile {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.wunsch__titel {
  margin: 0;
}

/* Der Zeichenzaehler unter dem Beschreibungsfeld (Artboard 46). Er steht
   rechtsbuendig, weil er zum Feld darueber gehoert und nicht zur Beschriftung
   darunter. */
.wunsch__zaehler {
  align-self: flex-end;
}

/* Bereich und Gerät (Spec 12.1). Sie sind eine AUSKUNFT und kein Knopf: keine
   Randlinie, kein Zeiger, nichts zu tippen. Die Flaeche ist dieselbe wie am
   Chip, damit sie in derselben Reihe nicht aus dem Rahmen fallen. */
.chip--auskunft {
  border-color: transparent;
  color: var(--raum-text-schwach);
  cursor: default;
}

/* --------------------------------------------------------------------------
 * Artboard 41 — die eigene Bilanz (WI-0100, Produktspec 4.8)
 *
 * KEINE RANGLISTE, KEINE LIGA, KEINE WERTUNG. Was hier nicht steht, ist die
 * Aussage des Bildschirms; im CSS heisst das, dass es keine Platzierungs-,
 * Medaillen- oder Vergleichsklasse gibt, an die man spaeter eine anhaengen
 * koennte.
 * ------------------------------------------------------------------------ */

.bilanz__kacheln {
  display: flex;
  gap: var(--space-2);
}

/* Die drei Zahlen im Kopf stehen GLEICH gross nebeneinander — auch die
   Niederlagen. Die Bilanz ist ehrlich ueber sie (Spec 4.8), und eine kleinere
   Kachel waere ein leises Wegschauen. */
.bilanz__kachel {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-2);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-lg);
  background: var(--feld-flaeche);
  text-align: center;
}

/* Die Siegeskachel traegt den Erfolgston (Artboard 41). Gruen ist hier eine
   Auskunftsfarbe und wird nie ein Knopf (Designspec Kap. 9). */
.bilanz__kachel[data-bilanz='siege'] {
  border-color: var(--gruen-rand);
  background: var(--gruen-flaeche);
}

.bilanz__kachel[data-bilanz='siege'] .bilanz__zahl {
  color: var(--gruen-text);
}

/* Die beiden Kartenkacheln stehen linksbuendig: dort steht die Beschriftung
   ueber der Zahl, nicht darunter (Artboard 41). */
.bilanz__kacheln--karten .bilanz__kachel {
  align-items: flex-start;
  flex-direction: column-reverse;
  text-align: left;
}

.bilanz__zahl {
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--schrift-h3);
  line-height: 1;
  color: var(--raum-text);
}

.bilanz__marke {
  font-size: var(--schrift-klein);
  color: var(--raum-text-schwach);
}

.bilanz__block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-karte);
  background: var(--feld-flaeche);
}

.bilanz__staerkste {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  font-size: var(--schrift-h4);
  color: var(--raum-text);
}

.bilanz__kategorien {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.bilanz__kategorie {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* DIE BESCHRIFTUNGSSPALTE — UND SIE HAELT JETZT AUCH (WI-0331, Befund 41-1).

   Die Breite stand hier seit WI-0100 (`--bilanz-name-breite`, die 96 px des
   Bretts) und `flex: none` dazu. Was fehlte, war die SCHRANKE: ohne sie
   laeuft ein zu langer Text ueber die Kante seiner Box hinaus, und die Box
   daneben ist der Balken. „Höchstgeschwindigkeit" lief damit UNTER den
   Balken — ein Balken, der Text ueberlagert.

   DREI ZEILEN, UND ALLE DREI SIND NOETIG: `nowrap` haelt den Text in einer
   Zeile (ein Umbruch machte die Zeile hoeher als den Balken daneben),
   `overflow: hidden` schneidet an der Spaltenkante, `text-overflow` setzt
   das Auslassungszeichen statt hart abzuschneiden. Die Spalte ist damit
   geometrisch dicht, unabhaengig von Sprache und Textlaenge — die kuerzere
   Beschriftung in `bilanzKategorieName` ist die LESBARE Loesung, diese Regel
   die belastbare. */
.bilanz__kategorie-name {
  width: var(--bilanz-name-breite);
  flex: none;
  overflow: hidden;
  font-size: var(--schrift-klein);
  color: var(--raum-text-gedaempft);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Derselbe Balken wie auf der Karte — dieselbe Hoehe, dieselbe Spur. Ein
   zweiter Balkenstil daneben waere genau der zweite Pfad, den Designspec
   Kap. 9 verbietet. */
.bilanz__balken {
  flex: 1;
  height: var(--balken-hoehe);
  border-radius: var(--radius-pille);
  background: var(--balken-spur);
  overflow: hidden;
}

.bilanz__balken-fuellung {
  display: block;
  height: 100%;
  background: var(--bilanz-balken-leise);
}

/* Nur die staerkste Kategorie bekommt den vollen Akzent — sie ist die eine
   Zeile, die den Deckbau aendert (Spec 4.8). */
.bilanz__kategorie[data-fuehrend='ja'] .bilanz__balken-fuellung {
  background: var(--color-accent);
}

.bilanz__kategorie-anteil {
  width: var(--bilanz-anteil-breite);
  flex: none;
  text-align: right;
  font-size: var(--schrift-klein);
  color: var(--raum-fliess);
}

.bilanz__zeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: var(--karte-rand) solid var(--blatt-rand);
  border-radius: var(--radius-lg);
  background: var(--feld-flaeche);
  color: var(--raum-fliess);
}

.bilanz__gegner {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Eine Zeile je Gegner — und nichts darueber hinaus. Kein Rang, keine
   Platzziffer, keine Sortierung nach Staerke: die Reihenfolge ist die des
   ersten Aufeinandertreffens (src/duell.js). */
.bilanz__gegner-zeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--blatt-rand);
  border-radius: var(--radius-md);
}

.bilanz__gegner-name {
  flex: 1;
  color: var(--raum-text);
}

/* --------------------------------------------------------------------------
 * Tableiste und Toast
 * ------------------------------------------------------------------------ */

/* Die schwebende Pille (HANDOFF §4.3). EINGERUECKT, nicht ueber die volle
   Breite: sie steht mittig, ist nur so breit wie ihre drei Eintraege und
   laesst links und rechts Rand stehen. Vor WI-0093 hing sie mit vier
   Eintraegen auf jedem Bildschirm ueber beide Kanten hinaus. */
.tableiste {
  position: fixed;
  left: 50%;
  bottom: var(--tableiste-unten);
  /* Der Home-Indikator kommt DAZU (WI-0417). Als Aussenrand statt im
     `bottom`, damit jede Regel, die `bottom` umstellt, ihn behaelt. */
  margin-bottom: var(--sicher-unten);
  transform: translateX(-50%);
  display: flex;
  gap: var(--tableiste-luecke);
  padding: var(--tableiste-polster);
  border: var(--tableiste-randbreite) solid var(--tableiste-randfarbe);
  border-radius: var(--radius-pille);
  background: var(--tableiste-flaeche);
  backdrop-filter: var(--tableiste-blur);
  box-shadow: var(--shadow-lg);
  /* Der Riegel gegen den Rueckfall: sollte je ein Eintrag dazukommen, bricht
     die Leiste nicht mehr aus dem Geraet aus, sondern bleibt innerhalb der
     393 px — der Befund wuerde es dann an den Eintraegen zeigen, nicht an
     einem negativen Rand, der jeden anderen Messwert mitreisst. */
  max-width: calc(100% - var(--tableiste-unten) * 2);
}

.tableiste[hidden] {
  display: none;
}

/* Der Eintrag. Der Zaehler sitzt IM Knopf, nicht daneben: die Leiste bleibt
   eine Reihe gleich hoher Pillen, und der Reiter behaelt seine
   Trefferflaeche. */
.tableiste__knopf {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--tableiste-luecke);
  border: 0;
  border-radius: var(--radius-pille);
  background: transparent;
  color: var(--raum-fliess);
  font-family: var(--font-body);
  font-size: var(--tableiste-schrift);
  font-weight: var(--gewicht-heading);
  padding: 0 var(--tableiste-knopf-polster);
  /* Die Hoehe der Leiste ist kein Zufallsergebnis aus Polster und Schriftgrad
     mehr, sondern ein Token — die Kartenseite rechnet damit (WI-0038). */
  min-height: var(--tableiste-knopf);
  cursor: pointer;
}

.tableiste__knopf[aria-current='page'] {
  /* §4.3: `rgba(198,113,57,.9)` — der Akzent, leicht durchscheinend, damit
     die Pille auf dem verschwommenen Grund nicht wie ein Aufkleber sitzt. */
  background: color-mix(in srgb, var(--color-accent) 90%, transparent);
  color: var(--btn-text);
  font-weight: var(--gewicht-fett);
}

/* Der Zaehler am Duell-Reiter (Artboard 22, HANDOFF §4.3). */
.tableiste__zaehler {
  min-width: var(--zaehler-seite);
  height: var(--zaehler-seite);
  padding: 0 var(--zaehler-polster);
  border-radius: var(--radius-pille);
  background: var(--zaehler-flaeche);
  color: var(--zaehler-text);
  font-size: var(--zaehler-schrift);
  font-weight: var(--gewicht-fett);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tableiste__knopf[aria-current='page'] .tableiste__zaehler {
  background: var(--zaehler-flaeche-aktiv);
  color: var(--zaehler-text-aktiv);
}

/* Der Toast steht UEBER der Leiste, nicht auf ihr. Bis WI-0093 war das mit
   `+ --btn-hoehe` geschaetzt und ging knapp auf; seit die Leiste ihre Masse
   aus §4.3 hat, wird gerechnet: ihr Abstand nach unten, ihre Hoehe, dann
   eine Stufe Luft. */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tableiste-unten) + var(--tableiste-hoehe) + var(--space-2));
  /* Wie bei der Leiste: der Home-Indikator als Aussenrand, damit die drei
     Regeln weiter unten, die `bottom` je Bildschirm umstellen, ihn
     behalten (WI-0417). */
  margin-bottom: var(--sicher-unten);
  transform: translateX(-50%);
  border-radius: var(--radius-pille);
  background: var(--toast-flaeche);
  color: var(--toast-text);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-fett);
  padding: var(--space-2) var(--space-6);
  box-shadow: var(--shadow-md);
}

/* Steht die Leiste NICHT — Wurf, laufende Scan-Strecke, Vollbild,
   Loeschabfrage —, rueckt der Toast an ihre Stelle. Sonst schwebte er dort
   ohne Grund einen Leistenplatz hoch und legte sich auf den Handlungsblock
   des Bildschirms; genau das ist er auf dem Wartezustand (WI-0069) getan.
   Der Selektor greift, weil die Leiste im Geruest das Geschwister VOR dem
   Toast ist (app.js: buehne, tableiste, toast) — es braucht dafuer keine
   zweite Klasse und keine Zeile JavaScript. */
.tableiste[hidden] ~ .toast {
  bottom: var(--tableiste-unten);
}

/* AUF DEM SCAN-BILDSCHIRM STEHT DER TOAST UEBER DEM AUSLOESER (WI-0110).
   Seit der Ausloeser unten verankert ist (Artboard 07), liegen beide an
   derselben Kante: die Meldung „Über den QR-Code verbunden" deckte den
   Knopf zu — sichtbar geworden im Bildvergleich (qr-sucher.png). Der Toast
   ist kurzlebig, der Ausloeser ist die Haupthandlung des Bildschirms; also
   weicht der Toast. Gerechnet, nicht geschaetzt: Fussfreiraum der Buehne,
   der Knopf, eine Stufe Luft.

   Der Selektor greift, weil die Buehne im Geruest vor dem Toast steht
   (app.js: buehne, tableiste, toast) — wie bei der Regel darueber. */
.app__buehne[data-bildschirm='scannen'] ~ .toast {
  bottom: calc(var(--buehne-unten) + var(--ausloeser) + var(--space-2));
}

/* DASSELBE AUF DER ERKENNUNGSSEITE (WI-0113). Seit der Wartezustand die ganze
   Seite von Artboard 08 traegt, steht sein Ausgang „Weiter fotografieren"
   unten verankert — und der Toast „Wird noch erkannt" legte sich genau auf
   seine Mitte. Im Blatt am unteren Rand sass der Knopf hoeher, deshalb fiel es
   dort nicht auf. Gerechnet, nicht geschaetzt: Fussfreiraum dieser Seite
   (--space-8, aus der Massregel der Ablaufseiten weiter oben), Knopfhoehe,
   eine Stufe Luft. */
.app__buehne[data-bildschirm='scan_laeuft'] ~ .toast {
  bottom: calc(var(--space-8) + var(--btn-hoehe) + var(--space-2));
}

.toast[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
 * Papier — die Karte wird auch gedruckt, und Papier ist nicht dunkel.
 * ------------------------------------------------------------------------ */

@media print {
  .app {
    background: var(--color-bg);
  }

  .tableiste,
  .toast,
  .knopfreihe,
  .btn,
  /* Der Wunschkanal ist ein Bildschirmbereich. Auf Papier — also im hellen
     Raum — waere sein gedaempfter Text auf hellem Grund nicht mehr lesbar,
     und gedruckt werden soll ohnehin nur die Karte. */
  .wunsch__formular,
  .wunsch__liste {
    display: none;
  }

  .karte {
    box-shadow: var(--kante-neutral);
    break-inside: avoid;
  }
}

/* ============================================================================
 * Freunde, Deckbau, Duell (T3 — Produktspec Kap. 7, Spec 4.7)
 *
 * Reuse statt Neubau: das Kacheln-Raster, die Chips, das Blatt, `.code`,
 * `.leerzustand` und `.btn` sind schon da und werden hier nur benutzt — kein
 * zweiter Renderer, kein zweiter Fehlerkanal (Designspec Kap. 9).
 * ========================================================================= */

/* `.freund-hinweis` ist mit WI-0068 ERSATZLOS entfallen. Der Satz lag ueber
   dem Livebild, war dort unlesbar und ueberlappte den Ausloeser; im Sucher
   steht seitdem nichts ausser Hinweispille, Eckwinkeln, Silhouette und
   Ausloeser (Produktspec 4.2, HANDOFF §6 Zeile 07). Der Freundescode lebt auf
   dem Duell-Bildschirm. */

.freunde__code {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* WO DER ENTWURF QR UND CODE ZEICHNET (Artboard 23, WI-0096): NEBENeinander.
   Links das Quadrat mit fester Kante, rechts die Spalte mit Code, Satz und
   „Neuen Code holen". Untereinander nahm der Block so viel Hoehe, dass das
   Eingabefeld darunter unter die Falz rutschte. */
.freunde__code-paar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.freunde__code-spalte {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}

/* Echtes Schwarz auf echtem Weiss (siehe --qr-hell/--qr-dunkel im
   Token-Block) — sonst liest keine Kamera den Code. */
.freunde__qr {
  width: var(--qr-seite);
  height: var(--qr-seite);
  flex: none;
  background: var(--qr-flaeche);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  fill: var(--qr-dunkel);
}

.freunde__code-text {
  font-size: var(--schrift-h4);
}

/* --------------------------------------------------------------------------
 * „Dein Code" waehrend des Abrufs und wenn er scheitert — Artboard 24
 * (WI-0073)
 *
 * NIE EINE LEERE FLAECHE (Spec 4.7). Bis hierher stand zwischen Ueberschrift
 * und „Neuen Code holen" nichts, solange kein Code da war. Der Entwurf setzt
 * dorthin einen Kasten: Warnsymbol im Kreis links, Ueberschrift und Satz
 * rechts, darunter der erneute Versuch — und unter dem Kasten die Zeile, dass
 * der Weg ueber den Code des anderen offen bleibt.
 *
 * Der Block selbst ist zentriert (der QR steht mittig); der Kasten ist es
 * NICHT: ein Fliesssatz ueber drei Zeilen liest sich linksbuendig, und der
 * Entwurf zeichnet ihn so.
 * ------------------------------------------------------------------------ */

/* Der Block ist zentriert, weil der QR es ist. Der Fehlerfall traegt an
   dieser Stelle kein Bild, sondern drei Zeilen Fliesstext — und die liest der
   Entwurf linksbuendig. Die Ueberschrift darueber bleibt, wo sie im geladenen
   Zustand steht: sie darf beim Zustandswechsel nicht springen. */
.freunde__code[data-code-stand='fehler'] > .meta {
  align-self: stretch;
  text-align: left;
}

.freunde__code-fehler {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  width: 100%;
  padding: var(--code-fehler-polster);
  border-radius: var(--code-fehler-radius);
  background: var(--code-fehler-flaeche);
  border: var(--code-fehler-strich) solid var(--code-fehler-rand);
  text-align: left;
}

.freunde__code-fehler-zeichen {
  width: var(--code-fehler-zeichen);
  height: var(--code-fehler-zeichen);
  flex: none;
  /* Der Entwurf legt das Symbol in einen 44-px-Kreis in der Warnflaeche. Der
     Kreis ist Polster, nicht Rahmen — deshalb steckt er als Box-Shadow am
     Symbol statt als zweites Element im DOM. */
  margin: calc((var(--code-fehler-kreis) - var(--code-fehler-zeichen)) / 2);
  border-radius: var(--radius-pille);
  box-shadow: 0 0 0 calc((var(--code-fehler-kreis) - var(--code-fehler-zeichen)) / 2)
    var(--warn-flaeche);
  background: var(--warn-flaeche);
  fill: none;
  stroke: var(--warn-icon);
  stroke-width: var(--strich-meldung);
  stroke-linecap: round;
}

.freunde__code-fehler-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}

.freunde__code-fehler-titel {
  margin: 0;
  color: var(--raum-text);
  font-family: var(--font-body);
  font-size: var(--schrift-fliess);
  font-weight: var(--gewicht-heading);
  line-height: var(--zeilenhoehe-fliess);
}

/* Der Wartezustand. HANDOFF §6 laesst genau ein Bauteil zu — den
   eingebetteten Kreisel —, und ausdruecklich KEIN Skelett. Der Satz daneben
   ist der Unterschied zum Fehlerfall: er sagt, dass noch gewartet wird. */
.freunde__code-laedt {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.kreisel {
  width: var(--kreisel-groesse);
  height: var(--kreisel-groesse);
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--kreisel-strich);
  stroke-linecap: round;
  /* Ein Viertelkreis, der sich dreht: der Umfang von r=9 ist 2*pi*9 = 56,55. */
  stroke-dasharray: 14 43;
  animation: kreisel-dreht var(--kreisel-dauer) linear infinite;
  transform-origin: 50% 50%;
}

@keyframes kreisel-dreht {
  to {
    transform: rotate(360deg);
  }
}

.freunde__eingabe {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* --------------------------------------------------------------------------
 * Die Meldung unter dem Eingabefeld — Artboard 23 (WI-0071)
 *
 * Der Entwurf zeichnet sie als Zeile aus zwei Teilen: ein 18 px grosses
 * Symbol links, oben ausgerichtet, und der Satz daneben. Beides in der
 * Warnfarbe (--warn-icon, HANDOFF §11 `--cs-warn`), Fliessgroesse, normale
 * Zeilenhoehe. Keine Flaeche, kein Rahmen, kein Kasten — die Meldung gehoert
 * zum Feld darueber und soll nicht wie ein eigener Block wirken.
 *
 * Die gute Meldung ist DIESELBE Zeile in Gruen (--gruen-icon): derselbe Ort
 * fuer dieselbe Frage. Terracotta bleibt den Knoepfen (HANDOFF §7 Regel 13).
 * ------------------------------------------------------------------------ */

.freunde__meldung {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0;
  color: var(--warn-icon);
  font-family: var(--font-body);
  font-size: var(--schrift-fliess);
  line-height: var(--zeilenhoehe-fliess);
}

.freunde__meldung--gut {
  color: var(--gruen-icon);
}

.freunde__meldung-zeichen {
  width: var(--icon-meldung);
  height: var(--icon-meldung);
  flex: none;
  fill: none;
  /* Farbe des Satzes, nicht eine zweite: Warnung und Bestaetigung
     unterscheiden sich an EINER Stelle (der Klasse oben). */
  stroke: currentColor;
  stroke-width: var(--strich-meldung);
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Der Entwurf setzt das Symbol einen Hauch tiefer als die erste Zeile —
     sonst haengt es ueber dem Text statt neben ihm. */
  margin-top: var(--meldung-zeichen-versatz);
}

/* --------------------------------------------------------------------------
 * DIE KOPFZEILE DES DUELL-EINSTIEGS — Artboard 22 (WI-0318, Befund F-1)
 *
 * „Title `Duell` now sits in a flex row with the pill" (HANDOFF §22,
 * Aenderungsliste `22-duel-home`). Links der Titel, rechts die beiden
 * Pillen: Bilanz (Umriss, Balkenzeichen, `9 : 5`) und `+ Freund` (warm
 * getoent). Beide stehen OBEN — die schwebende Tableiste deckt nur das
 * untere Ende des Koerpers ab (§4.3, Produktspec 4.6).
 * ------------------------------------------------------------------------ */

.duell-kopfzeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* Der Titel nimmt den Platz, die Pillen stehen rechts — wie im Entwurf
   (`justify-content: space-between` mit dem Titel als einzigem Dehnbaren). */
.duell-kopfzeile .bildschirm-titel {
  flex: 1;
  min-width: 0;
  margin: 0;
}

.duell-kopfzeile__pille {
  flex: none;
  min-height: var(--duell-kopf-pille-hoehe);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0 var(--space-3);
  border-radius: var(--radius-pille);
  font-family: var(--font-body);
  font-size: var(--duell-kopf-pille-schrift);
  cursor: pointer;
}

.duell-kopfzeile__pille .ikone {
  width: var(--icon-klein);
  height: var(--icon-klein);
  flex: none;
}

/* Die Bilanz: neutraler Umriss, Zahlen im hellen Textton, das Balkenzeichen
   im Salbeigruen des Entwurfs. Sie ist eine Auskunft mit einem Weg dahinter,
   keine Handlung — deshalb kein Terracotta. */
.duell-kopfzeile__pille--bilanz {
  background: none;
  border: var(--karte-rand) solid var(--feld-rand);
  color: var(--raum-text-hell);
  font-weight: var(--gewicht-kraeftig);
}

.duell-kopfzeile__pille--bilanz .ikone {
  color: var(--gruen-icon);
}

.duell-kopfzeile__stand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* Der Doppelpunkt steht im Entwurf leiser als die beiden Zahlen. */
.duell-kopfzeile__teiler {
  color: var(--raum-text-schwach);
}

/* HIER STAND `.duell-kopfzeile__pille--freund` — die Pille „+ Freund" der
   Kopfzeile. Entfallen mit WI-0330 (22-1): die Kopfzeile traegt nur noch die
   Bilanz-Pille. Ihre beiden Toene trug danach `.freunde__hinzufuegen`, die
   gestrichelte Zeile am Ende von „Gegner wählen" — auch sie ist entfallen
   (Rob, 13.10.2026, WI-0344): das Brett zeichnet weder die Pille noch die
   Zeile, und der Zugang bleibt als der Einladungsblock weiter unten. */

/* --------------------------------------------------------------------------
 * Laufende Partien, beide Richtungen — Artboard 22 (WI-0066)
 *
 * Der Entwurf unterscheidet die beiden Abschnitte durch das GEWICHT der
 * Flaeche, nicht durch eine zweite Bauweise: „Wartet auf dich" traegt den
 * Akzentschleier und einen Akzentrand, „Wartet auf die anderen" nur eine
 * Haarlinie. Alles andere (Knoepfe, Ueberschriften, Fliesstext) sind die
 * vorhandenen Bauteile — kein zweiter Renderer.
 * ------------------------------------------------------------------------ */

.duell-offen__block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.duell-offen__hinweis {
  color: var(--warn-icon);
}

.duell-offen {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}

.duell-offen__zeile--mich {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--duell-offen-radius);
  background: var(--duell-offen-flaeche);
  border: var(--karte-rand) solid var(--duell-offen-rand);
}

.duell-offen__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.duell-offen__zeichen {
  width: var(--duell-offen-zeichen);
  height: var(--duell-offen-zeichen);
  flex: none;
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  display: flex;
  align-items: center;
  justify-content: center;
}

.duell-offen__text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.duell-offen__titel {
  color: var(--raum-text);
  font-weight: var(--gewicht-fett);
}

.duell-offen__unter {
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-klein);
}

/* Im Entwurf traegt die EINLADUNG ihre Einsatzzeile im warmen Auskunftston,
   die laufende Partie ihre Rundenzeile im gedaempften. Der Unterschied ist
   nicht Schmuck: die Einladung nennt, worauf man sich einlaesst. */
.duell-offen__zeile--mich[data-grund='einladung'] .duell-offen__unter {
  color: var(--warn-icon);
  font-weight: var(--gewicht-fett);
}

.duell-offen__aktionen {
  display: flex;
  gap: var(--space-2);
}

/* Der Entwurf laesst die Hauptaktion die Breite nehmen und „Ablehnen" nur so
   breit werden, wie das Wort ist. */
.duell-offen__aktionen .btn {
  flex: 1;
}

.duell-offen__aktionen .btn--ghost {
  flex: none;
}

/* --------------------------------------------------------------------------
 * Artboard 37c — die eigene ANGEHALTENE Partie in der Uebersicht (WI-0284)
 *
 * Sie ist eine Zeile wie die anderen, die auf mich warten, und bringt keine
 * eigene Flaeche mit. Was sie unterscheidet, ist die laufende Frist: der
 * Entwurf setzt sie als eigenen Satz zwischen Unterzeile und Knopf, und sie
 * traegt den WARNTON, weil sie ablaeuft — nicht Terracotta, denn Terracotta
 * bleibt die Aktionsfarbe (§7 Punkt 13). Die Aktion ist der Knopf darunter.
 * ------------------------------------------------------------------------ */
.duell-offen__zeile--angehalten [data-frist] {
  color: var(--warn-icon);
  font-weight: var(--gewicht-fett);
}

/* Der Weg zurueck nimmt die ganze Breite: er ist die einzige Handlung der
   Zeile, und der Entwurf zeichnet keinen zweiten Knopf daneben. */
.duell-offen__zeile--angehalten .duell-offen__aktionen .btn {
  flex: 1;
}

.duell-offen__zeile--andere {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--duell-offen-radius-still);
  border: var(--karte-rand) solid var(--blatt-rand);
}

/* WI-0349 — DIE ZEILE BRICHT UM, STATT ABZUSCHNEIDEN (WI-0343 F-2).
   Bis hierher stand der Satz einzeilig mit Auslassungspunkten (WI-0209: neben
   „Ansehen" und „Erinnern" bleiben ihm rund 150 px, eine zweite Zeile kostet
   ~19 px unter der Falz). Der Preis war zu hoch: auf dem Telefon gibt es kein
   Hovern, das `title`-Merkmal ist dort unerreichbar, und „Mia-1791880323288
   bau…" verschluckt genau das, wofuer die Zeile da ist — wer und seit wann.
   Artboard 22 zeichnet die Wartezeile ohnehin zweizeilig (HANDOFF-PATCH P-3:
   „every wait row is two lines"). Ein Spitzname hat seit WI-0349 hoechstens
   16 Zeichen; damit passt der Satz in zwei Zeilen — gemessen in
   tests/e2e/duell-anfrage.spec.js (WI-0343-Block), nicht hier behauptet.
   `anywhere` faengt einen Namen ohne Leerzeichen ab, der allein breiter waere
   als die Spalte. */
.duell-offen__zeile--andere .duell-offen__titel {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-halb);
}

/* Eine beantwortete Anfrage bleibt als ruhiger, verbindlicher Status stehen.
   Sie ist weder wartend noch eine neue Handlung. */
.duell-offen__zeile--andere[data-grund='abgelehnt'] .duell-offen__titel {
  color: var(--cs-text-2);
  font-weight: 800;
}

/* WI-0209 — DIE BEIDEN STILLEN BEDIENUNGEN (HANDOFF §22.3, Artboard 22).
   „`Ansehen` beside `Erinnern`, both 44px hit areas in `accent-300`." Die
   Zeile selbst bleibt still: sie behaelt ihren Haarstrich aus --blatt-rand und
   bekommt KEINEN Akzentrand wie die Zeilen unter „Wartet auf dich".
   Hineinschauen ist nicht dasselbe wie aufgefordert werden.

   DIE TREFFERFLAECHE LIEGT UEBER DER ZEILE, NICHT IN IHR. Die 44 px sind ein
   Mass fuer den DAUMEN, kein Mass fuer die Zeile: der Entwurf zeichnet die
   ruhige Zeile mit 13 px Innenabstand um eine 18 px hohe Uhr, und genau so
   hoch ist sie in der App seit WI-0066. Haengt man die 44 px als `min-height`
   ohne Ausgleich hinein, streckt sich die Zeile um 26 px, 22 und 22b rollen
   26 px weiter unter die Falz (242 -> 268) — und die Ratsche wertet das zu
   Recht als „vom Entwurf abgerueckt". Deshalb zieht der Block seine eigene
   Hoehe mit einem negativen Aussenabstand wieder heraus: die Knoepfe sind
   44 px hoch und treffbar, tragen zur Zeilenhoehe aber 0 px bei. Gemessen
   statt geglaubt — `tests/duell-ui.test.js` nagelt beide Haelften fest. */
.duell-offen__still-aktionen {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex: none;
  margin-block: calc(var(--btn-hoehe-treffer) / -2);
}

.duell-offen__still-aktion {
  min-height: var(--btn-hoehe-treffer);
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-2);
  background: none;
  border: 0;
  color: var(--color-accent-300);
  font-family: var(--font-body);
  font-size: var(--schrift-klein);
  font-weight: var(--gewicht-kraeftig);
  cursor: pointer;
}

.duell-offen__uhr {
  width: var(--duell-offen-uhr);
  height: var(--duell-offen-uhr);
  flex: none;
  color: var(--raum-text-schwach);
}

/* Ein langer Deckbau ist keine festgestellte Trennung: Die Zeile bleibt
   dieselbe ruhige Wartezeile, zeigt die Unsicherheit aber sichtbar an. */
.duell-offen__zeile--andere[data-vermutlich-inaktiv='true'] .duell-offen__titel,
.duell-offen__zeile--andere[data-vermutlich-inaktiv='true'] .duell-offen__uhr {
  color: var(--warn-icon);
}

/* --------------------------------------------------------------------------
 * Die EROBERUNG wartet auf eine Zustimmung — Artboards 22c/22d/22e (WI-0335)
 *
 * Zwei Zeilen wie die Einladung, die auf mich wartet (Abzeichen, Titel,
 * Unterzeile): HANDOFF-PATCH §24.8 nennt es ausdruecklich „derselbe
 * Wartezeilen-Bauplan", nur fuer die EROBERUNG statt den Deckbau. Die
 * gewoehnliche stille Zeile (`--andere` ohne `--einsatz`) bleibt unveraendert
 * einzeilig — sie ist nicht Teil dieses Items.
 * ------------------------------------------------------------------------ */

/* Der Anker um den Einladungsblock (22f) nimmt am Flex-Fluss von Artboard 22
   nicht teil — er fuegt nur eine Greifstelle hinzu, keinen Abstand. */
.duell-einladung-anker {
  display: contents;
}

.duell-offen__zeile--einsatz {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: stretch;
  padding: var(--space-3);
  border-radius: var(--duell-offen-radius-still);
  border: var(--karte-rand) solid var(--blatt-rand);
}

/* Ueberfaellig traegt denselben Akzentrand wie eine Partie, die wirklich auf
   mich wartet (--duell-offen-rand) — eine WARNUNG, kein zweiter Farbwert. */
.duell-offen__zeile--einsatz[data-vermutlich-inaktiv='true'] {
  border-color: var(--duell-offen-rand-ueberfaellig);
}

.duell-offen__abzeichen {
  width: var(--duell-offen-zeichen);
  height: var(--duell-offen-zeichen);
  flex: none;
  border-radius: var(--radius-pille);
  display: flex;
  align-items: center;
  justify-content: center;
}

.duell-offen__abzeichen .duell-offen__uhr,
.duell-offen__abzeichen .duell-offen__verbotszeichen {
  width: var(--duell-offen-uhr);
  height: var(--duell-offen-uhr);
  color: currentColor;
}

/* Lila fuer die vorgeschlagene Eroberung — derselbe Ton wie der EROBERT-Chip
   und der Topf (`--cs-r-epic`, HANDOFF §11), nicht ein neuer Farbwert. */
.duell-offen__abzeichen--eroberung {
  background: color-mix(in srgb, var(--cs-r-epic) 12%, transparent);
  color: var(--cs-r-epic);
}

/* Amber jenseits der Schwelle — derselbe Ton wie jede andere Warnung
   (`--cs-warn`), nicht die Aktionsfarbe. */
.duell-offen__abzeichen--ueberfaellig {
  background: var(--warn-flaeche);
  color: var(--warn-icon);
}

/* Die naechstgelegene Textstufe (`--cs-text-3`) fuer eine Partie, die es
   nicht mehr gibt — kein Terracotta (Aktion) und kein Warnton (sie ist
   beantwortet, nicht gefaehrdet). */
.duell-offen__abzeichen--abgelehnt {
  background: var(--feld-flaeche);
  color: var(--cs-text-3);
}

.duell-offen__tag {
  color: var(--warn-icon);
  font-weight: var(--gewicht-fett);
}

/* Die abgelehnte Eroberung ist eine Zeile unter „Wartet auf dich" wie jede
   andere — dieselbe Flaeche und derselbe Akzentrand (`.duell-offen__zeile--mich`
   darueber), nur mit dem Schliessen-Knopf am Kopf. */
.duell-offen__zeile--eroberung-abgelehnt .duell-offen__kopf {
  align-items: flex-start;
}

/* --------------------------------------------------------------------------
 * Anfrage entfernen, Spieler blockieren — Artboards 22 und 22b (WI-0182)
 *
 * DER MISTKUEBEL (HANDOFF §5.5d, Zeile `22-duel-home` der Aenderungsliste):
 * 34 px, rechts in der Kopfzeile der Anfragezeile, auf --feld-flaeche mit
 * einer Haarlinie darum. Dieselbe Scheibe wie der Namenskreis daneben, nur
 * neutral gefaerbt — er ist ein Knopf, keine Person. Er entfernt nichts
 * direkt; er oeffnet 22b.
 * ------------------------------------------------------------------------ */

.duell-offen__mistkuebel,
.freund-zeile__still {
  width: var(--duell-offen-zeichen);
  height: var(--duell-offen-zeichen);
  flex: none;
  padding: 0;
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
  border: 1px solid var(--blatt-rand);
  color: var(--raum-text-gedaempft);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.duell-offen__mistkuebel .ikone,
.freund-zeile__still .ikone {
  width: var(--icon-klein);
  height: var(--icon-klein);
}

/* DAS BLATT 22b. Es liegt in derselben `blattlage` wie die Loeschabfrage und
   ist genauso eingerueckt — der Entwurf zeichnet beide mit demselben Abstand
   zum Rand und derselben unteren Verankerung.

   KEINE FESTE HOEHE: der Entwurf setzt `left/right/bottom` und laesst das
   Blatt so hoch werden, wie sein Inhalt ist. Damit stehen die Hauptaktionen
   auf 393 x 793 im unteren Drittel, und kein Zustand traegt Leerraum, den er
   nicht braucht (Designspec 10.3 Punkt 1). */
.anfrageblatt {
  position: relative;
  margin: 0 var(--space-4) var(--space-6);
  padding: var(--space-6);
  gap: var(--space-3);
}

.anfrageblatt__titel {
  margin: 0;
}

/* Die leichte Entscheidung zuerst: `Behalten` als Hauptaktion, `Nur
   entfernen` als ruhiger Umriss darunter. */
.anfrageblatt__leicht {
  gap: var(--space-3);
}

/* UND ERST DARUNTER DIE SCHWERE (HANDOFF §5.5d): eigener Trennstrich, eigene
   Versalzeile, die Folgen NEBEN der Handlung. Blockieren bekommt bewusst
   keine gleichwertige Flaeche weiter oben. */
.anfrageblatt__schwer {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  border-top: 1px solid var(--blatt-rand);
  padding-top: var(--space-4);
}

.anfrageblatt__folgen {
  margin: 0;
  line-height: var(--zeilenhoehe-fliess);
}

.anfrageblatt__rueckweg {
  margin: 0;
  line-height: var(--zeilenhoehe-fliess);
}

.anfrageblatt .ikone--block {
  width: var(--icon-klein);
  height: var(--icon-klein);
  flex: none;
}

.freunde__liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: 0;
}

/* WI-0318 (Befund F-2) — EINE ZEILE, EINE AKTIONSPILLE.
   Der Entwurf zeichnet die Gegnerzeile EINZEILIG: Kreis, Name ueber
   Kartenzahl, rechts eine Pille. Bis WI-0318 stand hier eine Spalte mit
   einer zweiten Reihe aus vier gleich schweren Knoepfen darunter. */
.freund-zeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
  border: var(--karte-rand) solid var(--feld-rand);
}

/* Artboard 22, Abschnitt „Gegner wählen": Kreis, dann Name ueber Kartenzahl.
   Seit WI-0318 ist dieser Block der Weg in die Sammlung (Artboard 40) und
   damit ein Knopf — er traegt deshalb keine Knopfflaeche, nur die
   Trefferflaeche der ganzen Zeile. */
.freund-zeile__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
  min-height: var(--btn-hoehe-treffer);
  margin-block: calc(var(--btn-hoehe-treffer) / -2);
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
  font-family: inherit;
  color: inherit;
  cursor: pointer;
}

.freund-zeile__text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.freund-zeile__name {
  font-family: var(--font-heading);
  font-weight: var(--gewicht-heading);
  color: var(--raum-text);
}

/* Die EINE Aktionspille (Artboard 22: `min-height: 40px; padding: 0 16px`,
   gefuellt in der Handlungsfarbe). */
.freund-zeile__pille {
  flex: none;
  min-height: var(--btn-hoehe-ghost);
  padding: 0 var(--space-4);
  font-size: var(--schrift-hinweis);
}

/* Die TUER zu Entfernen und Blockieren (HANDOFF §5.5d, WI-0330): dieselbe
   stille 34-px-Scheibe, die der Entwurf eine Handbreit darueber an der
   Anfragezeile zeichnet — und sie tut dort dasselbe, sie oeffnet das Blatt.
   Bis WI-0330 standen hier ZWEI davon, und die zweite blockierte sofort. */
.freund-zeile__still {
  flex: none;
}

/* --------------------------------------------------------------------------
 * HIER STAND DIE GESTRICHELTE ZEILE „Freund hinzufügen" (WI-0330, 22-1)
 *
 * Artboard 22, letzte Zeile von „Gegner wählen": gestrichelter Rahmen,
 * gestrichelter Kreis mit Pluszeichen, zwei Textzeilen. Entfernt auf Robs
 * Entscheidung vom 13.10.2026 (WI-0344, Befund F-1 aus WI-0343) — das
 * freigegebene Brett (`design/Carspotter App.dc.html`, `22-duel-home`,
 * Zeilen 3412-3491) zeichnet diese Zwischenzeile nicht: nach den
 * Freundeszeilen folgt direkt „Dein Code". Der Zugang bleibt erhalten, als
 * der Einladungsblock weiter unten (`22f-duel-home-invite`), der diese
 * Klassen (`.freunde__hinzufuegen*`) nicht brauchte und nicht beruehrt wird.
 * ------------------------------------------------------------------------ */

/* --------------------------------------------------------------------------
 * DAS REAKTIONSBLATT — die Familie `16r-*` (WI-0181, HANDOFF §5.5c)
 *
 * ELF ZUSTAENDE, EIN BAUTEIL. Was sie unterscheidet, steht in `data-stand`
 * und in den Zeilen; der Aufbau ist bei allen derselbe. Die drei Hoehen sind
 * gezeichnet und deshalb fest — sie sind der Grund, warum beim Scrollen
 * nichts unter den Knopf rutscht.
 * ------------------------------------------------------------------------ */

/* DIE GEOMETRIE GEHOERT DEM BLATT UEBER DER KARTE, nicht der Klasse
   `.reaktionen`. Artboard 40 traegt in seiner Sammlung ein eigenes,
   gewoehnliches Blatt mit derselben Klasse — bekaeme es diese feste Hoehe,
   spannte es sich ueber den halben Bildschirm und schoebe seinen Inhalt unter
   die Falz. */
.reaktionen--overlay,
.reaktionen--auswahl {
  box-sizing: border-box;
  height: var(--reaktionen-hoehe-liste);
  padding: var(--reaktionen-polster-oben) var(--reaktionen-polster-seite)
    var(--reaktionen-polster-unten);
  gap: 0;
  border-bottom: 0;
  border-left: 0;
  border-right: 0;
  border-radius: var(--reaktionen-radius) var(--reaktionen-radius) 0 0;
  box-shadow: var(--reaktionen-schatten);
  overflow: hidden;
}

/* Leer und Fehler sind kuerzer — der Entwurf zeichnet sie mit 310 px. Ein
   Blatt in Listenhoehe mit zwei Zeilen darin waere eine Flaeche, die etwas
   verspricht, was nicht da ist. */
.reaktionen--overlay[data-stand='leer'],
.reaktionen--overlay[data-stand='fehler'] {
  height: var(--reaktionen-hoehe-kurz);
  justify-content: center;
}

/* Waehrend das Auswahl-Overlay oben liegt, tritt die Liste dahinter auf
   50 % zurueck — sie bleibt sichtbar, ist aber nicht mehr das, was gerade
   bedient wird. */
.reaktionen--gedimmt {
  opacity: 0.5;
  pointer-events: none;
}

/* Der Griff IST der Rueckweg: 36 x 4 px sichtbarer Strich in einer 44 px
   hohen Trefferflaeche. Ein Blatt ohne Ausgang waere eine Sackgasse
   (Designspec 10.3 Punkt 2), ein zweiter Knopf daneben stuende nicht im
   Entwurf. */
.blatt__griff {
  flex: none;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--reaktionen-griff-treffer);
  height: var(--reaktionen-griff-treffer);
  margin: calc(-1 * var(--reaktionen-griff-versatz)) 0 var(--reaktionen-griff-abstand);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.blatt__griff-strich {
  display: block;
  width: var(--reaktionen-griff-breite);
  height: var(--reaktionen-griff-hoehe);
  border-radius: var(--radius-pille);
  background: var(--reaktionen-griff-farbe);
}

.reaktionen__kopf {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.reaktionen__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--reaktionen-titel);
  line-height: 1.1;
}

.reaktionen__zahl {
  font-size: var(--reaktion-caption);
  color: var(--raum-text-schwach);
}

/* Die Liste des Blattes von Artboard 40 — kompakte Zeilen, hoechstens ein
   Drittel der Hoehe. Sie stand vor WI-0181 genau so da und bleibt so. */
.reaktionen__liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
  max-height: 30vh;
  overflow-y: auto;
}

/* IM BLATT UEBER DER KARTE rollt sie und blendet an beiden Kanten aus — oben
   18 px, unten 14 px. Eine halb sichtbare Zeile liest sich dann als
   angeschnitten und nicht als kaputt (`16r-reactions-scrolled`). */
.reaktionen--overlay .reaktionen__liste {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  gap: var(--space-4);
  mask-image: var(--reaktionen-maske);
  -webkit-mask-image: var(--reaktionen-maske);
}

.reaktion {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

/* Eine Antwort liegt EINE Ebene tief, hinter einer Haarlinie. Tiefer geht es
   nicht: auf eine Antwort wird nicht geantwortet (Spec 4.7). */
.reaktion--antwort {
  margin-left: var(--reaktion-antwort-einzug);
  padding-left: var(--space-3);
  border-left: var(--reaktion-antwort-linie);
}

/* Name, Pille und Aktion stehen UNTEREINANDER — der Entwurf setzt
   `Antworten` unter die Pille, nicht daneben. */
.reaktion__koerper {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.reaktion__kopf {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

/* DER LANGE ABSENDERNAME (`16r-reactions-longname`). Er nimmt die Restbreite
   und wird am ENDE beschnitten — nie zweizeilig, sonst waechst die Zeile und
   die Liste rutscht. Der Satz DARUNTER bleibt ganz; er steht in einer
   eigenen Zeile und ist von dieser Regel nicht betroffen. */
.reaktion__name {
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--reaktion-name);
  font-weight: var(--gewicht-fett);
  color: var(--raum-text);
}

.reaktion--antwort .reaktion__name {
  font-size: var(--reaktion-caption);
  color: var(--raum-text-hell);
}

.reaktion__zeit {
  flex: none;
  font-size: var(--reaktion-zeit);
  color: var(--raum-text-schwach);
}

/* Die Pille ist STATISCH — sie ist keine Aktion, sie ist das Gesagte. */
.reaktion__pille {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--reaktion-pille-hoehe);
  padding: 0 var(--space-3);
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--reaktion-pille-rand);
  background: var(--reaktion-pille-flaeche);
  font-size: var(--reaktion-satz);
  font-weight: var(--gewicht-fett);
  color: var(--reaktion-pille-text);
}

/* Die EIGENE Reaktion traegt Terrakotta statt Salbei — und darunter steht
   `Zurücknehmen`, nie `Bearbeiten`. */
.reaktion__pille--eigen {
  border-color: var(--reaktion-eigen-rand);
  background: var(--reaktion-eigen-flaeche);
  color: var(--reaktion-eigen-text);
}

/* HOECHSTENS EINES, und es steht IN der Pille hinter dem Satz. */
.reaktion__zeichen {
  font-size: var(--reaktion-emoji);
  line-height: 1;
}

/* Die Kompaktzeile im Blatt von Artboard 40 — unveraendert seit WI-0040. */
.reaktion-zeile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--schrift-klein);
  color: var(--raum-fliess);
}

.reaktion-zeile__zeichen {
  font-size: var(--schrift-h4);
}

/* `Antworten` / `Zurücknehmen` — 44 px Trefferflaeche, damit ein Daumen sie
   trifft, ohne dass die Zeile dadurch hoeher wird.

   KEINE Knopfflaeche: der Entwurf zeichnet hier reine Schrift in Akzent-300.
   Deshalb traegt das Element auch nicht die Basisklasse `btn` — sie brachte
   Flaeche und Schein mit, und die Zeile las sich dann wie drei Knoepfe
   uebereinander. */
.reaktion__aktion {
  display: inline-flex;
  align-items: center;
  min-height: var(--btn-hoehe-treffer);
  margin-top: var(--reaktion-aktion-versatz);
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--reaktion-caption);
  font-weight: var(--gewicht-fett);
  color: var(--color-accent-300);
  cursor: pointer;
}

/* AUSGEBLENDET UND BLOCKIERT. Die Zeile behaelt ihren Platz — nichts ist
   geloescht —, aber sie nennt weder Absender noch Satz. Der leere Kreis ist
   gestrichelt, damit sichtbar bleibt, dass dort jemand steht. */
.reaktion__leerkreis {
  flex: none;
  width: var(--avatar-reaktion);
  height: var(--avatar-reaktion);
  border-radius: 50%;
  border: var(--karte-rand) dashed var(--feld-rand);
}

.reaktion__hinweis {
  margin: 0;
  font-size: var(--reaktion-satz);
  color: var(--raum-text-gedaempft);
}

/* Drei Skelettzeilen, 64 px, OHNE Schimmer (`16r-laden`). */
.reaktion--skelett {
  height: var(--reaktion-skelett-hoehe);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
}

.reaktionen__fehler {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
}

.reaktionen__nochmal {
  align-self: stretch;
}

/* `Sag was Nettes` steht FEST am unteren Rand des Blatts und rollt nicht mit.
   Es gibt keine dauerhafte Satzleiste daneben — der Satz wird im Overlay
   gewaehlt. */
.reaktionen__sagen {
  flex: none;
  margin-top: var(--space-4);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.reaktionen__sagen .ikone--sprechblase {
  width: var(--icon-klein);
  height: var(--icon-klein);
}

/* STUMPF, solange die Liste nicht steht — abschicken, bevor sie bekannt ist,
   kann eine Reaktion doppeln (Flow-Paket 02.09., `16r-laden`). */
.btn--stumpf,
.btn--stumpf[disabled] {
  background: var(--reaktion-stumpf-flaeche);
  color: var(--reaktion-stumpf-text);
  opacity: 1;
  cursor: default;
}

/* --- Das Auswahl-Overlay (`16r-reactions-picking`) --- */

.reaktionen__lage {
  position: relative;
}

.reaktionen--auswahl {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 3;
  height: var(--reaktionen-hoehe-auswahl);
}

/* Der Koerper rollt, `Abschicken` steht fest darunter. Ohne das faellt die
   Hauptaktion bei einer laengeren Zurechnungszeile (Englisch) unter die
   Blattkante — und ein Knopf, den man nicht sieht, ist keiner. */
.reaktionen__wahlkoerper {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  /* Eng gesetzt, damit die Zurechnungszeile („Geht als du raus …") in den
     466 px UEBER dem Knopf steht und nicht unter die Kante rutscht: der
     Entwurf nennt sie ausdruecklich vor dem Abschicken, nicht danach. */
  gap: var(--space-2);
}

.reaktionen__senden {
  flex: none;
  margin-top: var(--space-3);
}

.reaktionen--auswahl .fliess {
  margin: 0;
}

/* Drei Saetze als volle 48-px-Zeilen. KEIN Eingabefeld daneben und keines
   darunter — es gibt in dieser Strecke keines. */
.reaktionen__saetze {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.reaktionen__satz {
  min-height: var(--btn-hoehe);
  width: 100%;
  padding: 0 var(--space-4);
  text-align: left;
  border-radius: var(--radius-md);
  border: 1px solid var(--feld-rand);
  background: var(--feld-flaeche);
  color: var(--raum-text);
  font-size: var(--reaktion-satz);
  font-weight: var(--gewicht-fett);
  cursor: pointer;
}

/* Sechs runde Zeichenknoepfe, EINFACHAUSWAHL. Keine Emoji-Tastatur, keine
   Suche, keine Zuletzt-benutzt-Liste. */
.reaktionen__zeichen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.reaktionen__chip {
  width: var(--btn-hoehe);
  height: var(--btn-hoehe);
  border-radius: 50%;
  border: 1px solid var(--feld-rand);
  background: var(--feld-flaeche);
  font-size: var(--reaktion-emoji);
  line-height: 1;
  cursor: pointer;
}

/* Der gewaehlte Satz — im Overlay von `16r-reactions-picking` als Zeile, auf
   Artboard 40 als Chip. Dieselbe Auszeichnung: 2 px Akzentrand auf der
   getoenten Flaeche. */
.chip--gewaehlt,
.reaktionen__satz--gewaehlt,
.reaktionen__chip--gewaehlt {
  border: var(--btn-wahl-rand) solid var(--color-accent);
  background: var(--vorschlag-wahl-flaeche);
}

/* Die Zurechnung steht VOR dem Abschicken, nicht danach. */
.reaktionen__zurechnung {
  margin: 0;
}

/* --------------------------------------------------------------------------
 * Deckbau (Produktspec 7.2/7.3)
 * ------------------------------------------------------------------------ */

/* Die Zaehlerzeile (Artboard 28): links „6 von 8 gewählt", rechts daneben die
   verfuegbare Anzahl. Seit WI-0096 steht die Pille „Automatisch füllen" in
   der ZEILE DARUNTER, rechtsbuendig — genau so zeichnet der Entwurf sie, und
   zu dritt in einer Zeile drueckte sie die beiden Angaben zusammen. */
.deckbau__zaehler {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

/* WI-0387 (§5.5d2): beide Zahlen in EINER Zeile links, die Ringe rechts. */
.deckbau__zahlen {
  flex: 1;
  min-width: 0;
}

/* --------------------------------------------------------------------------
 * DAS STEHENDE KOPFBAND (Artboards 19s und 28s, WI-0424)
 *
 * Das Fenster rollt, nicht ein innerer Kasten — deshalb `sticky` und kein
 * eigener Scrollbereich: Nachladen, Rueckkehr an die Stelle und „Nach oben"
 * haengen alle an der Fensterlage.
 *
 * Das Band steht UNTER dem oberen Systemrand (`top: --sicher-oben`, WI-0417).
 * Der Streifen darueber — Statusleiste, Dynamic Island — bekommt dieselbe
 * Flaeche ueber `::before`, sobald das Band steht; sonst rollten die Kacheln
 * sichtbar hinter der Uhrzeit durch. Seitlich greift das Band ueber das
 * Polster der Buehne, damit die Flaeche von Kante zu Kante reicht.
 *
 * EBENE 2 UND NICHT HOEHER: dieselbe wie `.blattlage`. Ueber den Kacheln
 * (deren Marken liegen auf 1), aber nie ueber einem Blatt — bei gleicher
 * Ebene entscheidet die Reihenfolge im Baum, und das Filterblatt steht am
 * Ende der Garage. Mit 3 lag das Band ueber dem offenen Filterblatt und
 * fing den Tipp auf „Alle zurücksetzen" ab (gemessen im Container).
 * ------------------------------------------------------------------------ */
.kopfband {
  position: sticky;
  top: var(--sicher-oben);
  z-index: 2;
  margin-inline: calc(var(--buehne-seite) * -1);
  padding-inline: var(--buehne-seite);
  background: var(--kopfband-flaeche);
}

.kopfband::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: var(--sicher-oben);
  background: var(--kopfband-flaeche);
  visibility: hidden;
}

.kopfband[data-gerollt='ja'] {
  box-shadow: var(--kopfband-schatten);
}

.kopfband[data-gerollt='ja']::before {
  visibility: visible;
}

/* In der Garage beginnt das Band an der Oberkante der Buehne: es nimmt ihr
   Polster in sich auf, damit der Titel ruhend dort steht, wo er stand, und
   stehend denselben Abstand zum Systemrand behaelt. */
.kopfband--garage,
.kopfband--freund {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: calc(var(--buehne-oben) * -1);
  padding-top: var(--buehne-oben);
  padding-bottom: var(--space-1);
}

/* Im Deckbau steht das Band mitten im Bildschirm (Titel, Gegner und Pillen
   rollen weg). Oben ein kleines Polster, damit die Zahlen stehend nicht an
   der Kante kleben. */
.kopfband--deckbau {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}

/* Die Knoepfe von 28s stehen unten fest. Das Band greift ueber das untere
   Polster der Buehne und den Home-Indikator (WI-0417), damit der Verlauf
   bis an die Kante reicht und die Knoepfe darueber stehen. */
.deckbau__aktionen {
  position: sticky;
  bottom: 0;
  /* Ebene 2 wie das Kopfband: nie ueber einem Blatt. */
  z-index: 2;
  margin-inline: calc(var(--buehne-seite) * -1);
  margin-bottom: calc((var(--space-6) + var(--sicher-unten)) * -1);
  padding: var(--space-8) var(--buehne-seite) calc(var(--space-6) + var(--sicher-unten));
  background: var(--deckbau-fuss-verlauf);
}

/* Die Pillenzeile: links `Alle Gruppen ▾`, rechts `Automatisch füllen`. */
.deckbau__fuellzeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.deckbau__gruppenliste {
  margin-top: var(--space-2);
}

/* Das Salbeiband (flows/filters.html, `28-filter-gewaehlte-versteckt`):
   16 px Radius, Flaeche und Rand aus dem guten Ton, 12,5 px Schrift. */
.deckbau__band {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-top: var(--space-2);
  padding: 10px 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--gruen-rand);
  background: var(--gruen-flaeche);
  color: var(--gruen-text);
}

.deckbau__band p {
  margin: 0;
  font-size: 12.5px;
  line-height: var(--zeilenhoehe-fliess);
}

/* Die Pille selbst. Kein Terracotta: sie nimmt dem Spieler die Tipparbeit ab,
   sie ist nicht die Hauptaktion des Bildschirms — die bleibt „Deck
   bestätigen" (Designspec Kap. 9: Terracotta ist den Aktionen vorbehalten,
   und hier steht eine Hilfe daneben, kein zweiter Hauptweg). */
.btn--fuellen {
  min-height: var(--fuellen-hoehe);
  padding: 0 var(--space-3);
  border: var(--fuellen-strich) solid var(--feld-rand);
  background: transparent;
  color: var(--ghost-text);
  font-size: var(--schrift-klein);
  box-shadow: none;
  white-space: nowrap;
}

.deckbau__wartet {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
  text-align: center;
}

/* Die drei Auskunftspillen unter der Unterzeile (Artboard 28): Serie, „je 8
   Karten", „16 im Spiel". Sie sind KEINE Wahl — deshalb ohne Zeigefinger und
   ohne den gedrueckten Zustand der Chips. */
.chips--auskunft .chip {
  cursor: default;
}

.chip--still {
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-fliess);
}

/* --------------------------------------------------------------------------
 * Duell aufsetzen — Artboard 26 (WI-0096)
 *
 * Drei Entscheidungen, je ein Satz. Die beiden ersten stehen als Wahlkarten
 * untereinander (Titel plus Erklaerung), die Deckgroesse als Reihe aus vier
 * gleich breiten Pillen. Was die gewaehlte Bezugsart nicht traegt, steht
 * GESPERRT da — nicht weggelassen: eine kuerzere Reihe waere keine Auskunft.
 * ------------------------------------------------------------------------ */

.duell-aufsetzen {
  flex: 1;
}

/* --------------------------------------------------------------------------
 * DIE KOPFZEILE MIT DEM 34-PX-KREUZ (Artboard 26, HANDOFF Zeile 865; WI-0317)
 *
 * „Close row: the screen heading `Gegen Jonas` carries a 34px round X to its
 * right (added in v2 — the screen had no exit)." Die Zeile ist dieselbe Form
 * wie `.garage__kopf`: Titel links, ein Steuerelement rechts, beides in einer
 * Zeile. Die Masse des Kreuzes kommen aus den `--kreuz-*`-Tokens, die das
 * Kreuz auf 14/15/16 schon traegt — kein zweiter Satz Werte, und kein Bauteil
 * ueberschrieben.
 * ------------------------------------------------------------------------ */
.duell-aufsetzen__kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

/* Der Titel darf schrumpfen, das Kreuz nicht: ein langer Spitzname kuerzt den
   Namen, er darf nicht das Trefferziel von der Flaeche schieben. */
.duell-aufsetzen__kopf .bildschirm-titel {
  flex: 1;
  min-width: 0;
}

/* Die Trefferflaeche ist die Ghost-Knopfhoehe, die SCHEIBE sind die 34 px des
   Entwurfs — genau die Aufteilung von `.kartenseite__schliessen` (Designspec
   10.3 Punkt 3: Trefferziel als Mass, nicht als Optik). */
.duell-aufsetzen__schliessen {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--btn-hoehe-ghost);
  height: var(--btn-hoehe-ghost);
  padding: calc((var(--btn-hoehe-ghost) - var(--kreuz-scheibe)) / 2);
  border: 0;
  background: transparent;
  color: var(--ghost-text);
  cursor: pointer;
}

.duell-aufsetzen__schliessen > * {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: var(--space-2);
  border: var(--kreuz-rand);
  border-radius: var(--radius-pille);
  background: var(--kreuz-flaeche);
}

/* Der Grund der gesperrten `Ablage`-Pille steht im SELBEN Satz wie die aktive
   Wahl, nur im gedaempften Ton — §5.5e erlaubt genau dieser einen Zeile zwei
   Zeilen Text („each sentence must stay one line except the play-style one").
   Eine eigene Zeile daneben waere eine sechste Entscheidung auf einem
   Bildschirm, der nicht rollen darf. */
.spielart__grund {
  color: var(--cs-text-off);
}

/* DIE WAHLKARTE IST MIT WI-0180 ENTFALLEN. Bezugsart und Einsatz standen als
   gestapelte Kaesten mit je zwei Zeilen; HANDOFF §5.5e zeichnet sie als
   46-px-Zweiwahl-Zeile mit einem Satz darunter — siehe `.chips--paar` weiter
   oben. `--wahlkarte-radius` und `--wahlkarte-rand-aktiv` bleiben: sie tragen
   jetzt die Gruppenzeilen von 26b und die gewaehlte Pille. */

/* Die Reihe der drei Deckgroessen: gleich breit, damit die Reihe eine Reihe
   bleibt, auch wenn eine Zahl zweistellig ist. */
.groessen {
  display: flex;
  gap: var(--space-2);
}

/* --------------------------------------------------------------------------
 * Deckgroesse und Runden NEBENEINANDER (HANDOFF §5.5e, Stand 01.10.2026;
 * WI-0284)
 *
 * „`Deckgröße` + `Runden` side by side in one row … two groups of three
 * pills, `4 · 8 · 12` und `50 · 100 · ohne`, 6px gap inside, 14px between
 * groups." Die beiden Luecken sind genau die Tokens, die diese Werte tragen:
 * `--space-2` innen (die Pillenluecke von `.groessen`), `--space-4`
 * zwischen den Gruppen.
 *
 * WARUM NEBENEINANDER UND NICHT UNTEREINANDER: das Aufsetzen traegt sechs
 * Entscheidungen auf 757 px und darf NICHT rollen (§5.5e, Designspec 10.3
 * Punkt 1). Gestapelt stuende der Hauptknopf unter der Falz.
 * ------------------------------------------------------------------------ */
.wahlpaar {
  display: flex;
  gap: var(--space-4);
}

/* Beide Gruppen gleich breit: drei Pillen links, drei rechts. `min-width: 0`
   laesst die Pillen schrumpfen, statt die Zeile zu sprengen. */
.wahlpaar__gruppe {
  flex: 1;
  min-width: 0;
}

.groesse {
  flex: 1;
  justify-content: center;
  min-height: var(--groesse-hoehe);
  font-size: var(--schrift-fliess);
}

.groesse[disabled] {
  color: var(--cs-text-off);
  border-color: var(--cs-line-1);
  background: transparent;
  cursor: default;
}

.chip[disabled] {
  color: var(--cs-text-off);
  border-color: var(--cs-line-1);
  cursor: default;
}

/* --------------------------------------------------------------------------
 * Die Fahrzeuggruppe — Artboards 26 („Fahrzeuggruppe") und 26b (WI-0180)
 *
 * Der Entwurf zeichnet die Zeile des Aufsetzens als ZWEIWAHL aus zwei gleich
 * breiten Pillen — genau wie Bezugsart und Einsatz darueber — und darunter
 * EINEN Satz, der die aktive Wahl beschreibt. Steht eine Gruppe, traegt der
 * Satz rechts den Weg `ändern` auf Artboard 26b.
 * ------------------------------------------------------------------------ */

/* Zwei Pillen, die sich die Zeile teilen (Artboard 26: `flex:1` auf beiden).
   Ohne das faellt eine Chipreihe auf ihre Textbreite zurueck und die Zeile
   sieht anders aus als die vier daneben. */
/* Die NICHT gewaehlte Pille traegt den Fliesston, nicht den Auskunftston der
   uebrigen Chipreihen — Artboard 26 zeichnet sie in #cfc3ab, und genau dieser
   Ton fehlte der Farbleiter dieses Bildschirms sonst. */
.chips--paar .chip {
  flex: 1;
  justify-content: center;
  min-height: var(--groesse-hoehe);
  color: var(--raum-fliess);
  font-size: var(--schrift-hinweis);
  text-align: center;
}

/* Die gewaehlte Pille traegt den 2-px-Akzentrand und den Akzentschleier, mit
   dem der Entwurf ueberall die Auswahl markiert — nicht die schmale
   Akzentschrift der Chipreihen (Artboard 26). */
.chips--paar .chip[aria-pressed='true'] {
  border-width: var(--wahlkarte-rand-aktiv);
  background: var(--cs-accent-tint);
  color: var(--raum-text);
  font-weight: var(--gewicht-fett);
}

/* Die Eroberung ist eine AUSKUNFT ueber den Einsatz, keine Aktion — deshalb
   der Einsatzton statt Terracotta (§7 Punkt 13, wie an der Wahlkarte). */
.chips--paar .chip[data-art='eroberung'][aria-pressed='true'] {
  border-color: var(--cs-r-epic);
  background: var(--erobert-flaeche);
  color: var(--erobert-text);
}

/* Der Satz mit dem Weg daneben (Artboard 26: `display:flex`, 10 px Luecke). */
.zeile-mit-aktion {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.zeile-mit-aktion__text {
  flex: 1;
  min-width: 0;
}

/* `ändern` ist ein Textweg wie der auf 11b/11c — dieselbe Behandlung, damit
   nicht zwei Textwege verschieden aussehen. Die Trefferflaeche steht als
   `min-height` da und nicht als Hoehe (Designspec 10.3 Punkt 3). */
.zeile-mit-aktion__weg {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--btn-hoehe-ghost);
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--color-accent-300);
  font-family: var(--font-body);
  font-size: var(--schrift-hinweis);
  font-weight: var(--gewicht-kraeftig);
  cursor: pointer;
}

/* --- Artboard 26b: die Liste der Gruppen --- */

.duell-gruppenwahl {
  flex: 1;
}

.gruppenliste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.gruppenzeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--gruppenzeile-hoehe);
  padding: 0 var(--gruppenzeile-polster);
  border-radius: var(--wahlkarte-radius);
  border: var(--karte-rand) solid var(--feld-rand);
  background: transparent;
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
}

/* Der Gruppenname steht in der Ueberschriftenschrift — er ist das, was
   gelesen wird, und der Entwurf setzt ihn deshalb auf 19 px Rokkitt. */
.gruppenzeile__name {
  flex: 1;
  min-width: 0;
  color: var(--raum-text);
  font-family: var(--font-heading);
  font-size: var(--gruppenzeile-name);
  line-height: var(--zeilenhoehe-heading);
}

/* Beide Zahlen — oder, bei einer gesperrten Zeile, der Grund MIT NAMEN. */
.gruppenzeile__zahlen {
  flex: none;
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-klein);
}

.gruppenzeile__haken {
  flex: none;
  width: var(--gruppenzeile-haken);
  height: var(--gruppenzeile-haken);
  color: var(--color-accent-400);
}

/* Gewaehlt: derselbe Akzentrand und Akzentschleier wie an jeder anderen
   Auswahl der App (Artboards 11, 26, 28a). */
.gruppenzeile[aria-pressed='true'] {
  border-width: var(--wahlkarte-rand-aktiv);
  border-color: var(--color-accent);
  background: var(--cs-accent-tint);
}

/* GESPERRT: die Zeile bleibt stehen und bleibt lesbar — sie traegt den Grund.
   Deshalb wird sie abgeblendet und nicht ausgegraut: „Jonas hat nur 1" ist
   eine Auskunft und muss zu lesen sein (Spec 7.2). */
.gruppenzeile[disabled] {
  opacity: var(--gruppenzeile-gesperrt);
  cursor: default;
}

/* Der Fusssatz steht dicht unter der Liste (Artboard 26b: `margin:16px 2px 0`)
   und traegt den leisesten Textton des Entwurfs — er erklaert die Liste, er
   ist keine zweite Auskunft. KEIN `margin-bottom: auto` hier: der
   Handlungsblock traegt sein `margin-top: auto` schon, und zwei Autos teilen
   den freien Raum, statt den Block nach unten zu setzen. */
.gruppenliste__fuss {
  margin-top: var(--space-3);
  color: var(--raum-text-schwach);
  font-size: var(--gruppen-fuss-schrift);
}

/* Titel und Einleitung stehen auf den Graden des Artboards: 29 px in der
   Ueberschriftenschrift, 13,5 px im Fliesstext. */
.duell-gruppenwahl .fliess {
  font-size: var(--schrift-hinweis);
}

/* Gar keine Gruppe (26b-gruppe-keine): der gestrichelte Einladungskasten,
   dasselbe Muster wie die leere Garage (Artboard 21). `margin-bottom: auto`
   schiebt die eine Aktion ans untere Ende. */
.gruppen-leer {
  padding: var(--space-4);
  border-radius: var(--gruppen-leer-radius);
  border: var(--tableiste-randbreite) dashed var(--feld-rand);
}

.gruppen-leer__titel {
  margin: 0 0 var(--space-1);
  color: var(--raum-text);
  font-size: var(--schrift-fliess);
  font-weight: var(--gewicht-kraeftig);
  line-height: var(--zeilenhoehe-fliess);
}

.gruppen-leer__text {
  margin: 0;
  color: var(--raum-text-gedaempft);
  font-size: var(--schrift-hinweis);
  line-height: var(--zeilenhoehe-fliess);
}

/* --------------------------------------------------------------------------
 * Die Verbindung wird aufgebaut — Artboard 25 (WI-0096)
 *
 * DIESELBE BUEHNE WIE ARTBOARD 08 (§6 Zeile 25: „Same stage as 08"). Hier
 * steht deshalb nur, was in der Scheibe anders ist: zwei Zeichen statt einer
 * Silhouette, die aufeinander zuwandern.
 * ------------------------------------------------------------------------ */

.duell-verbinden__paar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
}

/* Der erklaerende Satz steht auf 25 eine Stufe leiser als der Fliesston der
   Flussbildschirme (Artboard 25: `color:#b5a992`) — §11 fuehrt ihn als
   `--cs-text-mute`. Die Zeile gilt NUR fuer diesen Bildschirm: die Buehne 08
   daneben zeichnet ihren Satz im Fliesston, und `.fliess` traegt ihn ueberall
   sonst weiter. */
.duell-verbinden .fliess {
  color: var(--raum-text-gedaempft);
}

.duell-verbinden__zeichen {
  width: var(--verbinden-zeichen);
  height: var(--verbinden-zeichen);
  flex: none;
  border-radius: var(--radius-pille);
  border: var(--karte-rand) solid var(--feld-rand);
  background: var(--feld-flaeche);
  color: var(--ghost-text);
  font-family: var(--font-heading);
  /* Artboard 25 setzt die beiden Zeichen auf 24 px — zwischen h4 (20) und
     h3 (25) der Skala, deshalb als eigenes Mass am Bauteil. */
  font-size: var(--verbinden-schrift);
  font-weight: var(--gewicht-heading);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: cs-verbinden var(--verbinden-dauer) cubic-bezier(0.3, 0.8, 0.3, 1) infinite;
}

/* Das EIGENE Zeichen kommt von links und traegt den Akzent — es ist der
   Spieler, der hier auf jemanden zugeht. */
/* DIE GLYPHE STEHT IM SANDTON, nicht im Akzent: Artboard 25 zeichnet sie als
   `color:#c9c0a8` — derselbe Rueckfallton, den §4.5b fuer einen Namen ohne
   eigene Farbe vorsieht und den der Entwurf auch auf `43-account` benutzt.
   Sie steht damit als einzige Avatarfarbe NICHT im vollen Dreiklang (die
   Scheibe darunter ist terracotta); das ist ein Widerspruch IM Artboard und
   als Luecke gemeldet, nicht hier aufgeloest. */
.duell-verbinden__zeichen--eigen {
  --verbinden-von: calc(var(--verbinden-weg) * -1);
  border-color: var(--verbinden-eigen-rand);
  background: var(--verbinden-eigen-flaeche);
  color: var(--avatar-sand);
}

.duell-verbinden__zeichen {
  --verbinden-von: var(--verbinden-weg);
}

.duell-verbinden__pfeil {
  width: var(--icon-mittel);
  height: var(--icon-mittel);
  flex: none;
  fill: none;
  stroke: var(--color-accent-300);
  stroke-linecap: round;
}

@keyframes cs-verbinden {
  0%,
  100% {
    transform: translateX(var(--verbinden-von));
    opacity: 0.55;
  }
  55% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
 * HIER STAND ARTBOARD 42 — DER GESPERRTE DUELL-REITER (WI-0096)
 *
 * `.duell-gesperrt__*`, `.ikone--schloss` und `.tableiste__schloss`. Entfernt
 * mit WI-0302: HANDOFF §23.1 nimmt `42-duel-locked` aus dem Produkt — „Duels
 * are open to every account."
 * ------------------------------------------------------------------------ */

/* --------------------------------------------------------------------------
 * Eroberung: der Kasten auf Artboard 27 und die Beute im Ergebnis
 *
 * Der Kasten ist der einzige Ort, an dem der Einsatzton FLAECHIG steht — dort
 * entscheidet jemand darueber, ob er Karten verlieren kann, und der Text muss
 * so schwer wiegen wie die Entscheidung.
 * ------------------------------------------------------------------------ */

/* Der Bildschirm nimmt die Hoehe, die das Geraet hergibt — der Kasten steht
   oben, die drei Wege unten im Daumenbereich (Designspec 10.3 Punkt 1 und 3). */
.duell-bestaetigen {
  flex: 1;
}

.duell-bestaetigen__kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Name und Kartenzahl stehen UNTEREINANDER rechts neben der Scheibe (Artboard
   27: „Mira fordert dich heraus" / „37 Karten"; WI-0317). Die Zahl stand bis
   dahin gar nicht da. Der Block darf schrumpfen, die Scheibe nicht — sie ist
   ein festes Mass, der Name ist Text und kann umbrechen. */
.duell-bestaetigen__anrede {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.duell-bestaetigen__aktionen {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.duell-bestaetigen__kasten {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: var(--karte-rand) solid var(--erobert-rand);
  background: var(--erobert-flaeche);
}

/* Artboard 27 setzt die Groessenleiter dieses Bildschirms eigens: die
   Einsatz-Zeile ueber dem Kasten als 11-px-Versalzeile, den zweiten Absatz
   darin auf 13,5 px und die drei Zeilen des Datenblocks auf 14 px. Der
   Merkmalsvergleich hat genau diese drei Stufen als fehlend gemeldet
   (WI-0096). Sie stehen HIER und nicht an den Grundbauteilen: `.chip` und
   `.datenblock` tragen ihre Groesse auf anderen Bildschirmen weiter. */
/* Artboard 27 setzt diese eine Augenbraue tiefer als die Skala ihre h6-Stufe
   (13 px, Rokkitt): 11 px Karla in 800, versal. Das ist die Stufe, die §4.6
   fuer `h6` ausschreibt — die Skala der App fuehrt sie als
   `--schrift-abschnitt`. Die Laufweite bleibt `--laufweite-versal`; der
   Entwurf zeichnet hier .12em, der Handoff nennt .08em, und ein zweiter
   Versalabstand daneben waere eine zweite Wahrheit fuer dieselbe Sache. */
.duell-bestaetigen__einsatz {
  margin: 0;
  color: var(--cs-r-epic);
  font-family: var(--font-body);
  font-size: var(--schrift-abschnitt);
  font-weight: var(--gewicht-fett);
}

/* WI-0188 — DIE ZWEI SAETZE IM KASTEN STANDEN VERTAUSCHT. Artboard 27 setzt
   die REGEL („behaelt die Karte … fuer immer") in den vollen Textton und den
   Trost darunter eine Stufe leiser; die App hatte beide je eine Stufe zu
   dunkel. Beide Werte kommen weiter aus §11, nur an der richtigen Zeile. */
.duell-bestaetigen__kasten .fliess {
  color: var(--raum-text);
}

.duell-bestaetigen__kasten .meta {
  font-size: var(--schrift-hinweis);
  color: var(--raum-fliess);
}

/* WI-0188 — DIE DREI ZEILEN SIND ZEILEN, KEINE AUFZAEHLUNG. Artboard 27
   zeichnet sie als drei volle Flaechen (`--cs-fill-1`) mit dem Wort links
   und dem Wert rechts; die App hatte sie als umbrechende Wortpaare ohne
   Flaeche. Als Gitter mit zwei Spalten steht jedes Paar auf einer Zeile;
   Rundung und Polster liegen je zur Haelfte an `dt` und `dd`, damit die
   beiden zusammen wie EINE Flaeche lesen, ohne dass die Liste dafuer ein
   Zwischenelement braucht. */
.duell-bestaetigen .datenblock {
  font-size: var(--schrift-zeile);
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0;
  row-gap: var(--datenblock-zeile-luecke);
}

.duell-bestaetigen .datenblock dt,
.duell-bestaetigen .datenblock dd {
  background: var(--cs-fill-1);
  padding: var(--datenblock-zeile-polster-oben) 0;
}

.duell-bestaetigen .datenblock dt {
  font-size: var(--schrift-zeile);
  color: var(--raum-text-gedaempft);
  padding-left: var(--datenblock-zeile-polster-seite);
  border-radius: var(--datenblock-zeile-radius) 0 0 var(--datenblock-zeile-radius);
}

.duell-bestaetigen .datenblock dd {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
  text-align: right;
  padding-right: var(--datenblock-zeile-polster-seite);
  border-radius: 0 var(--datenblock-zeile-radius) var(--datenblock-zeile-radius) 0;
}

/* WI-0314 — Artboard 38: die Kopf-Statistikzeile „Gegen {Name} X:Y ·
   Insgesamt X:Y" (Spec 4.8). Pille wie der Entwurf: Flaeche
   `rgba(245,234,216,.05)`, Rand `rgba(245,234,216,.16)` — §11 fuehrt beide
   Werte nicht, gemischt wird deshalb aus --cs-text, dieselbe Bauart wie an
   jeder anderen gemeldeten Luecke dieser Datei. */
.duell-ergebnis__bilanzkopf {
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: var(--radius-pille);
  background: color-mix(in srgb, var(--cs-text) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--cs-text) 16%, transparent);
  padding: 8px 16px;
}

/* `display: contents` nimmt die Gruppe aus dem Flex-Baum: der Entwurf setzt
   Beschriftung, Stand, Teiler, Beschriftung, Stand als EINE flache Reihe mit
   demselben 10px-Abstand, kein zweites Flex-Level. */
.duell-ergebnis__bilanzkopf-gruppe {
  display: contents;
}

.duell-ergebnis__bilanzkopf-label {
  font-size: 12px;
  color: var(--cs-text-dim);
}

.duell-ergebnis__bilanzkopf-stand {
  display: flex;
  align-items: baseline;
  gap: 3px;
}

.duell-ergebnis__bilanzkopf-zahl {
  font-family: var(--font-heading);
  font-size: 19px;
}

.duell-ergebnis__bilanzkopf-zahl--sieg {
  color: var(--cs-good-soft);
}

/* #e8a877 fuehrt §11 nicht — dieselbe Luecke wie an --chip-gefiltert-zahl und
   --reaktion-eigen-text, genommen wird deshalb dieselbe Sprosse der
   Akzentrampe statt eines Werts ohne Quelle. */
.duell-ergebnis__bilanzkopf-zahl--niederlage {
  color: var(--color-accent-400);
}

/* „:" zwischen den Zahlen, #6f6659 im Entwurf. §11 fuehrt den Ton nicht;
   gemischt wird wie an --chip-leer-name (72% der gedaempften Textstufe gegen
   den Grund trifft denselben Wert). */
.duell-ergebnis__bilanzkopf-trenner {
  font-size: 13px;
  color: color-mix(in srgb, var(--cs-text-dim) 72%, var(--cs-bg-top));
}

.duell-ergebnis__bilanzkopf-teiler {
  width: 1px;
  height: 16px;
  background: color-mix(in srgb, var(--cs-text) 16%, transparent);
}

.duell-ergebnis__erobert {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Die gewonnenen Karten werden BENANNT, nicht gezaehlt (Artboard 38). */
.duell-ergebnis__beute {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.duell-ergebnis__beute li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-lg);
  border: var(--karte-rand) solid var(--blatt-rand);
  background: var(--feld-flaeche);
  text-align: left;
}

/* Der Seltenheitsstreifen links an jeder Beutezeile — 40x54, in der Farbe der
   Karte (Artboard 38). Er ist die einzige Stelle, an der die Zeile eine Farbe
   traegt; sie kommt aus --r-g und nirgends sonst. */
.duell-ergebnis__beute-streifen {
  flex: none;
  width: 40px;
  height: 54px;
  border-radius: 9px;
  background: var(--karten-koerper);
  box-shadow: 0 0 0 2px var(--r-g);
}

.duell-ergebnis__beute-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* --------------------------------------------------------------------------
 * ARTBOARD 38b — verloren mit dem EIGENEN Deck (WI-0183)
 *
 * Der Spiegel von 38: dieselbe Zeile, andere Richtung. Bernstein statt Gruen,
 * Abwaertspfeil statt Haken, und die Liste ROLLT — eine Eroberung kann bei
 * Deckgroesse 8 acht Karten kosten und bei 32 mehr (Umsetzungs-Handoff §6.5).
 * ------------------------------------------------------------------------ */

/* DIE ROLLENDE STELLE, NACH DER REGEL AUS §8.1: genau EIN Kind mit ALLEN DREI
   Angaben — `flex: 1`, `min-height: 0`, `overflow-y: auto`. Zwei von dreien
   scheitern lautlos: die Spalte meldet keinen Ueberlauf, und die letzten
   Karten stehen unter der Bildkante. Deshalb tragen die Vorfahren `min-height:
   0` und NUR die Liste den Ueberlauf.

   DIE REGEL GILT „AUF JEDER EBENE" — und die oberste ist die Buehne. `.app`
   ist auf `min-height: 100dvh` gesetzt und waechst mit ihrem Inhalt; ohne
   einen Deckel ganz oben hat die Liste nichts, wogegen sie rollen koennte,
   und acht Karten schieben den Handlungsblock unter die Bildkante. Derselbe
   Deckel wie auf `11c` (`max-height: 100dvh`), aber ueber `:has()` NUR fuer
   diesen einen Zustand: die Partiebuehne traegt zwoelf andere Bildschirme,
   und keiner von ihnen soll dabei etwas abbekommen. */
.app__buehne[data-bildschirm='partie']:has(.duell-ergebnis[data-verlust='eigen']) {
  max-height: var(--sicher-hoehe);
  min-height: 0;
}

.app__buehne[data-bildschirm='partie']:has(.duell-ergebnis[data-verlust='eigen']) .duell {
  min-height: 0;
}
.duell-ergebnis[data-verlust='eigen'] {
  min-height: 0;
  padding-top: var(--verlust-rand-oben);
}

/* Die Groessenleiter der Zeile, wie 38b sie setzt. */
.duell-ergebnis__verlust .partie__halb-name {
  font-size: var(--verlust-name-schrift);
}

.duell-ergebnis__verlust .meta {
  font-size: var(--verlust-herkunft-schrift);
}

.duell-ergebnis[data-verlust='eigen'] .duell-ergebnis__erobert {
  flex: 1;
  min-height: 0;
}

.duell-ergebnis__verlust {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* Die Zeilen selbst wachsen NICHT mit dem Rollbereich mit (`flex: none` im
   Entwurf) — sonst schrumpfen acht Karten auf Streifenhoehe zusammen, statt
   dass die Liste rollt. */
.duell-ergebnis__verlust > li {
  flex: none;
}

/* Die Miniatur steht bei 55 %: sie belegt, WELCHE Karte weg ist — sie bietet
   sie nicht mehr an (Artboard 38b). Die Seltenheitsfarbe des Rings bleibt
   voll, sonst waere die Stufe nicht mehr abzulesen. */
.duell-ergebnis__verlust > li .duell-ergebnis__beute-streifen {
  opacity: var(--verlust-streifen-deckkraft);
}

/* EIN LANGER MODELLNAME BRICHT DIE ZEILE NICHT AUF.
   Der Name umbricht innerhalb seiner Spalte (die `min-width: 0` traegt),
   notfalls mitten im Wort — ein „Mercedes-Benz E-Klasse T-Modell" schiebt
   sonst den Chip aus der Zeile, und mit ihm die Auskunft, WOHIN die Karte
   geht. Der Chip bleibt unverkuerzbar. */
.duell-ergebnis__verlust .partie__halb-name {
  overflow-wrap: anywhere;
}

.duell-ergebnis__verlust .chip--verlust {
  flex: none;
}

/* Der Chip `An Mira` — dieselbe Bauart wie die EROBERT-Marke an der Karte,
   nur im Warnton: gefuellte Pille, dunkle Schrift, versal. Die beiden Toene
   sind ABLEITUNGEN aus --warn-icon (HANDOFF §11 `--cs-warn`) und keine
   abgeschriebenen Werte; §11 fuehrt fuer diese Marke keine eigene Stufe. */
.chip--verlust {
  border-color: transparent;
  background: var(--verlust-marke);
  color: var(--verlust-marke-text);
  font-size: var(--verlust-marke-schrift);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-versal);
  text-transform: uppercase;
  padding: var(--verlust-marke-polster);
  cursor: default;
}

/* Der Rueckweg ist ein NEBENSATZ der Ergebniszeile, kein eigener Block — und
   er traegt den Gut-Ton, weil er die einzige gute Nachricht auf dieser Seite
   ist (Umsetzungs-Handoff §6.5). */
.duell-ergebnis__rueckweg {
  color: var(--gruen-text);
}

/* Bernstein statt Grau: der Ring von 38b sagt „etwas ist gegangen", nicht
   „nichts ist passiert" (39) und nicht „verloren = Alarm". Kein Rot. */
.duell-ergebnis[data-verlust='eigen'] .duell-ergebnis__ring {
  border-width: var(--verlust-ring-rand);
  border-color: var(--verlust-ring-farbe);
  background: var(--verlust-ring-flaeche);
}

.duell-ergebnis[data-verlust='eigen'] .duell-ergebnis__glyphe {
  color: var(--warn-icon);
}

/* Ein Knopf mit einem Zeichen neben der Beschriftung (38b, „Zur Bilanz"). Er
   bleibt ein `.btn` — das Zeichen sitzt daneben, nicht darin.

   Er ist die ERSTE der beiden Aktionen und traegt deshalb deren Groesse: 48px
   hoch und 16px Schrift, wie sonst die Hauptaktion. Er ist trotzdem ein
   Ghost-Knopf — der Entwurf setzt hier ausdruecklich kein Terrakotta („nach
   einer Niederlage drängt hier nichts"), aber auch nicht die leisere zweite
   Stufe: darunter steht mit „Zur Garage" noch eine. */
.btn--mit-zeichen {
  gap: var(--space-2);
  min-height: var(--btn-hoehe);
  font-size: var(--btn-schrift);
}

.btn--mit-zeichen .ikone {
  flex: none;
  width: var(--icon-klein);
  height: var(--icon-klein);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
 * ARTBOARD 39 — verloren, ohne etwas zu verlieren
 *
 * Der gruene Block ist die haerteste Stelle der App: er widerspricht dem
 * Titel darueber, und das mit Absicht. Deshalb liegt er auf der
 * Erfolgsflaeche und nicht auf der neutralen — er soll gelesen werden, bevor
 * der Daumen weiterzieht (Nutzerreise J2 Schritt 7).
 * ------------------------------------------------------------------------ */

.duell-ergebnis__geliehen {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: var(--karte-rand) solid var(--gruen-rand);
  background: var(--gruen-flaeche);
  text-align: left;
}

.duell-ergebnis__geliehen-kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 15px;
  font-weight: var(--gewicht-fett);
  color: var(--gruen-text);
}

.duell-ergebnis__geliehen-kopf .ikone {
  flex: none;
  width: var(--icon-klein);
  height: var(--icon-klein);
  color: var(--gruen-icon);
}

.duell-ergebnis__geliehen .fliess {
  margin: 0;
  color: var(--gruen-text);
}

/* Der Ausblick darunter steht in einem EIGENEN, neutralen Kasten: er ist
   keine Beruhigung mehr, sondern eine Auskunft ueber die naechste Partie. */
.duell-ergebnis__geliehen-naechstes {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--blatt-rand);
  color: var(--raum-fliess);
}

.duell-ergebnis__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--partie-ergebnis-titel);
  line-height: 1.1;
  color: var(--raum-text);
}

/* Eine gewaehlte Kachel im Deckbau traegt den Terracotta-Rand — dieselbe
   Aktionsfarbe wie jeder Knopf, kein zweiter Ton fuer "ausgewaehlt". */
.kachel[data-gewaehlt='ja'] {
  box-shadow: 0 0 0 2.5px var(--color-accent);
}

/* In einer FREMDEN Sammlung heisst „gewaehlt" etwas anderes als im Deckbau:
   dort ist es eine Entscheidung (Terracotta, die Aktionsfarbe), hier ist es
   nur der Hinweis, auf welche Karte sich das Blatt darunter bezieht. Deshalb
   der Ring in der Seltenheitsfarbe der Karte — so zeichnet ihn Artboard 40,
   und so bleibt Terracotta den Aktionen (§7 Punkt 13). */
.freund-sammlung .kachel[data-gewaehlt='ja'] {
  box-shadow: 0 0 0 2.5px var(--r-g);
}

/* --------------------------------------------------------------------------
 * Duellbrett (Produktspec Kap. 7, Kartenspec Kap. 3/7)
 * ------------------------------------------------------------------------ */

/* Die Einsatzpille oben auf dem Brett (Artboard 29–39): eine PILLE, kein Band
   ueber die ganze Breite — in einer Spalte streckt sich sonst jedes Kind. */
.duell > [data-einsatz] {
  align-self: flex-start;
}

/* Die tippbare Wertezeile auf Artboard 29. Sie ist der EINZIGE Rest des alten
   Bretts: Statuszeile, Topfkasten, Rundenverlauf und die zwei gestapelten
   Seiten sind mit WI-0095 in die elf Zustaende oben aufgegangen und hier
   geloescht — stehengelassenes CSS waere ein zweiter Bauplan fuer dieselbe
   Sache. */
.partie .wertzeile[data-aktion] {
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--zeile-dauer) ease;
}

.partie .wertzeile[data-aktion]:hover,
.partie .wertzeile[data-aktion]:focus-visible {
  background: var(--glow-flaeche);
}

.partie .wertzeile[data-aktion][disabled] {
  cursor: not-allowed;
  opacity: var(--deaktiviert-deckkraft);
}

.duell-regel__pfeil {
  color: var(--karte-abwaerts);
}

/* --------------------------------------------------------------------------
 * DIE ELF ZUSTAENDE DER LAUFENDEN PARTIE — Artboards 29 bis 39 (WI-0095)
 *
 * EIN Bauteil `.partie`, elf Zustaende an `data-partie`. Was sie
 * unterscheidet, steht ausschliesslich hier; public/js/app.js setzt nur das
 * Attribut. Die Regel des Entwurfs, die dabei am haeufigsten greift: der Sieg
 * bekommt Ringe, Funken und den Gewinnhintergrund, die Niederlage bekommt
 * DIESELBE Anordnung ohne sie — „Verlieren wird gesagt, nicht bestraft"
 * (HANDOFF §7.9).
 * ------------------------------------------------------------------------ */

.partie {
  align-self: stretch;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Der Bildschirm nimmt die ganze Hoehe, damit der Handlungsblock unten sitzt
   und nicht in der Mitte (HANDOFF §4.4, Designspec 10.3 Punkt 1). */
.duell {
  flex: 1;
  min-height: 0;
}

/* Die Buehne der Partie hat ihre EIGENEN Raender, und zwar die des Entwurfs
   (HANDOFF §5.5: `padding: 12px 20px 0`; die Inhaltsspalte darunter sitzt bei
   24–26 px). Gemessen gegen die Artboards 28a–39 lag die allgemeine Buehne
   auf JEDEM der vierzehn Bildschirme daneben: oben 26 statt 14, seitlich 18
   statt 25.

   Die schwebende Tableiste steht hier ausserdem NICHT (HANDOFF §4.3 zaehlt
   sie einzeln auf, 29–39 sind nicht dabei). Der Fussfreiraum, den die Buehne
   fuer sie reserviert, waere 96 px totes Feld unter dem Knopf — der Entwurf
   verankert ihn bei 26 px. */
.app__buehne[data-bildschirm='partie'] {
  padding: var(--partie-rand-oben) var(--partie-rand-seite) var(--space-6);
}

/* Die beiden Ergebnisseiten fangen tiefer an als das Brett — der Entwurf
   setzt ihren ersten Block auf `padding: 40px 26px 0` (Artboards 38/39). */
.duell-ergebnis {
  padding-top: var(--space-6);
}

/* Der Gewinnhintergrund liegt unter der gewonnenen Runde und dem gewonnenen
   Duell — derselbe Ton wie unter dem gewonnenen Auftakt (28b). */
.partie[data-partie='runde-gewonnen'],
.partie[data-partie='ergebnis-sieg'] {
  background: var(--sieg-hintergrund);
}

/* --- Die Kopfzeile jeder Partieseite (HANDOFF §5.5) --- */

.partie__kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.partie__mitte {
  font-size: var(--partie-kopf-mitte);
  color: var(--raum-fliess);
}

/* „Verlassen" ist ein Ausgang, keine Hauptaktion: eine Textzeile, kein Knopf.
   Terracotta bleibt den Aktionen (HANDOFF §7.13). */
.partie__verlassen {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--partie-kopf-ausgang);
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text-schwach);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
 * DIE VIER FESTEN SAETZE DER PARTIE — 31b, 31c, 31d (HANDOFF §5.5b3)
 * ------------------------------------------------------------------------ */

/* Die Sprechblase im Kopf, links vom Ausgang. EIN Knopf, und er heisst immer
   „senden" — das Plus sagt „verfassen", der Strich sagt, dass Verfassen gerade
   ausgeschaltet ist. Stummschalten ist nicht dieser Knopf. */
.partie__nachricht-knopf {
  width: var(--partie-nachricht-knopf);
  height: var(--partie-nachricht-knopf);
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pille);
  border: var(--avatar-rand) solid var(--nachricht-knopf-rand);
  background: var(--nachricht-knopf-flaeche);
  color: var(--nachricht-knopf-glyphe);
  cursor: pointer;
}

.partie__nachricht-knopf[data-nachrichten='aus'] {
  border-color: var(--nachricht-knopf-aus-rand);
  background: transparent;
  color: var(--nachricht-knopf-aus-glyphe);
}

.ikone--sprechblase {
  width: var(--partie-nachricht-glyphe);
  height: var(--partie-nachricht-glyphe);
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

/* 31d — die EINE erklaerende Zeile. Kein Abzeichen, kein Zaehler daneben:
   sie sagt, dass es nichts zu verpassen gibt. */
.partie__nachrichten-aus {
  display: flex;
  align-items: center;
  gap: var(--nachricht-aus-abstand);
  margin-top: auto;
  padding: var(--nachricht-aus-polster);
  border-radius: var(--nachricht-aus-radius);
  border: var(--karte-rand) solid var(--blatt-rand);
  background: var(--feld-flaeche);
  color: var(--raum-fliess);
}

.partie__nachrichten-aus .fliess {
  flex: 1;
  margin: 0;
  font-size: var(--nachricht-aus-schrift);
}

.partie__nachrichten-aus .ikone--sprechblase {
  color: var(--nachricht-knopf-aus-glyphe);
}

/* 31c — die Flugbahn. Sie liegt UEBER allem und faengt nichts ab: eine
   Nachricht ist ein Gruss, kein Vorhang (§5.5b3). */
/* `fixed` aus demselben Grund wie `.blattlage`: die Bahn gehoert dem
   BILDSCHIRM, nicht dem Inhaltskasten der Partie — der endet oberhalb der
   Tableiste, und eine Pille darin wuerde auf halbem Weg abgeschnitten. */
.partie__nachrichtenflug {
  position: fixed;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}

.partie__nachrichtenspur {
  position: absolute;
  left: 0;
  right: 0;
  animation: cs-fly var(--nachricht-flug-1) linear 1 both;
}

.partie__nachrichtenspur[data-spur='0'] {
  top: var(--nachricht-spur-1);
  animation-duration: var(--nachricht-flug-1);
}

.partie__nachrichtenspur[data-spur='1'] {
  top: var(--nachricht-spur-2);
  animation-duration: var(--nachricht-flug-2);
}

.partie__nachricht {
  display: inline-flex;
  align-items: center;
  gap: var(--nachricht-pille-abstand);
  padding: var(--nachricht-pille-polster);
  border-radius: var(--radius-pille);
  /* Der Rand traegt die ABSENDERFARBE (MTC-10). Sie kommt aus `data-avatar`,
     das `avatarMarke` ohnehin schon setzt — damit gibt es zwischen Scheibe und
     Rand keine zweite Uebersetzungstabelle. */
  border: var(--avatar-rand) solid currentColor;
  background: var(--blatt-flaeche);
  box-shadow: var(--shadow-lg);
  animation: cs-bob var(--nachricht-wippe) ease-in-out infinite;
}

.partie__nachricht[data-avatar='#5fa39b'] {
  color: var(--avatar-tuerkis);
}
.partie__nachricht[data-avatar='#d97ea0'] {
  color: var(--avatar-rose);
}
.partie__nachricht[data-avatar='#7f9ede'] {
  color: var(--avatar-kornblume);
}
.partie__nachricht[data-avatar='#d9b24a'] {
  color: var(--avatar-senf);
}
.partie__nachricht[data-avatar='#a98cd9'] {
  color: var(--avatar-flieder);
}
.partie__nachricht[data-avatar='#c9c0a8'] {
  color: var(--avatar-sand);
}

/* Der Satz selbst bleibt Textfarbe — die Absenderfarbe faerbt nur Rand und
   Scheibe. Eine Avatarfarbe faerbt nie einen Text (§4.5b). */
.partie__nachricht-text {
  font-size: var(--nachricht-pille-schrift);
  font-weight: var(--gewicht-fett);
  color: var(--raum-text);
  white-space: nowrap;
}

.partie__nachricht-zeichen {
  font-size: var(--nachricht-pille-zeichen);
}

.avatar--nachricht {
  width: var(--avatar-nachricht);
  height: var(--avatar-nachricht);
  font-size: var(--avatar-nachricht-glyphe);
}

/* 31b — das Auswahlblatt. Dieselbe `blattlage` wie unter der Loeschabfrage. */
/* OHNE `position` hier malt die CSS-Stapelreihenfolge den positionierten
   `.blattlage__schleier` immer VOR diesem Blatt, unabhaengig von der
   DOM-Reihenfolge — ein echter Tipp auf den Schalter traf dann den Schleier,
   nicht den Schalter (WI-0342 Befund F-3, WI-0348). Jedes andere Blatt in
   einer `.blattlage` traegt diese `position` bereits an seiner eigenen Klasse
   (`.loeschen__blatt`, `.filterblatt`, `.anfrageblatt`,
   `.abmelden__blatt`/`.kontoloeschen__blatt`) — hier fehlte sie als einzige. */
.nachrichtenblatt {
  position: relative;
}

.nachrichtenblatt__titel {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--schrift-h3);
}

.nachrichtenblatt__raster {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

.nachrichtenblatt__satz {
  min-height: var(--nachricht-satz-hoehe);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0 var(--space-2);
  border-radius: var(--nachricht-satz-radius);
  border: var(--avatar-rand) solid var(--cs-line-3);
  background: none;
  font-family: var(--font-body);
  font-size: var(--nachricht-satz-schrift);
  font-weight: var(--gewicht-fett);
  color: var(--raum-text);
  text-align: center;
  cursor: pointer;
}

.nachrichtenblatt__satz[disabled] {
  opacity: var(--schleier-deckkraft);
  cursor: default;
}

.nachrichtenblatt__zeichen {
  font-size: var(--nachricht-satz-zeichen);
}

/* Der Schalter liegt IM Blatt („in context, where it annoys") und traegt
   dieselbe Zeile wie auf 43 — nur ohne den Rahmen der Kontoliste. */
.nachrichtenblatt__schalter {
  border: 0;
  border-top: var(--haarlinie) solid var(--cs-line-1);
  border-radius: 0;
  background: none;
  padding: var(--space-3) 0 0;
}

/* Die Augenbraue ueber einem Abschnitt (HANDOFF §12 „Board eyebrow").
 *
 * DIE KARTENBILDSCHIRME TRAGEN SIE SEIT WI-0329 NICHT MEHR (Befund 16-1).
 * `Eckdaten`, `Fundmarken`, `Dein Wurf` und `Woher sie kommt` auf
 * `16-card-fullscreen` standen hier — und damit in der Anzeigeschrift (die
 * Regel setzt keine Familie, das `h2` darunter erbt `--font-heading`) und in
 * `--color-accent-300`, also in Terracotta. Der Entwurf zeichnet sie als
 * kleine Versalzeile im Fliesstext und im gedaempften Ton, Wort fuer Wort
 * dieselbe Zeile wie `DEIN ZUGANG` auf `43-account` — und Terracotta bleibt
 * nach Designspec Kap. 9 den AKTIONEN; eine Abschnittsmarke ist keine.
 *
 * Genommen wurde deshalb `.abschnitt` (weiter oben), die vorhandene Fassung
 * genau dieser Zeile. Kein Bauteil hat eine Farbe ueberschrieben und keine
 * ist erfunden.
 *
 * DIE GEMELDETE LUECKE IST GESCHLOSSEN (WI-0340). Hier stand, der Entwurf
 * faerbe die Zeile mit `#a89c88`, HANDOFF §4.6 und §12 nennten beide
 * `--cs-text-dim` und §11 fuehre `#a89c88` gar nicht als Token — deshalb
 * zeige das Bauteil einen Nachbartoken. Der Ton steht seit WI-0340 als
 * `--cs-label` in §11 (HANDOFF §16.7, 01.10.2026), und `.abschnitt` bindet
 * daran. Die Begruendung ist damit erledigt; sie bleibt stehen, weil sie
 * sagt, WARUM diese Zeile einmal anders aussah.
 *
 * Was hier bleibt, ist die Grundfassung dieser Klasse: `--color-accent-300`.
 * Sie gilt WEITER fuer `29` („Wähl eine Kategorie") — der Entwurf schreibt
 * dort woertlich `var(--color-accent-300)` und NICHT `#a89c88`. Nur die drei
 * Lagen, die der Entwurf in `#a89c88` zeichnet, binden unten an den
 * Etikettton: `.partie__ansage` (`31`–`34`), `.partie__naechster` (`36`) und
 * `.partie__warten` (`30`). */
.abschnitt-label {
  margin: 0;
  font-size: var(--schrift-label);
  font-weight: var(--gewicht-fett);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-300);
}

/* --- Artboard 29: die Stapelzeile --- */

.partie__stapel,
.partie__gegnerzeile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.partie__stapel-ruecken {
  flex: none;
  width: var(--partie-ruecken-breite);
  height: var(--partie-ruecken-hoehe);
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  border: 3px solid var(--btn-text);
}

.partie__stapel-gegner {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.partie__stapel-eigen {
  display: flex;
  flex-direction: column;
  text-align: right;
}

.partie__stapel-name {
  font-size: 15px;
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text);
}

/* Das dritte Element: es sitzt ZWISCHEN den beiden Stapeln und ist auf seinen
   Inhalt bemessen ("sized to content", HANDOFF §5.5b6) — die beiden Stapel
   behalten ihren Platz, der Topf nimmt nur, was seine zwei Woerter brauchen.
   `flex: none` deshalb, und kein `flex: 1`. */
.partie__stapel-topf {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--partie-stapel-topf-polster);
  min-height: var(--partie-stapel-topf-hoehe);
  border: var(--partie-stapel-topf-rand);
  border-radius: var(--partie-stapel-topf-radius);
  background: var(--partie-stapel-topf-flaeche);
}

/* Die zwei Grade des Entwurfs: das Etikett auf 11,5 px/700
   (`--schrift-hinweis-klein`), die Zahl auf dem h5-Grad der Skala (16 px) in
   der Ueberschriftenfamilie — beides Token, kein roher Wert. */
.partie__stapel-topf-name {
  font-size: var(--schrift-hinweis-klein);
  font-weight: var(--gewicht-kraeftig);
  color: var(--cs-epic-soft);
}

.partie__stapel-topf-zahl {
  font-family: var(--font-heading);
  font-size: var(--schrift-h5);
  color: var(--cs-epic-soft);
}

.partie__stapel-zahl {
  font-size: var(--partie-kopf-mitte);
  color: var(--raum-text-schwach);
}

/*
 * DIE ZWEI GRADE DER STAPELZEILE SELBST (HANDOFF §5.5b6, WI-0346).
 *
 * Die beiden Regeln darueber (`-name` 15 px hell, `-zahl` 12,5 px matt)
 * gehoeren der GEGNERZEILE auf `30` — das Artboard zeichnet sie dort genau so
 * („Mira waehlt die Kategorie" auf 15px/700, „9 Karten im Stapel" auf 12,5px
 * #8d8272). In der Stapelzeile zeichnet derselbe Entwurf es UMGEKEHRT: das
 * Etikett matt und klein (11,5px #8d8272), die Zahl gross und hell in der
 * Ueberschriftenfamilie (16px #f5ead8). Beides sind dieselben Tokens, nur
 * getauscht — keine neue Farbe, kein neuer Grad.
 *
 * WARUM DAS HIER STEHT UND NICHT IN EINEM EIGENEN ITEM: solange die Zeile nur
 * auf `29` und `33b` stand, war der vertauschte Grad eine Abweichung an zwei
 * Stellen. Mit der Zeile auf neun Bildschirmen verdraengen die 12,5 px der
 * Zahl auf `31` den 26-px-Grad der Ansage aus den sechs meistbenutzten
 * Groessen, und der gemessene Abstand zum Entwurf springt von 0,5 auf 10
 * (design/entwurfs-befund.json, Merkmal `schriftgroessen`). Gesenkt wird an
 * der Ursache, nicht als Eintrag in design/befund-ausnahmen.json.
 *
 * Der Nachbarschaftsselektor ist Absicht: in der Stapelzeile sind die beiden
 * Bloecke DIREKTE Kinder von `.partie__stapel`, in der Gegnerzeile haengt
 * `.partie__stapel-gegner` unter `.partie__gegnerzeile`. So trifft die Regel
 * die Zeile und laesst die Gegnerzeile unberuehrt.
 */
.partie__stapel > .partie__stapel-gegner > .partie__stapel-name,
.partie__stapel > .partie__stapel-eigen > .partie__stapel-name {
  font-size: var(--schrift-hinweis-klein);
  font-weight: normal;
  color: var(--raum-text-schwach);
}

.partie__stapel > .partie__stapel-gegner > .partie__stapel-zahl,
.partie__stapel > .partie__stapel-eigen > .partie__stapel-zahl {
  font-family: var(--font-heading);
  font-size: var(--schrift-h5);
  color: var(--raum-text);
}

.partie__warten {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 3px;
  color: var(--raum-text-etikett);
}

/* --- Artboard 29: die gewaehlte Zeile ist HERVORGEHOBEN, nicht gespielt --- */

.partie .wertzeile[data-gewaehlt='ja'] {
  border: 2px solid var(--gruen-icon);
  background: var(--gruen-flaeche);
}

/* Der Handlungsblock jeder Partieseite — unten, mit einem Daumen erreichbar
   (HANDOFF §4.4, Designspec 10.3 Punkt 1). */
.partie__aktionen {
  margin-top: auto;
  padding-top: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* --- Artboards 30/31/32/34: zwei Karten nebeneinander --- */

.partie__zwei {
  display: flex;
  justify-content: center;
  /* STRETCH, nicht flex-start: die verdeckte Karte des Gegners ist im Entwurf
     genau so hoch wie die offene daneben (150x261 auf 30, 150x289 auf 31).
     Ihre eigene Hoehe hat sie aus der Kartenansicht und waere hier fast
     doppelt so hoch. */
  align-items: stretch;
  gap: var(--space-3);
}

.partie__platz {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.partie__platz-name {
  font-size: 10.5px;
  font-weight: var(--gewicht-fett);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--raum-text-schwach);
}

.partie__platz[data-wer='ich'] .partie__platz-name {
  color: var(--gruen-icon);
}

/* Die verdeckte Karte des Gegners: dieselbe Rueckseite wie ueberall, auf die
   Breite der halben Karte gebracht. Sie traegt KEINE Seltenheitsfarbe — sonst
   liesse sich von hinten lesen, was er hat (Kartenspec Kap. 10). */
.partie__rueckseite {
  width: var(--partie-halb-breite);
  flex: 1;
}

.partie__rueckseite .karte {
  width: 100%;
  height: 100%;
}

/* WI-0208 — DIE AUFDECKUNG LAEUFT VON SELBST (HANDOFF §5.5b, §22.4).
 *
 * Es gibt keinen `Karte aufdecken`-Knopf mehr; die Rueckseite hebt sich und
 * dreht sich weg. Der Takt steht im Entwurf: 0 ms heben (8 px, 1.03), ab
 * 220 ms drehen ueber 620 ms — bei 840 ms ist sie kantig zum Betrachter, und
 * genau dort wechselt der Bildschirm auf den Vergleich, der die aufgedeckte
 * Karte zeigt. Die beiden letzten Schlaege des Entwurfs (1020 ms die
 * gespielte Zeile, 1260 ms die Urteilszeile) liegen deshalb DORT und nicht
 * hier — sie brauchen Bauteile, die es auf 31 gar nicht gibt.
 *
 * KEINE ZWEITE KARTENFLAECHE: der Entwurf beschreibt zwei Gesichter in einem
 * `preserve-3d`-Behaelter, die App zeichnet das zweite Gesicht ohnehin schon
 * — als Vergleich, eine Zustandsgrenze weiter. Ein verstecktes Duplikat
 * daneben waere ein zweiter Kartenrenderer und stuende ausserdem in jeder
 * Messung dieses Bildschirms mit drin.
 *
 * DER UEBERGANG HAENGT AN DER UHR, NICHT AN `animationend` (app.js
 * `pflegeStrecke`): unter `prefers-reduced-motion` laeuft hier gar nichts,
 * und ein Bildschirm ohne Knopf, der dann stehenbliebe, waere eine Sackgasse. */
.partie__rueckseite[data-aufdecken='laeuft'] {
  transform-origin: 50% 50%;
  animation:
    cs-reveal-lift var(--partie-aufdeck-heben) ease-out forwards,
    cs-reveal-turn var(--partie-aufdeck-drehen) var(--partie-aufdeck-heben)
      var(--partie-aufdeck-kurve) forwards;
}

@keyframes cs-reveal-lift {
  from {
    transform: translateY(0) scale(1);
  }
  to {
    transform: translateY(-8px) scale(1.03);
  }
}

/* Der Bodenschatten geht mit: er schmaelert sich, waehrend die Karte kantig
   wird — das ist es, was die Drehung koerperlich statt wie einen Bildtausch
   aussehen laesst (§5.5b, `cs-reveal-shadow`). */
@keyframes cs-reveal-turn {
  from {
    transform: perspective(1100px) translateY(-8px) scale(1.03) rotateY(0deg);
    filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.45));
  }
  to {
    transform: perspective(1100px) translateY(-8px) scale(1.03) rotateY(90deg);
    filter: drop-shadow(0 10px 10px rgba(0, 0, 0, 0.7));
  }
}

/* --- Die halbe Karte (HANDOFF §5.4) --- */

.partie__halb {
  width: var(--partie-halb-breite);
  flex: none;
  display: flex;
  flex-direction: column;
  padding: var(--partie-halb-polster);
  border-radius: var(--partie-halb-radius);
  background: var(--karten-koerper);
  box-shadow: var(--partie-halb-rand-verlierer);
}

.partie__halb[data-ausgang='sieger'] {
  box-shadow: var(--partie-halb-rand-sieger);
}

.partie__halb[data-ausgang='verlierer'] {
  opacity: 0.9;
}

.partie__halb-name {
  font-family: var(--font-heading);
  font-size: var(--partie-halb-name);
  line-height: 1.15;
  color: var(--raum-text);
}

.partie__halb-klasse {
  font-size: var(--partie-halb-klasse);
  color: var(--raum-text-schwach);
  margin-bottom: var(--space-2);
  /* Zwei Zeilen fest: der Fundzaehler (Kartenspec Kap. 7) laesst die Zeile je
     nach Modellname umbrechen, und ohne festes Mass staenden die Werte der
     beiden Karten dann auf verschiedenen Hoehen. */
  min-height: 2.5em;
}

.partie__halb-foto {
  height: var(--partie-halb-foto);
  border-radius: var(--partie-gespielt-radius);
  background: var(--foto-flaeche);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-bottom: var(--space-2);
}

/*
 * DIE LAGE DES AUSSCHNITTS (WI-0127). `object-position` steht hier bewusst mit
 * `50% 50%` — dem Vorgabewert — und wird vom Renderer ueberschrieben, sobald
 * das Foto seine Fahrzeugmitte mitbringt (public/js/card.js
 * `fuelleFotoflaeche`, abgeleitet in `filterchain.objektPosition` aus
 * `FOTOBAENDER`). Ohne gespeicherte Mitte — jedes Foto von vor WI-0127 —
 * bleibt es bei diesem Wert. Wer hier einen anderen setzt, verschiebt jedes
 * Bestandsfoto.
 */
.partie__halb-foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}

.partie__halb-foto .silhouette {
  width: 70%;
  color: var(--r-g);
}

.partie__halb-werte {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.partie__halb-zeile {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--partie-halb-zeile);
  color: var(--raum-fliess);
}

.partie__halb-wert {
  color: var(--raum-text);
  font-weight: var(--gewicht-kraeftig);
}

/* Die gespielte Zeile wird aus der Liste herausgehoben (§5.4). */
.partie__halb-zeile[data-gespielt='ja'] {
  align-items: center;
  border-radius: var(--partie-gespielt-radius);
  border: var(--partie-gespielt-rand-verlierer);
  padding: var(--partie-gespielt-polster);
  color: var(--warn-icon);
  font-weight: var(--gewicht-fett);
}

.partie__halb[data-ausgang='sieger'] .partie__halb-zeile[data-gespielt='ja'] {
  background: var(--partie-gespielt-flaeche);
  border: var(--partie-gespielt-rand);
  color: var(--gruen-text);
}

.partie__halb-zeile[data-gespielt='ja'] .partie__halb-wert {
  font-family: var(--font-heading);
  font-size: var(--partie-halb-gespielt);
  color: inherit;
}

/* --- Artboard 31: die Ansage ueber den Karten --- */

.partie__ansage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
}

.partie__ansage .abschnitt-label {
  color: var(--raum-text-etikett);
}

.partie__kategorie {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 26px;
  line-height: 1.15;
  color: var(--raum-text);
}

.partie__pille {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 10px 18px;
  border-radius: var(--radius-pille);
  background: var(--feld-flaeche);
  border: 1px solid var(--feld-rand);
  font-size: 14px;
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text);
}

/* --- Die Urteilszeile (§5.4): gruen im Sieg, warnorange in der Niederlage --- */

.partie__urteil {
  margin: 0;
  text-align: center;
  font-family: var(--font-heading);
  font-size: var(--partie-urteil);
  line-height: 1.1;
  color: var(--warn-icon);
}

[data-partie='vergleich-sieg'] .partie__urteil,
[data-partie='runde-gewonnen'] .partie__urteil {
  color: var(--gruen-text);
}

[data-partie='runde-gewonnen'] .partie__urteil,
[data-partie='runde-verloren'] .partie__urteil {
  font-size: var(--partie-urteil-gross);
}

/* --- Artboards 33/35: die Rundenbewegung --- */

.partie__buehne {
  position: relative;
  display: flex;
  justify-content: center;
  padding-top: var(--space-4);
}

.partie__ring {
  position: absolute;
  left: 50%;
  /* Der Ring sitzt UNTEN an den Karten, nicht in ihrer Mitte: der Entwurf
     setzt seinen Mittelpunkt auf y=300 bei Karten von y=110 bis y=340 — er
     laeuft also nach UNTEN aus dem Kartenblock heraus und nie ueber die
     Kopfzeile. */
  top: 88%;
  width: var(--partie-ring);
  height: var(--partie-ring);
  margin-left: calc(var(--partie-ring) / -2);
  margin-top: calc(var(--partie-ring) / -2);
  border-radius: var(--radius-pille);
  border: 2px solid var(--gruen-icon);
  animation: cs-glowring var(--partie-ring-dauer) ease-out infinite;
  pointer-events: none;
}

.partie__ring--spaet {
  border-color: color-mix(in srgb, var(--gruen-icon) 60%, transparent);
  animation-delay: var(--partie-ring-versatz);
}

[data-partie='runde-gewonnen'] .partie__zwei--bewegt > * {
  animation: cs-toMe var(--partie-karten-dauer) var(--partie-karten-kurve) infinite;
}

[data-partie='runde-verloren'] .partie__zwei--bewegt > * {
  animation: cs-toThem var(--partie-karten-dauer-verloren) var(--partie-karten-kurve) infinite;
}

.partie__zwei--bewegt > *:nth-child(2) {
  animation-delay: 0.12s;
}

.partie__funken {
  display: flex;
  justify-content: center;
  gap: 9px;
}

.partie__funken > span {
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pille);
  background: var(--sieg-farbe);
  box-shadow: 0 0 10px var(--sieg-farbe);
  animation: cs-spark 1.6s ease-out infinite;
}

.partie__funken > span:nth-child(2) {
  background: var(--sieg-stern-hell);
  animation-duration: 1.8s;
  animation-delay: 0.2s;
}

.partie__funken > span:nth-child(3) {
  animation-duration: 1.5s;
  animation-delay: 0.35s;
}

.partie__funken > span:nth-child(4) {
  background: var(--sieg-stern-hell);
  animation-duration: 1.9s;
  animation-delay: 0.5s;
}

/* --- WI-0208, Artboard 33b: ich bin durch, die andere Seite nicht ---
 *
 * HANDOFF §22.2. Kein eigener Bildschirm und kein zweites Bauteil: derselbe
 * Kartenblock wie auf 33/35, nur ANGEHALTEN und gedaempft — „sie sind
 * erledigt, nicht taetig". Ringe und Funken fehlen hier nicht aus Versehen:
 * die Runde wurde auf 33 gefeiert, und ein zweites Mal zu feiern, waehrend
 * nichts geschieht, ist Laerm. */
.partie__buehne--ruht .partie__zwei--bewegt > * {
  animation: none;
  opacity: var(--partie-warten-karten);
}

/* Die Aussage steht im gedaempften Ton und NICHT in Salbei: Warten ist weder
   gute noch schlechte Nachricht (§22.2). */
.partie__warten-titel {
  margin: 0;
  text-align: center;
  font-family: var(--font-heading);
  font-size: var(--partie-warten-titel);
  line-height: 1.1;
  font-weight: var(--gewicht-kraeftig);
  color: var(--raum-text-hell);
}

/* Statt eines Knopfes ein Zustandsblock — es gibt nichts mehr zu druecken.
   Er hat deshalb die Hoehe eines Knopfes, aber weder Terrakotta noch
   Zeigefinger (Designspec Kap. 9: Terrakotta bleibt den Handlungen). */
.partie__durch {
  min-height: var(--partie-durch-hoehe);
  border-radius: var(--radius-pille);
  background: var(--partie-durch-flaeche);
  border: 1.5px solid var(--partie-durch-rand);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  font-size: 16px;
  font-weight: var(--gewicht-kraeftig);
  color: var(--partie-durch-text);
}

.partie__durch-haken {
  width: var(--partie-durch-haken);
  height: var(--partie-durch-haken);
  color: var(--gruen-icon);
  flex: none;
}

/* --- Artboard 36: Gleichstand, der Topf waechst (Spec 7.4) --- */

.partie__gleichstand {
  border-radius: var(--radius-lg);
  border: var(--partie-topf-rand);
  background: var(--partie-topf-flaeche);
  padding: var(--space-4);
  text-align: center;
}

.partie__gleichstand h3 {
  margin: 0 0 var(--space-1);
  color: var(--partie-topf-titel);
}

.partie__gleichstand p {
  margin: 0;
}

.partie__topfstapel {
  position: relative;
  height: 170px;
}

.partie__topfkarte {
  position: absolute;
  left: 50%;
  width: var(--partie-topfkarte-breite);
  height: var(--partie-topfkarte-hoehe);
  border-radius: 12px;
  background: var(--color-accent);
  border: 4px solid var(--btn-text);
  animation: cs-drop var(--partie-topf-dauer) var(--partie-topf-kurve) both;
}

.partie__topfkarte[data-platz='0'] {
  --r: -8deg;
  top: 34px;
  margin-left: -90px;
  transform: rotate(-8deg);
}

.partie__topfkarte[data-platz='1'] {
  --r: -2deg;
  top: 26px;
  margin-left: -46px;
  transform: rotate(-2deg);
  animation-delay: var(--partie-topf-versatz);
}

.partie__topfkarte[data-platz='2'] {
  --r: 5deg;
  top: 30px;
  margin-left: -6px;
  transform: rotate(5deg);
  animation-delay: calc(var(--partie-topf-versatz) * 2);
}

.partie__topfkarte[data-platz='3'] {
  --r: 11deg;
  top: 38px;
  margin-left: 32px;
  transform: rotate(11deg);
  animation-delay: calc(var(--partie-topf-versatz) * 3);
}

.partie__naechster {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
}

.partie__naechster .abschnitt-label {
  color: var(--raum-text-etikett);
}

.partie__naechster p {
  margin: 0;
}

.partie__naechste-karte {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

@keyframes cs-glowring {
  0% {
    transform: scale(0.6);
    opacity: 0.85;
  }
  100% {
    transform: scale(1.7);
    opacity: 0;
  }
}

@keyframes cs-toMe {
  0% {
    transform: translate(0, 0) rotate(-4deg) scale(1);
    opacity: 1;
  }
  70% {
    transform: translate(0, 300px) rotate(6deg) scale(0.6);
    opacity: 1;
  }
  100% {
    transform: translate(0, 360px) rotate(8deg) scale(0.5);
    opacity: 0;
  }
}

@keyframes cs-toThem {
  0% {
    transform: translate(0, 0) rotate(4deg) scale(1);
    opacity: 1;
  }
  70% {
    transform: translate(0, -300px) rotate(-6deg) scale(0.6);
    opacity: 1;
  }
  100% {
    transform: translate(0, -350px) rotate(-8deg) scale(0.5);
    opacity: 0;
  }
}

@keyframes cs-drop {
  0% {
    transform: translateY(-160px) rotate(0);
    opacity: 0;
  }
  62% {
    opacity: 1;
  }
  78% {
    transform: translateY(8px) rotate(var(--r));
  }
  90% {
    transform: translateY(-4px) rotate(var(--r));
  }
  100% {
    transform: translateY(0) rotate(var(--r));
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
 * ARTBOARD 37 — Verbindung weg (Produktspec 7.5)
 *
 * Ein Blatt ueber dem VERWISCHTEN Brett, derselbe Aufbau wie bei der
 * Loeschabfrage (HANDOFF §6 Zeile 17): das Darunter bleibt sichtbar, damit
 * erkennbar bleibt, um welche Partie es geht — und tritt weit genug zurueck,
 * dass die Entscheidung vorn steht.
 * ------------------------------------------------------------------------ */

.duell[data-verwischt='ja'] {
  position: relative;
}

[data-verwischt='ja'] > .partie {
  filter: blur(var(--schleier-unschaerfe));
  opacity: var(--schleier-deckkraft);
  pointer-events: none;
}

/* Das Blatt liegt UEBER dem Brett und unten an (Artboard 37). Im Fluss
   gestapelt haette es das Brett nach oben aus dem Bild geschoben — und der
   Entwurf zeichnet das Brett ausdruecklich darunter, damit erkennbar bleibt,
   um welche Partie es geht. */
[data-verwischt='ja'] > .duell-abbruch {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin-top: 0;
}

.duell-abbruch__ikone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pille);
  background: var(--cs-accent-tint);
  color: var(--color-accent-300);
}

.duell-abbruch__ikone .ikone {
  width: var(--icon-mittel);
  height: var(--icon-mittel);
}

.duell-abbruch__stand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--feld-flaeche);
  border: 1px solid var(--feld-rand);
  font-size: 13.5px;
  color: var(--raum-fliess);
}

/* --------------------------------------------------------------------------
 * Artboard 37b — „Partie verlassen?" (HANDOFF §23.6, WI-0284)
 *
 * Dasselbe Blatt wie 37, an derselben Stelle: unten an, ueber dem
 * verwischten Brett. Es bringt keine eigene Geometrie mit — die Frage ist
 * ein Blatt wie die Loeschabfrage (§6 Zeile 17/37), und zwei Blaetter mit
 * verschiedenen Maassen waeren zwei Bauteile fuer eine Lage.
 * ------------------------------------------------------------------------ */
[data-verwischt='ja'] > .duell-verlassen {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin-top: 0;
}

/* WI-0319 (F-11) — Artboard 28f: dasselbe Blatt-ueber-verwischtem-Brett wie
   37/37b, nur mit der Regel-Einblendung als Inhalt statt der Abbruch- oder
   Verlassen-Frage. */
[data-verwischt='ja'] > .duell-regel {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin-top: 0;
}

/* --------------------------------------------------------------------------
 * Der Rundenauftakt — Schere, Stein, Papier (Produktspec 7.3a, 28a/28b/28c)
 *
 * DREI ZUSTAENDE, EIN BAUTEIL. `data-auftakt` traegt sie: `wahl` und
 * `nochmal` sind die Auswahl, `gewonnen` und `verloren` das Ergebnis. Die
 * verlorene Auslosung bekommt AUSDRUECKLICH keinen Ring und keine Funken —
 * dieselbe Regel wie bei der verlorenen Partie.
 * ------------------------------------------------------------------------ */

/* Er nimmt die Hoehe, die das Geraet hergibt — kein Block oben und eine
   leere Flaeche darunter (Designspec 10.3 Punkt 3). Die Buehne ist eine
   Flexspalte; ohne diese beiden Zeilen bliebe der Auftakt oben kleben. */
.duell--auftakt {
  flex: 1;
}

.auftakt {
  align-self: stretch;
  flex: 1;
  gap: var(--space-3);
}

/* Drei gleich breite Karten in EINER Reihe, im UNTEREN Drittel: sie sind die
   Hauptaktion dieses Bildschirms und muessen mit einem Daumen erreichbar sein
   (Designspec 10.3 Punkt 1). Was darueber steht, erklaert sie nur. */
.auftakt__wahl {
  align-self: stretch;
  margin-top: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

/* WI-0188 — `font-family` steht HIER, weil ein `<button>` die Schrift der
   Seite nicht erbt: der Browser setzt seine eigene (gemessen: Arial). Der
   Entwurf schreibt auf allen drei Kacheln Karla. */
.auftakt__karte {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-2);
  border-radius: var(--radius-lg);
  border: var(--auftakt-rand);
  background: transparent;
  font-family: var(--font-body);
  color: var(--raum-fliess);
  cursor: pointer;
}

/* Die gewaehlte Kachel steht LAUTER als die beiden anderen — nicht nur im
   Rand: Artboard 28a setzt ihren Namen auf den vollen Textton in 800, die
   ungewaehlten eine Stufe leiser in 700. Ohne den Unterschied traegt die Wahl
   allein der Rand, und der ist auf einem Handy im Sonnenlicht das erste, was
   verschwindet. */
.auftakt__karte[data-gewaehlt='ja'] {
  border: var(--auftakt-rand-gewaehlt);
  background: var(--auftakt-flaeche-gewaehlt);
  color: var(--raum-text);
}

.auftakt__karte[data-gewaehlt='ja'] .auftakt__name {
  font-weight: var(--gewicht-fett);
}

.auftakt__ikone {
  width: var(--auftakt-ikone);
  height: var(--auftakt-ikone);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.auftakt__ikone--gross {
  width: var(--auftakt-ikone-gross);
  height: var(--auftakt-ikone-gross);
}

.auftakt__name {
  font-size: var(--auftakt-name);
  font-weight: var(--gewicht-kraeftig);
}

/* WI-0188 — DIE GEGNERZEILE VON 28a: Avatarscheibe, daneben der Satz. Bis
   hierher stand dort nur der Satz. Die Scheibe ist dieselbe wie ueberall
   (§4.5b), in seiner Farbe — sie sagt auf einen Blick, WER wartet. */
.auftakt__gegner {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-align: left;
}

/* 14 px — der Entwurf setzt diese eine Zeile eine Stufe ueber die Metazeile,
   weil sie das einzige ist, was ueber den anderen Spieler dasteht. */
.auftakt__gegner-text {
  flex: 1;
  font-size: var(--schrift-zeile);
}

/* Beide Zeichen NEBENEINANDER — meines links, seines rechts. Die beiden
   `auto`-Abstaende teilen die freie Hoehe: das Bild sitzt in der Mitte, der
   Knopf ganz unten. */
.auftakt__buehne {
  align-self: stretch;
  margin-top: auto;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--space-3);
  animation: cs-pop 620ms ease-out both;
}

.auftakt--ergebnis .btn {
  margin-top: auto;
}

.auftakt__seite {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--radius-lg);
  border: var(--auftakt-rand);
}

.auftakt__seite[data-sieger='ja'] {
  border: var(--auftakt-rand-sieger);
}

.auftakt[data-auftakt='verloren'] .auftakt__seite[data-sieger='nein'] {
  border: var(--auftakt-rand-verloren);
}

/* WI-0319 (F-12) — „Du"/Gegnername ueber dem Zeichen, Artboard 28b/28c:
   10.5 px, gesperrt, versal — derselbe Stil wie `.partie__platz-name` am
   Brett, nur unter einem eigenen Klassennamen, weil sie an `.auftakt__seite`
   haengt und nicht an `.partie__platz`. */
.auftakt__wer {
  font-size: var(--auftakt-wer);
  font-weight: var(--gewicht-fett);
  letter-spacing: var(--laufweite-buchstabe);
  text-transform: uppercase;
  color: var(--raum-text-schwach);
}

.auftakt__seite[data-sieger='ja'] .auftakt__wer {
  color: var(--gruen-icon);
}

/* Die Urteilszeile: „Stein schlägt Schere" — gruen im Sieg, warnorange in
   der Niederlage. */
.auftakt__urteil {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--auftakt-urteil);
  line-height: 1.1;
  color: var(--warn-icon);
}

/* WI-0188: `du-beginnst` stand hier mit — der Gewinngrund lag damit als
   getoente FLAECHE im Bildschirm statt als sein Grund (Artboard 28d malt ihn
   auf den Rahmen). Er kommt jetzt ueber `data-raum` an `.app`. */
.auftakt[data-auftakt='gewonnen'] {
  background: var(--sieg-hintergrund);
}

.auftakt[data-auftakt='gewonnen'] .auftakt__urteil {
  color: var(--gruen-text);
}

.auftakt--ergebnis {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
}

/* WI-0188 — 28d/28e SIND KEIN KASTEN AUF EINEM BILDSCHIRM, SIE SIND DER
   BILDSCHIRM. Der Entwurf verankert sie an den Kanten: Kopfzeile auf
   `12px 20px`, Fussblock `left:26 right:26 bottom:34`. Das Polster eines
   eigenen Kastens hat die Inhaltsspalte um 18 px nach innen gezogen und den
   Fuss um dieselben 18 px nach oben — beides gemessen als Abweichung. Die
   Buehne der Partie setzt die Seiten schon; unten fehlt zu den gezeichneten
   34 px genau eine Stufe 2. */
.auftakt--start {
  padding: 0 0 var(--space-2);
}

/* --------------------------------------------------------------------------
 * „Wer beginnt" — 28d/28e (Handoff v3 §17)
 *
 * ZWEI ZUSTAENDE, EIN BAUTEIL, und ihre Geometrie ist Zeile fuer Zeile
 * dieselbe: `du-beginnst` traegt den Gewinnhintergrund und Sage,
 * `gegner-beginnt` den normalen Hintergrund und Terracotta. Der EINZIGE
 * bauliche Unterschied ist der Leuchtreif, den es nur auf 28d gibt — kein
 * Ring, keine Funken auf der verlorenen Seite (HANDOFF §7.9).
 *
 * Der Balken unten ist ein BILD. Weitergezaehlt wird in public/js/app.js an
 * der Uhr, damit ein Lauf, der nie anlaeuft, niemanden festhaelt.
 * ------------------------------------------------------------------------ */

/* Zwischen Kopfzeile und Fuss frei schwebend: die beiden `auto`-Abstaende
   teilen die Hoehe, der Fuss bleibt unten (Designspec Kap. 9 — verankert wird
   an den Kanten, nicht am Pixelversatz). */
.auftakt__start {
  align-self: stretch;
  margin: auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.auftakt__scheibe {
  position: relative;
  width: var(--auftakt-scheibe);
  height: var(--auftakt-scheibe);
  margin-bottom: var(--space-6);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* WI-0188 — SIE IST EINE AVATARSCHEIBE (§4.5b) UND TRAEGT DESHALB HIER WEDER
   FLAECHE NOCH GLYPHENFARBE: beides kommt aus `.avatar--<farbe>`, damit es
   fuer die Farbe eines Spielers genau eine Stelle gibt. Was hier bleibt, ist
   das, was DIESE Scheibe von jeder anderen unterscheidet — sie fuellt ihren
   Rahmen, ihre Glyphe ist 40 px, und ihr Rand traegt den Ton des AUSGANGS,
   nicht den der Person (Artboard 28d zeichnet Sand auf Salbeigruen, 28e Rose
   auf Warnorange). */
.auftakt__marke {
  width: 100%;
  height: 100%;
  border-width: var(--auftakt-marke-rand);
  font-size: var(--auftakt-marke);
  line-height: 1;
}

.auftakt[data-auftakt='du-beginnst'] .auftakt__marke {
  border-color: var(--gruen-text);
}

.auftakt[data-auftakt='gegner-beginnt'] .auftakt__marke {
  border-color: var(--warn-icon);
}

.auftakt__reif {
  position: absolute;
  inset: calc(var(--auftakt-reif-ueberstand) * -1);
  border-radius: 50%;
  border: 2px solid var(--gruen-icon);
  animation: cs-glowring var(--auftakt-balken-dauer) ease-out infinite;
}

.auftakt__aussage {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--auftakt-aussage);
  line-height: 1.05;
  text-align: center;
  color: currentcolor;
  animation: cs-pop 620ms ease-out both;
}

.auftakt__zeile {
  margin: var(--space-3) 0 0;
  font-size: var(--auftakt-aussage-zeile);
  color: var(--raum-fliess);
}

/* Die Farbe des Ausgangs steht EINMAL, am Block — Scheibe, Marke und Aussage
   erben sie ueber `currentcolor`. */
.auftakt[data-auftakt='du-beginnst'] .auftakt__start {
  color: var(--gruen-text);
}

.auftakt[data-auftakt='gegner-beginnt'] .auftakt__start {
  color: var(--warn-icon);
}

.auftakt__fuss {
  align-self: stretch;
  margin-top: auto;
}

.auftakt__balken {
  height: var(--auftakt-balken);
  border-radius: var(--radius-pille);
  background: var(--auftakt-balken-spur);
  overflow: hidden;
}

/* Ohne Lauf steht er voll da — die volle Breite ist der Ausgangswert, und
   `cs-startbar` zieht ihn von 0 dorthin. Andersherum (Ausgangswert 0) waere
   bei abgeschalteter Bewegung eine leere Spur zu sehen, und das saehe aus wie
   etwas, das haengt. */
.auftakt__balkenlauf {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: var(--radius-pille);
  animation: cs-startbar var(--auftakt-balken-dauer) linear forwards;
}

.auftakt[data-auftakt='du-beginnst'] .auftakt__balkenlauf {
  background: var(--gruen-text);
}

.auftakt[data-auftakt='gegner-beginnt'] .auftakt__balkenlauf {
  background: var(--warn-icon);
}

/* WI-0208 — 28b/28c tragen denselben Balken (HANDOFF §22.1): der Ausgang
   faerbt ihn, wie er auf 28d/28e den Text faerbt. Gruen beim gewonnenen
   Wurf, Warnorange beim verlorenen — dieselbe Zuordnung wie oben, nur an dem
   Wert von `data-auftakt`, den das Ergebnis traegt. */
.auftakt[data-auftakt='gewonnen'] .auftakt__balkenlauf {
  background: var(--gruen-text);
}

.auftakt[data-auftakt='verloren'] .auftakt__balkenlauf {
  background: var(--warn-icon);
}

/* WI-0208 — derselbe Fuss auf dem Vergleich (32/34, §22.2), nur 1,4 s statt
   1,6 s lang. Er steht in der Partie und nicht im Auftakt, deshalb bekommt er
   die zweite Klasse und nicht eine Kopie des Bauteils. */
.partie__fuss .auftakt__balkenlauf {
  animation-duration: var(--partie-balken-dauer);
}

[data-partie='vergleich-sieg'] .auftakt__balkenlauf {
  background: var(--gruen-text);
}

[data-partie='vergleich-niederlage'] .auftakt__balkenlauf {
  background: var(--warn-icon);
}

.auftakt__fuss .meta {
  margin: var(--space-3) 0 0;
}

/* Der Lauf des Balkens (HANDOFF §14). */
@keyframes cs-startbar {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

/* DER FLUG EINER PARTIENACHRICHT (HANDOFF §5.5b3, Artboard 31c).
   Quer ueber den Schirm, von -118 % nach 118 %, mit einer Neigung von -3° auf
   3°; eingeblendet ueber die ersten 10 %, ausgeblendet ueber die letzten 10 %.
   Die Dauer steht am Bauteil (4,4 s / 5,2 s je Spur), nicht hier. */
@keyframes cs-fly {
  0% {
    transform: translateX(-118%) rotate(calc(-1 * var(--nachricht-neigung)));
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    transform: translateX(118%) rotate(var(--nachricht-neigung));
    opacity: 0;
  }
}

/* Und die Wippe darin — ±5 px in 1,6 s, „so it does not read as a ticker".
   Sie sitzt auf der Pille und nicht auf der Spur: zwei getrennte Bewegungen,
   damit keine die andere ueberschreibt. */
@keyframes cs-bob {
  0%,
  100% {
    transform: translateY(calc(-1 * var(--nachricht-wippe-weg)));
  }
  50% {
    transform: translateY(var(--nachricht-wippe-weg));
  }
}

/* Die ruhige Fassung derselben Pille (§5.5b3, `prefers-reduced-motion`): sie
   blendet oben mittig ein und wieder aus, ohne zu reisen und ohne zu wippen. */
@keyframes cs-einblenden {
  0%,
  100% {
    opacity: 0;
  }
  12%,
  88% {
    opacity: 1;
  }
}

@keyframes cs-pop {
  0% {
    transform: scale(0.86);
    opacity: 0;
  }
  45% {
    transform: scale(1.04);
    opacity: 1;
  }
  70% {
    transform: scale(0.99);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
 * Das Ergebnis — die Siegesanimation laeuft NUR beim eigenen Sieg
 * (Designspec 7.2, letzter Absatz)
 * ------------------------------------------------------------------------ */

.duell-ergebnis__buehne {
  position: relative;
  /* 150 px wie im Entwurf (Artboard 38), nicht 220: die 70 px Unterschied
     waren genau das, was `39-match-result-lost-borrowed` unter die Falz
     geschoben hat. Die Funken sitzen absolut zum Mittelpunkt und wandern
     weiter nach aussen — sie brauchen die Flaeche nicht. */
  width: 150px;
  height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.duell-ergebnis__ring {
  /* Der Entwurf: 150 px und 3 px Rand beim Sieg (38), 130 px und 2 px in der
     Niederlage (39) — die Niederlage ist auch in der Groesse leiser. */
  width: 130px;
  height: 130px;
  border-radius: var(--radius-pille);
  border: 2px solid var(--niederlage-farbe);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Haken im Sieg, neutrales Kreuz in der Niederlage (Artboards 38/39). Grau,
   nie rot: „Verlieren wird gesagt, nicht bestraft" (HANDOFF §7.9). */
.duell-ergebnis__glyphe {
  width: 56px;
  height: 56px;
  color: var(--niederlage-farbe);
  stroke-linecap: round;
  stroke-linejoin: round;
}

[data-ergebnis='sieg'] .duell-ergebnis__glyphe {
  color: var(--sieg-farbe);
}

[data-ergebnis='sieg'] .duell-ergebnis__ring {
  width: 150px;
  height: 150px;
  border-width: 3px;
  border-color: var(--sieg-farbe);
  background: var(--gruen-flaeche);
  box-shadow: var(--ergebnis-ring-schein);
}

/* Funken: ein 0x0-Arm, um den Punkt herum gedreht (Designspec 7.2 „Spark
   construction") — der Punkt selbst reist am Arm entlang nach aussen. */
.duell-funke {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  transform-origin: 0 0;
  transform: rotate(var(--duell-winkel));
}

.duell-funke::after {
  content: '';
  position: absolute;
  top: 0;
  left: -2.5px;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pille);
  background: var(--sieg-farbe);
  box-shadow: 0 0 6px rgba(var(--sieg-farbe-glow), 0.7);
  animation: cs-spark var(--duell-funke-eigen-dauer) ease-out infinite;
  animation-delay: var(--duell-verzoegerung);
}

/* Sterne: auf einem Kreis platziert, radial nach aussen gestaffelt
   (Designspec 7.2 „Stars sit on a circle"). */
.duell-stern {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  transform: rotate(var(--duell-stern-winkel)) translate(var(--duell-stern-radius)) scaleY(1.25);
  color: var(--sieg-stern-hell);
  animation: cs-star var(--duell-stern-eigen-dauer) ease-in-out infinite;
}

.duell-stern::before {
  content: '★';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
}

/* ==========================================================================
 * QUERFORMAT — DER FOTOGRAFIER-WEG UND SONST NICHTS (WI-0334)
 * ==========================================================================
 *
 * `design/handoffs/ux-2026-10-10/HANDOFF-PATCH.md` §24.7, vier Artboards im
 * Brett `design/Carspotter App.dc.html`, Abschnitt „2b · Finden quer":
 *
 *     07l-scan-viewfinder-landscape    793 x 393
 *     08l-scan-recognising-landscape   793 x 393
 *     09l-scan-no-car-landscape        793 x 393
 *     13l-card-new-landscape           793 x 393
 *
 * JEDE ZAHL IN DIESEM ABSCHNITT IST EINE ZAHL AUS DIESEN VIER RAHMEN. Sie
 * sind absolut auf 793 x 393 gezeichnet; uebernommen sind sie als EINRUECKUNGEN
 * von den Kanten, nicht als feste Groessen — dann sitzt die Anordnung auf dem
 * gezeichneten Mass genau und waechst mit jedem anderen Querformat mit.
 *
 * ES GIBT HIER KEINE `@media (orientation: landscape)`, UND DAS IST DER KERN
 * DER SACHE. Eine Media Query gilt fuer JEDEN Bildschirm — Garage, Duell und
 * Konto wuerden mitdrehen, und genau das verbietet §24.7. Gehangen wird
 * deshalb an `[data-ausrichtung='quer']`, und das setzt `zeichne()` in
 * public/js/app.js nur fuer die vier Zustaende, die der Export zeichnet
 * (`QUER_SLUGS` / `querSlug()` dort). Wer Querformat auf einen fuenften
 * Bildschirm ausdehnen will, braucht erst ein Artboard.
 *
 * DER ENTWURF ZEICHNET DIE KAMERA LINKS (§24.7, „Layout"): 48 px Schutzzone
 * an der linken Kante, die Bedienelemente in einer 128-px-Spalte rechts unter
 * dem Daumen. Liegt das Handy andersherum, wandert die Schutzzone an die
 * rechte Kante — die Anordnung wird NICHT gespiegelt, der Ausloeser bleibt
 * rechts. Deshalb steht hier kein `direction`- und kein Spiegel-Fall.
 * ------------------------------------------------------------------------ */

/* DER ZWEITE SELEKTOR IST KEINE DOPPELUNG, SONDERN DER GRUND, WARUM DIESE
   REGEL UEBERHAUPT GILT — und er ist gemessen, nicht vermutet.

   Der Sucher traegt hochkant eine eigene Polsterregel fuer den Fall, dass der
   Reihenstreifen steht: `.app__buehne[data-bildschirm='scannen']:has(.reihe)`
   setzt `padding-top: --reihe-oben` (12 px, Artboard 07b). Durch das `:has()`
   wiegt sie (0,3,0) und schlaegt eine Regel mit (0,2,0) — unabhaengig davon,
   welche weiter unten steht. Und quer steht der Streifen IMMER, weil `07l` die
   drei Plaetze selbst zeichnet: ohne diese zweite Zeile sitzt der ganze Rahmen
   12 px zu tief, und genau so wurde es im Browser nachgemessen (78 statt 66).

   Deshalb dieselbe Gewichtsklasse statt eines `!important`: `!important`
   verdeckte den Grund und waere beim naechsten `:has()` wieder falsch. */
.app__buehne[data-ausrichtung='quer'],
.app__buehne[data-ausrichtung='quer']:has(.reihe) {
  /* Die Querformat-Rahmen zeichnen ihre Masse von der ROHEN Kante aus; das
     allgemeine Polster der Buehne kaeme sonst oben drauf und verschoebe jede
     Zahl dieses Abschnitts. Die Schutzzone des Geraets bleibt: `env()` ist 0,
     wo es keine gibt. */
  padding: 0;
  gap: 0;
  max-width: none;
  /* 48 px Schutzzone an der linken Kante (§24.7). Liegt das Geraet
     andersherum, meldet der Browser sie rechts — beides kommt an, gespiegelt
     wird nichts. */
  padding-left: max(var(--quer-schutz), var(--sicher-links));
  padding-right: var(--sicher-rechts);
}

/* --------------------------------------------------------------------------
 * 07l — der Sucher
 *
 * Der Rahmen nimmt fast die ganze Flaeche: `left:58px; right:128px; top:66px;
 * bottom:50px` im Artboard. Die 58 sind die 48 px Schutzzone plus 10 px
 * Innenabstand; da die Schutzzone an der Buehne haengt, bleiben hier 10.
 * ------------------------------------------------------------------------ */

.app__buehne[data-ausrichtung='quer'] .scan {
  position: relative;
  display: block;
  flex: 1;
  min-height: 0;
}

/* Der Sucher selbst — keine feste Hoehe mehr, sondern die Flaeche zwischen
   den vier Einrueckungen des Artboards. `--sucher-hoehe` (236 px, Artboard 07)
   ist die HOCHKANTE Zahl und gilt hier nicht; was beide Lagen verbindet, ist
   nicht das Mass, sondern die Regel darunter: was der Sucher zeigt, bekommt
   die Karte (Produktspec 4.2). Die haelt `coverAusschnitt()` in
   public/js/camera.js ein, und zwar GERECHNET aus dem gemessenen Kasten — der
   Zuschnitt stimmt deshalb in jeder Lage, ohne dass hier eine Zahl davon
   wuesste. */
.app__buehne[data-ausrichtung='quer'] .scan > .sucher {
  position: absolute;
  left: var(--quer-rand-innen);
  /* WI-0341: `right:176px` statt 128 — der Rahmen rueckt um die Breite der
     Zoom-Spalte ein, die links neben der Bedienspalte liegt. */
  right: var(--quer-rand-rechts);
  top: var(--quer-sucher-oben);
  bottom: var(--quer-sucher-unten);
  width: auto;
  height: auto;
  margin: 0;
}

/* Die Hinweispille: `left:112px; right:176px; top:16px`, mittig in dem, was
   bleibt — 112 sind die 58 des Rahmens plus die 54, die das Kreuz samt Fuge
   braucht; die 176 rechts sind seit WI-0341 die Bedienspalte plus die
   Zoom-Spalte. */
.app__buehne[data-ausrichtung='quer'] .scan > .hinweis-pille {
  position: absolute;
  left: calc(var(--quer-rand-innen) + var(--quer-kreuz) + var(--space-2));
  right: var(--quer-rand-rechts);
  top: var(--quer-pille-oben);
  margin: 0;
  width: max-content;
  max-width: calc(100% - var(--quer-rand-rechts) - var(--quer-rand-innen) - var(--quer-kreuz));
  margin-inline: auto;
  z-index: 1;
}

/* DER ZAEHLER QUER (WI-0426, Artboards 07l/07ld): oben rechts, `right:20px;
   top:16px; min-height:40px`, der Balken 64 statt 96 px. */
.app__buehne[data-ausrichtung='quer'] .scan > .scan-zaehler {
  position: absolute;
  right: var(--zaehler-rechts-quer);
  top: var(--quer-pille-oben);
  min-height: var(--zaehler-hoehe-quer);
  margin: 0;
  z-index: 1;
}

.app__buehne[data-ausrichtung='quer'] .scan > .scan-zaehler .scan-zaehler__leiste {
  width: var(--zaehler-leiste-b-quer);
}

/* DER SATZ UNTER DEM AUSLOESER QUER — VORLAEUFIG. `07ld` zeichnet ihn nicht,
   und `07w` gibt es quer nicht. Er steht in der Bedienspalte unter dem
   Knopf, klein, damit er nicht in den Rahmen laeuft (Luecke im Bericht). */
.app__buehne[data-ausrichtung='quer'] .scan > .scan__ausloeser-satz {
  position: absolute;
  right: 0;
  top: calc(50% + var(--quer-ausloeser-versatz) + var(--ausloeser) / 2 + var(--ausloeser-satz-fuge));
  width: var(--quer-spalte);
  margin: 0;
  font-size: var(--schrift-abschnitt);
  z-index: 1;
}

/* Das Kreuz oben links: 44 x 44, `left:58px; top:12px` (Artboard 07l). */
.app__buehne[data-ausrichtung='quer'] .scan__schliessen {
  position: absolute;
  left: var(--quer-rand-innen);
  top: var(--quer-kreuz-oben);
  width: var(--quer-kreuz);
  height: var(--quer-kreuz);
  border-radius: 50%;
  background: var(--tableiste-flaeche);
  border: var(--pille-strich) solid var(--cs-line-2);
  color: var(--raum-text-gedaempft);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  z-index: 1;
}

.app__buehne[data-ausrichtung='quer'] .scan__schliessen .ikone {
  width: var(--quer-kreuz-ikone);
  height: var(--quer-kreuz-ikone);
}

/* Die Warnzeile: `left:58px; right:176px; bottom:12px` — unter dem Rahmen und
   links von Zoom- und Bedienspalte, nicht unter ihnen. */
.app__buehne[data-ausrichtung='quer'] .scan__warnung {
  position: absolute;
  left: var(--quer-rand-innen);
  right: var(--quer-rand-rechts);
  bottom: var(--quer-warnung-unten);
  margin: 0;
  justify-content: center;
}

/* --------------------------------------------------------------------------
 * 07l — die Zoom-Spalte (WI-0341)
 *
 * `right:128px; top:66px; bottom:50px; width:48px` im Artboard: eine eigene
 * Spalte LINKS neben der Bedienspalte, auf der Hoehe des Rahmens. `Nah` oben,
 * `Weit` unten — und zwar in dieser Richtung, weil der Daumen quer an der
 * rechten Kante liegt und das nahe Ende dort hinaufzieht.
 *
 * DIESELBEN VIER TEILE WIE HOCHKANT, NUR AUF DER ANDEREN ACHSE. Gedreht wird
 * nichts: die Spur steht senkrecht, der gefuellte Teil waechst von UNTEN
 * (dem weiten Ende), der Griff sitzt auf seinem oberen Ende. Nur das
 * Bedienelement selbst braucht `writing-mode: vertical-rl` — ein
 * `input[type=range]` kennt keine andere Art, senkrecht zu laufen —, und
 * `direction: rtl` dreht es so, dass `min` UNTEN liegt. Nachgemessen im
 * Browser: Klick oben ergibt `max`, Klick unten `min`.
 *
 * DIE BESCHRIFTUNG WECHSELT DIE SEITEN, NICHT DEN TEXT. Hochkant steht sie als
 * Zeile UNTER der Spur, quer klammert sie die Spalte ein. `display: contents`
 * loest dafuer den Huellknoten auf, statt ihm eine zweite Anordnung
 * beizubringen; die Reihenfolge macht `order`, damit im Markup ueberall
 * dieselbe steht (`Weit` zuerst — so liest das Hochformat).
 * ------------------------------------------------------------------------ */
.app__buehne[data-ausrichtung='quer'] .scan > .scan__zoom {
  position: absolute;
  right: var(--quer-spalte);
  top: var(--quer-sucher-oben);
  bottom: var(--quer-sucher-unten);
  width: var(--quer-zoom-spalte);
  align-items: center;
  padding: 0;
  gap: var(--quer-zoom-luecke);
  z-index: 1;
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-beschriftung {
  display: contents;
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-ende {
  font-size: var(--quer-zoom-schrift);
}

/* `Nah` oben, Spur, `Weit` unten. Im Markup steht `Weit` zuerst. */
.app__buehne[data-ausrichtung='quer'] .scan__zoom-ende:last-child {
  order: 1;
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-feld {
  order: 2;
  flex: 1;
  width: var(--scan-zoom-flaeche);
  height: auto;
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-ende:first-child {
  order: 3;
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-spur {
  left: 50%;
  right: auto;
  top: 0;
  bottom: 0;
  width: var(--scan-zoom-spur);
  height: auto;
  margin: 0 0 0 calc(var(--scan-zoom-spur) / -2);
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-gefuellt {
  left: 50%;
  top: auto;
  bottom: 0;
  width: var(--scan-zoom-spur);
  height: var(--zoom-anteil, 0%);
  margin: 0 0 0 calc(var(--scan-zoom-spur) / -2);
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-griff {
  left: 50%;
  top: auto;
  bottom: var(--zoom-anteil, 0%);
  margin: 0 0 calc(var(--scan-zoom-griff) / -2) calc(var(--scan-zoom-griff) / -2);
}

.app__buehne[data-ausrichtung='quer'] .scan__zoom-regler {
  writing-mode: vertical-rl;
  direction: rtl;
}

/* Die Bedienspalte rechts: 128 px breit, ueber die ganze Hoehe, der Inhalt
   mittig mit 22 px Fuge — drei Plaetze (52 x 34, Fuge 6) ueber dem Ausloeser
   (76 px, 4 px Rand).
 *
 * Gerechnet statt gestapelt: die Mitte der GRUPPE liegt auf 50 %, der
 * Plaetzeblock sitzt (22 + 84) / 2 = 53 px darueber, der Ausloeser
 * (22 + 114) / 2 = 68 px darunter. So braucht keiner von beiden einen
 * zusaetzlichen Huellknoten, und die Gruppe bleibt mittig, auch wenn der
 * Rahmen hoeher oder niedriger ist als die gezeichneten 393 px. */
.app__buehne[data-ausrichtung='quer'] .scan > .reihe,
.app__buehne[data-ausrichtung='quer'] .scan > .ausloeser {
  position: absolute;
  right: 0;
  width: var(--quer-spalte);
  margin: 0;
  z-index: 1;
}

.app__buehne[data-ausrichtung='quer'] .scan > .reihe {
  top: 50%;
  transform: translateY(calc(-50% - var(--quer-reihe-versatz)));
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  justify-content: center;
}

/* Die drei Plaetze stehen quer UNTEREINANDER und in dem Mass des Artboards
   (52 x 34 statt 58 x 44 hochkant). */
.app__buehne[data-ausrichtung='quer'] .scan > .reihe .reihe__plaetze {
  flex-direction: column;
  gap: var(--quer-platz-luecke);
}

.app__buehne[data-ausrichtung='quer'] .scan > .reihe .reihe__platz {
  width: var(--quer-platz-b);
  height: var(--quer-platz-h);
  border-radius: var(--quer-platz-radius);
}

/* Die Zeile unter den Plaetzen zeichnet `07l` nicht: in der 128-px-Spalte
   haette sie keine Breite, und der Streifen ist hier eine Anzeige, kein Satz.
   Was sie hochkant sagt, bleibt hochkant. */
.app__buehne[data-ausrichtung='quer'] .scan > .reihe .reihe__zeile {
  display: none;
}

.app__buehne[data-ausrichtung='quer'] .scan > .ausloeser {
  top: 50%;
  transform: translateY(calc(-50% + var(--quer-ausloeser-versatz)));
  margin-inline: auto;
  left: auto;
  right: calc((var(--quer-spalte) - var(--ausloeser)) / 2);
  width: var(--ausloeser);
}

/* --------------------------------------------------------------------------
 * 08l und 09l — Erkennung und „kein Auto", zwei Spalten
 *
 * „Kreis links, Schritte rechts" (§24.7). Im Artboard: die Buehne in einer
 * 300-px-Spalte ab `left:58px`, die Textspalte `left:378px; right:40px`,
 * beide senkrecht mittig.
 * ------------------------------------------------------------------------ */

.app__buehne[data-ausrichtung='quer'] .lauf {
  /* WI-0366 — DIE TEXTSPALTE IST EINE SPALTE, NICHT VIER. Titel, Unterzeile,
     Schritte und Aktionsblock sind im Bauteil Geschwister der Buehne (der
     hochkante Weg stapelt sie, public/js/app.js `scanLaeuftBildschirm` und
     `scanFehlerBildschirm`). Bis WI-0366 drehte hier `flex-direction: row` die
     GANZE Reihe: jedes Geschwister wurde eine eigene, schmale Spalte, der
     Aktionsblock stand bei x = 876 jenseits der 793 px, und die Messung meldete
     `rand_rechts` 485 bzw. 507 gegen 214 bzw. 194 (die einzige breite Flaeche
     war die Buehne selbst). Deshalb bleibt die Seite eine Spalte — die
     Textspalte ab 378 bis 40 vor der Kante, senkrecht mittig — und nur die
     Buehne tritt aus ihr heraus in die linke 300-px-Spalte. */
  position: relative;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding-left: calc(var(--quer-rand-innen) + var(--quer-lauf-spalte) + var(--quer-lauf-fuge));
  padding-right: var(--quer-text-rand);
  text-align: left;
}

/* Die Buehne behaelt ihre 250 px, steht mittig in der 300-px-Spalte ab 58
   (`left:58px; width:300px; justify-content:center` im Artboard, also bei 83)
   und senkrecht mittig. Kein `transform` dafuer: die Ringe darin laufen selbst
   ueber `transform`, und die Buehne soll keine zweite Ebene dazu bekommen. */
.app__buehne[data-ausrichtung='quer'] .lauf .lauf__buehne {
  position: absolute;
  left: calc(var(--quer-rand-innen) + (var(--quer-lauf-spalte) - var(--lauf-buehne)) / 2);
  top: calc(50% - var(--lauf-buehne) / 2);
  margin: 0;
}

/* Alles, was nicht die Buehne ist, steht rechts davon und linksbuendig — der
   Entwurf zentriert quer keinen Satz. `.mittig` steht hochkant an der
   Unterzeile und am Kleingedruckten; hier wird es ueberstimmt statt im Bauteil
   weggelassen, damit der hochkante Weg unberuehrt bleibt. */
.app__buehne[data-ausrichtung='quer'] .lauf .lauf__titel,
.app__buehne[data-ausrichtung='quer'] .lauf .mittig {
  text-align: left;
}

/* Der Aktionsblock steht quer NICHT unten verankert, sondern unter den
   Schritten in derselben Spalte (`align-self: flex-start` im Artboard, Knopf
   mit `min-width`). `margin-top: auto` wuerde ihn an den Fuss der Zeile
   schieben und die Spalte auseinanderziehen. */
.app__buehne[data-ausrichtung='quer'] .lauf .aktionsblock {
  margin-top: 0;
  padding-top: var(--space-4);
  align-items: flex-start;
}

.app__buehne[data-ausrichtung='quer'] .lauf .aktionsblock .btn {
  width: auto;
  min-width: var(--quer-knopf-min);
}

.app__buehne[data-ausrichtung='quer'] .lauf[data-lauf='fehler'] .aktionsblock .btn {
  min-width: var(--quer-knopf-min-nochmal);
}

/* --------------------------------------------------------------------------
 * 13l — die neue Karte
 *
 * „Die Karte bleibt hochkant, links, verkleinert" (screens.json `13l`). Das
 * KARTENFORMAT aendert sich nicht — 59:91, Kartenspec; nur die Breite wird
 * kleiner gerechnet, damit die Karte in die 393 px Hoehe passt. Im Artboard
 * sitzt sie `left:96px; top:56px` in einem Kasten von 198 x 282, die
 * Textspalte `left:350px; right:44px`.
 * ------------------------------------------------------------------------ */

.app__buehne[data-ausrichtung='quer'] .wurf--quer {
  /* WI-0366: `display` steht hier selbst. Hochkant traegt die Seite die
     Klasse `gestapelt` (und mit ihr `display: flex`); der quere Zweig in
     public/js/app.js baut sie ohne — bis WI-0366 griff `flex-direction: row`
     deshalb auf einen Block, Karte und Textspalte standen UNTEREINANDER, und
     die Seite lief 126 px ueber die 393 px hinaus (`ueber_falz` 126 gegen 0). */
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: var(--quer-wurf-fuge);
  padding: var(--quer-wurf-oben) var(--quer-wurf-rechts) var(--quer-wurf-oben)
    var(--quer-wurf-links);
  /* Hochkant rechnet `--kw-breite` die Karte gegen die Hoehe der Seite samt
     allem, was darunter steht (`--kw-umfeld`). Quer steht nichts darunter,
     sondern daneben — das Umfeld ist deshalb nur das Polster oben und unten.
     Die Formel selbst bleibt dieselbe und damit das Format. */
  --kw-umfeld: calc(var(--quer-wurf-oben) * 2);
}

.app__buehne[data-ausrichtung='quer'] .wurf--quer .karte-buehne {
  flex: none;
  margin-block: 0;
  align-items: center;
}

.app__buehne[data-ausrichtung='quer'] .wurf__spalte {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2);
  text-align: left;
}

.app__buehne[data-ausrichtung='quer'] .wurf__titel {
  margin: 0;
  text-align: left;
}

.app__buehne[data-ausrichtung='quer'] .wurf__zeile {
  margin: 0;
  text-align: left;
}

/* Zwei Knoepfe, `Weiter fotografieren` zuerst — die Reihenfolge steht im Bauteil
   (public/js/app.js), nicht hier. Der Block ist im Artboard auf 300 px
   begrenzt und steht nicht unten verankert. */
.app__buehne[data-ausrichtung='quer'] .wurf__aktionen {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
  max-width: var(--quer-wurf-knopf-max);
}

@media (prefers-reduced-motion: reduce) {
  .karte,
  [data-wisch],
  [data-wisch][data-fliegt],
  [data-wisch][data-einflug],
  .wertzeile,
  .karte__halo,
  .schritt__zeichen,
  /* Die Erkennungs-Buehne steht still (HANDOFF §14: „respect
     prefers-reduced-motion"). Die Schrittliste sagt ohnehin in Worten, was
     gerade laeuft — die Ringe, die Spur und der Lichtstrich sind Schmuck. */
  .lauf__ring,
  .lauf__spur .silhouette,
  .lauf__strich,
  .punkte > span,
  .duell-funke::after,
  .duell-stern,
  /* Der Kreisel steht still — der Satz daneben sagt ohnehin, worauf gewartet
     wird (WI-0073). */
  .kreisel,
  /* 45d: der drehende Bogen ist Schmuck, und HANDOFF §5.5f schreibt es
     ausdruecklich aus („the ring does not rotate"). Was der Bildschirm SAGT,
     bleibt vollstaendig stehen: Ueberschrift, Umfang und der Satz, dass ab
     hier nichts mehr abzubrechen ist. Der Bogen behaelt seine Farbe und bleibt
     sichtbar — er verschwindet nicht, er steht nur still. */
  .loeschlauf__bogen,
  /* 45e: der Weiterleitungsbalken laeuft nicht, sondern steht VOLL da —
     HANDOFF §5.5f schreibt es aus („the forwarding bar is static with the same
     4 s dwell"). Die Frist bleibt dabei unveraendert: sie haengt an
     `LOESCHFERTIG_MS` in public/js/app.js und nicht an dieser Animation. Der
     Balken verschwindet nicht — er ist ohne Lauf einfach ganz gefuellt (der
     Ausgangswert von `cs-startbar` ist 100 % Breite). */
  .loeschfertig__balkenlauf,
  .auftakt__buehne,
  /* 28d/28e: Reif, Aussage und der Balkenlauf sind Schmuck. Der Bildschirm
     geht trotzdem weiter — die Frist steht in public/js/app.js und haengt an
     der Uhr, nicht an dieser Animation. Genau deshalb darf sie hier
     ersatzlos abgeschaltet werden. */
  .auftakt__reif,
  .auftakt__aussage,
  .auftakt__balkenlauf,
  /* Die Partiezustaende 33/35/36: Ringe, wandernde Karten, Funken und der
     fallende Topf sind Schmuck. Was geschehen ist, steht in der Urteilszeile
     und im Satz darunter — beide bleiben stehen. Die Karten muessen dabei
     ausdruecklich SICHTBAR bleiben: cs-toMe und cs-toThem enden bei
     `opacity:0`, ohne Lauf gilt der Anfangswert, und der ist 1. */
  .partie__ring,
  .partie__zwei--bewegt > *,
  .partie__funken > span,
  /* WI-0208: die Aufdeckung auf 31 ist ebenfalls Schmuck. Sie darf hier
     ausfallen, WEIL der Uebergang an der Uhr haengt und nicht an ihr — sonst
     stuende ein Bildschirm ohne Knopf still (app.js `pflegeStrecke`). Ohne
     Lauf gilt der Anfangswert: die Rueckseite bleibt schlicht liegen. */
  .partie__rueckseite[data-aufdecken='laeuft'],
  .partie__topfkarte {
    transition: none;
    animation: none;
  }

  /* WI-0214 — 31c: kein Flug und keine Wippe. §5.5b3 schreibt den Ersatz
     ausdruecklich aus: „the pill fades in centred at the top for 2.5 s and
     fades out". Die Pille verschwindet dabei NICHT von selbst — sie haengt an
     derselben Uhr wie sonst (app.js `pflegeNachrichtenflug`), und genau
     deshalb darf die Bewegung hier ersatzlos ausfallen. */
  .partie__nachrichtenspur,
  .partie__nachrichtenspur[data-spur='0'],
  .partie__nachrichtenspur[data-spur='1'] {
    top: var(--nachricht-ruhig-oben);
    text-align: center;
    animation: cs-einblenden var(--nachricht-ruhig-dauer) ease-in-out 1 both;
  }

  .partie__nachricht {
    animation: none;
  }

  /* Ohne Bewegung bleibt die gewischte Karte stehen, statt uebergangslos aus
     dem Bild zu springen: sonst waere die Flaeche fuer die Ausstiegszeit leer
     und der Wechsel ein Flackern. Sie wird nach dieser Zeit schlicht
     ausgetauscht. */
  [data-wisch][data-fliegt] {
    transform: none;
  }
}

/* WI-0419: Diagnosezeile am Detektor-Fehlerblatt (nur in der App). */
.fehler__diagnose {
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
 * Datenschutzerklaerung und Impressum (WI-0423)
 *
 * Eigene Seiten unter /datenschutz und /impressum, ausgeliefert von
 * src/routes/rechtliches.js. Es gibt dafuer KEIN Artboard (als Designluecke
 * gemeldet): schlichter Fliesstext, nur Groessen aus tokens.css und den
 * Grundregeln oben. Die Systemraender gelten auch hier — die Seite oeffnet
 * aus der iOS-App heraus (WI-0417).
 * ------------------------------------------------------------------------ */
.rechtsseite__inhalt {
  max-width: var(--buehne-max);
  margin: 0 auto;
  padding: calc(var(--space-6) + var(--sicher-oben)) calc(var(--space-4) + var(--sicher-rechts))
    calc(var(--space-8) + var(--sicher-unten)) calc(var(--space-4) + var(--sicher-links));
}

.rechtsseite h1 {
  margin-bottom: var(--space-3);
}

.rechtsseite h2 {
  margin: var(--space-6) 0 var(--space-2);
}

.rechtsseite p,
.rechtsseite ul {
  margin: 0 0 var(--space-3);
}

.rechtsseite ul {
  padding-left: var(--space-4);
}

.rechtsseite li + li {
  margin-top: var(--space-2);
}

.rechtsseite a {
  color: var(--color-accent);
}

.rechtsseite__kopf {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  font-size: var(--schrift-klein);
}

.rechtsseite__platzhalter {
  padding: var(--space-3);
  margin-bottom: var(--space-3);
  border: var(--karte-rand) dashed var(--cs-line-2);
  border-radius: var(--radius-md);
  background: var(--cs-fill-1);
}

.rechtsseite__marke,
.rechtsseite__stand {
  color: var(--cs-text-2);
  font-size: var(--schrift-klein);
}

/* Die beiden Verweise im Anmeldefuss (00) und am Kontofuss (43). */
.rechtsverweise {
  margin: 0;
  text-align: center;
  font-size: var(--schrift-klein);
  color: var(--cs-text-2);
}

.rechtsverweise a {
  color: inherit;
}

.anmeldefuss__note a {
  color: inherit;
}

/* Unter `43-account` direkt am Fuss: der Abstand des Stapels (`.konto` gap)
   wuerde die Seite auf 45 (Abmelden-Blatt) ueber die Falz schieben. */
.konto > .rechtsverweise {
  margin-top: calc(var(--space-1) - var(--space-4));
  line-height: var(--zeilenhoehe-heading);
}
