/* ══════════════════════════════════════════════════════════════════════════
   BattleBox — Bausteine nach Brand System V1.0
   Jeder Block nennt seine Quelle im Brand Guide.

   Zwei Regeln stehen über allem und erklären fast jede Entscheidung hier:
   – Nur die sieben Palettenwerte. Kein Zwischenton, kein eigenes Grau.
   – Diagonalen nur auf 22,5° und 45°. Horizontal und vertikal sind Struktur.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Schrift ─────────────────────────────────────────────── Guide S. 11 ── */

@font-face {
  font-family: "Quicky Nick";
  src: url("schrift/QuickyNick.woff2") format("woff2");
  font-weight: 400 700;
  font-display: block;
}
@font-face {
  font-family: "Quicky Nick";
  src: url("schrift/QuickyNickItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 400 700;
  font-display: block;
}
@font-face {
  font-family: "Titillium Web";
  src: url("schrift/TitilliumWeb-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: "Titillium Web";
  src: url("schrift/TitilliumWeb-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-display: block;
}
@font-face {
  font-family: "Titillium Web";
  src: url("schrift/TitilliumWeb-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: block;
}
@font-face {
  font-family: "Saira";
  src: url("schrift/Saira.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 50% 125%;
  font-display: block;
}

/* ── Token ───────────────────────────────────────── Guide S. 08, 09, 11 ── */

:root {
  /* Palette. „Die Werte dürfen nicht abgeändert werden!" (S. 08) */
  --cyan: #00e8ff;
  --pink: #ff1493;
  --lime: #dbff00;
  --weiss: #ffffff;
  --steel: #a6a7a7;
  --graphit: #1f1f21;
  --schwarz: #000000;

  /* Rollen (S. 09) */
  --team-a: var(--cyan);
  --team-b: var(--pink);
  --cta: var(--lime);
  --buehne: var(--schwarz);
  --panel: var(--graphit);

  /* Text auf Farbe (S. 10) — nie Weiß auf Cyan oder Lime */
  --auf-cyan: var(--schwarz);
  --auf-lime: var(--schwarz);
  --auf-pink: var(--schwarz);

  /* Schrift */
  --display: "Quicky Nick", "Saira", system-ui, sans-serif;
  --body: "Titillium Web", system-ui, sans-serif;
  --label: "Saira", "Titillium Web", system-ui, sans-serif;

  /* Geometrie (S. 03, 16) */
  --cut: 24px;
  --rail: 5px;
  --pad: 28px;

  /* Die drei Zahlen der 3-Meter-Regel */
  --tap: 96px;
  --min-schrift: 28px;
}

/* ── Grundlage ────────────────────────────────────────────────────────── */

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--schwarz);
  color: var(--weiss);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/*
 * Die Bühne hat die Maße des Wand-Tablets und wird als Ganzes skaliert.
 * So ist der Entwurf auf jedem Monitor derselbe wie auf dem Gerät — und
 * jede Größenangabe im Entwurf ist eine echte Gerätepixelangabe, keine
 * relative Schätzung.
 */
#buehne {
  position: relative;
  width: 1194px;
  height: 834px;
  background: var(--buehne);
  overflow: hidden;
  transform-origin: top left;
}

.schirm {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
}
.schirm.an {
  display: flex;
}

/* ── Arena Grid ──────────────────────────────────────────── Guide S. 14 ──
   „Subtiles Raster für Hintergründe." Es trägt nicht, es strukturiert.
   Steel auf 6 % — sichtbar genug, dass die Fläche Tiefe bekommt, schwach
   genug, dass es nie mit Inhalt verwechselt wird.                       */

.arena-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgb(166 167 167 / 6%) 1px, transparent 1px),
    linear-gradient(to bottom, rgb(166 167 167 / 6%) 1px, transparent 1px);
  background-size: 96px 96px;
}

/* Special Grid: dichteres Raster mit Kreuzmarken, für ruhige Flächen */
.special-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle, rgb(166 167 167 / 14%) 1px, transparent 1.5px);
  background-size: 32px 32px;
}

/* ── Speed Lines ─────────────────────────────────────────── Guide S. 14 ──
   „Diagonale Linien für Richtung, Übergang und Bewegung."
   45 Grad, weil Prinzip 1 keine andere Diagonale kennt.                 */

.speed-lines {
  position: absolute;
  inset: -20%;
  pointer-events: none;
  background: repeating-linear-gradient(
    45deg,
    transparent 0 44px,
    rgb(166 167 167 / 8%) 44px 47px
  );
}

/* ── Tri-Signal ──────────────────────────────────────────── Guide S. 14 ──
   „Drei kurze Balken in Cyan/Pink/Lime."
   Die Vorlage steht auf 37,5 Grad; hier auf 45 gebracht, weil Prinzip 1
   Vorrang vor der Vorlage hat.                                          */

.tri-signal {
  display: flex;
  gap: 0;
  height: var(--h, 14px);
}
.tri-signal > i {
  --w: 38px;
  display: block;
  width: calc(var(--w) + var(--h, 14px));
  height: 100%;
  margin-right: 10px;
  clip-path: polygon(var(--h, 14px) 0, 100% 0, calc(100% - var(--h, 14px)) 100%, 0 100%);
}
.tri-signal > i:nth-child(1) { background: var(--cyan); }
.tri-signal > i:nth-child(2) { background: var(--pink); }
.tri-signal > i:nth-child(3) { background: var(--lime); }

/* ── Karte ───────────────────────────────────────────────── Guide S. 16 ──
   „Pflichtform: obere rechte Ecke flach abgeschrägt.
    Keine runden Cards, keine Vollflächen-Glow-Effekte."

   clip-path kennt keine Kontur. Deshalb zwei Ebenen: die äußere trägt die
   Konturfarbe, die innere die Füllung — beide mit derselben Fase.       */

.karte {
  position: relative;
  padding: 1px;
  /*
   * Eine Karte kann auch ein <button> sein — im Notfallmodus sind es vier.
   * Ohne diese Zeile erbt sie die Standard-Schaltflächenfarbe des Browsers,
   * und der Titel steht schwarz auf Graphit: 1,28:1, praktisch unsichtbar.
   */
  color: var(--weiss);
  font-family: inherit;
  text-align: left;
  background: rgb(255 255 255 / 12%);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
}
.karte > .inhalt {
  position: relative;
  height: 100%;
  padding: var(--pad);
  padding-left: calc(var(--pad) + var(--rail));
  background: var(--panel);
  clip-path: polygon(
    0 0,
    calc(100% - var(--cut) + 1px) 0,
    100% calc(var(--cut) - 1px),
    100% 100%,
    0 100%
  );
}
/* Signal Rail: 4–6 px, genau EINE Akzentfarbe */
.karte > .inhalt::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--rail);
  background: var(--akzent, var(--cyan));
}
.karte.team-a { --akzent: var(--cyan); }
.karte.team-b { --akzent: var(--pink); }
.karte.aktiv  { --akzent: var(--lime); }

/* ── Schaltflächen ───────────────────────────────────────── Guide S. 17 ──
   „Primary zieht. Secondary ist Outline. Tertiary bleibt Text-Link.
    Disabled ist nur Zustand, keine eigene Button-Form."

   Alle drei teilen dieselbe Cut-Geometrie: oben rechts und unten links
   angeschnitten. Das ist die Form, an der die Marke wiedererkannt wird.  */

.knopf {
  --h: var(--tap);
  --bevel: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  min-height: var(--h);
  min-width: var(--tap);
  padding: 0 40px;
  border: 0;
  border-radius: 0;
  font-family: var(--label);
  font-size: 30px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
  clip-path: polygon(
    0 0,
    calc(100% - var(--bevel)) 0,
    100% var(--bevel),
    100% 100%,
    var(--bevel) 100%,
    0 calc(100% - var(--bevel))
  );
  transition: transform 100ms cubic-bezier(0.2, 0.9, 0.2, 1);
}

/* Primary: Lime auf Schwarz. Maximal EINE pro Bereich. */
.knopf.primaer {
  background: var(--lime);
  color: var(--auf-lime);
}
/* Secondary: Cyan-Kontur, weißer Text auf Graphit. */
.knopf.sekundaer {
  padding: 4px;
  background: var(--cyan);
}
.knopf.sekundaer > span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 0 36px;
  background: var(--graphit);
  color: var(--weiss);
  clip-path: polygon(
    0 0,
    calc(100% - 26px) 0,
    100% 26px,
    100% 100%,
    26px 100%,
    0 calc(100% - 26px)
  );
}
/* Tertiary: Text mit kurzer Pink-Unterstreichung, keine Box. */
.knopf.tertiaer {
  position: relative;
  padding: 0 12px 18px;
  background: none;
  color: var(--weiss);
  clip-path: none;
}
.knopf.tertiaer::after {
  content: "";
  position: absolute;
  right: 12%;
  bottom: 14px;
  left: 12%;
  height: 6px;
  background: var(--pink);
}
/* Disabled: gleiche Geometrie, Steel, reduzierte Deckkraft. */
.knopf:disabled,
.knopf.aus {
  background: var(--steel);
  color: var(--graphit);
  opacity: 0.45;
  cursor: default;
}
.knopf.sekundaer:disabled > span { color: var(--steel); }
/* Hover nur als Edge-Shift, Focus als 2-px-Cyan-Rahmen. */
.knopf:not(:disabled):hover { transform: translate(-2px, -2px); }
.knopf:not(:disabled):active { transform: translate(1px, 1px); }
.knopf:focus-visible { outline: 2px solid var(--cyan); outline-offset: 4px; }

/* ── Typografie ──────────────────────────────────────── Guide S. 11, 12 ──
   Die Skala des Guide (H1 52–72 pt) ist für Web und Print gerechnet. Auf
   dem Wand-Tablet gelten die Verhältnisse, nicht die Absolutwerte: aus
   drei Metern ist ein 12-pt-Fließtext nicht lesbar. 28 px ist die harte
   Untergrenze für alles Spielrelevante.                                  */

.hero {
  margin: 0;
  font-family: var(--display);
  font-size: 96px;
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}
.titel {
  margin: 0;
  font-family: var(--display);
  font-size: 54px;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
}
.eyebrow {
  font-family: var(--label);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--steel);
}
.fliess {
  font-family: var(--body);
  font-size: var(--min-schrift);
  font-weight: 400;
  line-height: 1.4;
}

/*
 * Zahlen, die sich ändern: Timer, Punktestand, Entfernung.
 * Saira mit tabular-nums. NICHT Quicky Nick — die Schrift hat keine
 * OpenType-Tabelle, ihre Ziffern sind 320 bis 521 Einheiten breit und
 * lassen sich nicht angleichen. Ein Timer springt darin um 47 px (E-056).
 */
.zahl {
  font-family: var(--label);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  line-height: 0.9;
}

/* ── Battle Index ────────────────────────────────────────── Guide S. 14 ──
   „Pfeilmarker für Dynamik und kleine Zahlboxen."
   Hier die Rundenanzeige: welche Runde läuft, welche sind gespielt.      */

.battle-index {
  display: flex;
  align-items: center;
  gap: 12px;
}
.battle-index .marke {
  width: 22px;
  height: 34px;
  background: var(--cyan);
  clip-path: polygon(0 0, 55% 0, 100% 50%, 55% 100%, 0 100%, 45% 50%);
}
.numbox {
  position: relative;
  width: 62px;
  height: 62px;
  background: var(--graphit);
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px));
}
.numbox > b {
  display: block;
  width: 100%;
  font-family: var(--label);
  font-size: 30px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 62px;
  text-align: center;
  color: var(--steel);
}
.numbox::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--steel);
}
.numbox.a::before { background: var(--cyan); }
.numbox.b::before { background: var(--pink); }
.numbox.a > b,
.numbox.b > b { color: var(--weiss); }
.numbox.laeuft { background: var(--lime); }
.numbox.laeuft > b { color: var(--auf-lime); }
.numbox.laeuft::before { background: var(--schwarz); }

/* ── Loading Bar ─────────────────────────────────────────── Guide S. 14 ──
   „Balken in Cyan/Pink/Lime." Hier der Countdown der laufenden Runde.
   Segmente als 45-Grad-Parallelogramme.                                  */

.balken {
  position: relative;
  display: flex;
  gap: 6px;
  height: 34px;
  padding: 0;
  overflow: hidden;
}
.balken > i {
  /*
   * Der 45-Grad-Versatz ist an die Höhe gekoppelt, nicht frei gewählt: bei
   * 45 Grad IST der waagerechte Versatz gleich der Höhe. Und die Segmente
   * müssen breiter sein als dieser Versatz, sonst bleibt vom Parallelogramm
   * nur ein Strich übrig — genau das war der erste Versuch.
   */
  --sw: 52px;
  flex: 0 0 var(--sw);
  height: 100%;
  background: var(--graphit);
  clip-path: polygon(34px 0, 100% 0, calc(100% - 34px) 100%, 0 100%);
  transition: background 160ms linear;
}
.balken > i.voll { background: var(--lime); }
.balken > i.warn { background: var(--pink); }

/* ── Fokusklammern ───────────────────────────────────────── Guide S. 14 ──
   „Zum Hervorheben — auch einfarbig."                                    */

.klammern {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.klammern > i {
  position: absolute;
  width: 46px;
  height: 46px;
  background: var(--akzent, var(--cyan));
  clip-path: polygon(0 0, 100% 0, 100% 6px, 6px 6px, 6px 100%, 0 100%);
}
.klammern > i:nth-child(1) { left: 0; top: 0; }
.klammern > i:nth-child(2) { right: 0; top: 0; transform: scaleX(-1); }
.klammern > i:nth-child(3) { left: 0; bottom: 0; transform: scaleY(-1); }
.klammern > i:nth-child(4) { right: 0; bottom: 0; transform: scale(-1, -1); }

/* ── Spark ───────────────────────────────────────────────── Guide S. 14 ──
   „Treffer, Resultat, Ready, Winner."
   Prinzip 2: Der Spark markiert Treffer, Ergebnis und Aktivierung —
   NICHT jeden Schmuckmoment. Er steht in dieser Datei genau an zwei
   Stellen: Rundensieg und Raumsieg.                                      */

.spark {
  display: block;
  color: var(--lime);
}

/* ── Bewegung ────────────────────────────────────────────────────────────
   Der Brand Guide macht keine Bewegungsvorgaben. Diese Kurven sind eigene
   Festlegung; sie folgen dem Grundsatz, dass Bewegung sich verdienen muss.
   Der Standard ist der harte Schnitt.                                    */

@keyframes bb-wipe   { from { transform: translateX(-101%); } to { transform: translateX(0); } }
@keyframes bb-rise   { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes bb-slam   { 0% { transform: scale(1.7); opacity: 0; } 45% { opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes bb-blink  { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0.15; } }
@keyframes bb-sparkin {
  0%   { transform: scale(0.2) rotate(-45deg); opacity: 0; }
  55%  { transform: scale(1.25) rotate(0deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
@keyframes bb-strahl { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.an .anim-wipe  { animation: bb-wipe 380ms cubic-bezier(0.15, 0.85, 0.25, 1) both; }
.an .anim-rise  { animation: bb-rise 320ms cubic-bezier(0.15, 0.85, 0.25, 1) both; }
.an .anim-slam  { animation: bb-slam 420ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
.an .anim-spark { animation: bb-sparkin 560ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
.an .verz-1 { animation-delay: 90ms; }
.an .verz-2 { animation-delay: 180ms; }
.an .verz-3 { animation-delay: 300ms; }

@media (prefers-reduced-motion: reduce) {
  .an [class*="anim-"] { animation-duration: 1ms !important; }
}

/* ── Einsatzraster ───────────────────────────────────────── Guide S. 16 ──
   Die Kacheln 1 bis stake_max. Verbrauchte bleiben an ihrem Platz und
   werden nur anders gezeichnet — wer die 7 sucht, findet sie auf Position 7,
   ob verbraucht oder nicht. Kleinste Kachel 96 px: das ist die Fingergröße,
   und unter der Ecke unten links lag schon einmal die „11" (E-052).       */

.einsatzraster {
  display: grid;
  grid-template-columns: repeat(var(--spalten, 4), 1fr);
  /*
   * Drei Reihen fest, egal wie viele Kacheln kommen. Sonst wandert die
   * Fußzeile je nach stake_max, und der Bildschirm sieht bei 9 Räumen anders
   * aus als bei 11. Die Kacheln wachsen in die Höhe, die da ist — bleiben
   * aber nie unter 96 px.
   */
  grid-template-rows: repeat(3, minmax(96px, 1fr));
  gap: 12px;
  flex: 1;
  min-height: 0;
}
.kachel {
  min-width: 96px;
  min-height: 96px;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--graphit);
  color: var(--weiss);
  font-size: 40px;
  cursor: pointer;
  /* Dieselbe Cut-Geometrie wie die Schaltflächen — oben rechts, unten links. */
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 18px));
  transition: transform 100ms cubic-bezier(0.2, 0.9, 0.2, 1);
}
.kachel:not(:disabled):hover { transform: translate(-2px, -2px); }
.kachel:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }

/*
 * Verbraucht ist kein Fehler, sondern Spielstand — deshalb Steel und
 * gedämpft, nicht durchgestrichen oder weggenommen. Die Zahl bleibt lesbar,
 * damit man sieht, WAS schon weg ist.
 */
.kachel[data-verbraucht="true"] {
  background: var(--schwarz);
  color: var(--steel);
  opacity: 0.4;
  cursor: default;
}
.einsatzraster[data-einsatz="a"] .kachel[data-gewaehlt="true"] {
  background: var(--cyan);
  color: var(--auf-cyan);
}
.einsatzraster[data-einsatz="b"] .kachel[data-gewaehlt="true"] {
  background: var(--pink);
  color: var(--auf-pink);
}

/* ══════════════════════════════════════════════════════════════════════════
   DIE LAUTE EBENE
   Brand Guide S. 15 (Blatt 13) und Prinzip 2 und 5.

   Der Guide gibt für Flächen eine ruhige Ordnung vor — und zeigt auf
   demselben Blatt vier Elemente, die alles andere als ruhig sind: „250" mit
   Explosionsstern, „VS" mit Blitz, die Stoppuhr mit versetzten Konturen.
   Daneben steht die Regel, die das erlaubt:

       „Grundsätzlich einfarbig — ausgenommen große Skalierung."

   Und Prinzip 5: „Optische Balance und bewusste Spannung gehen vor steriler
   Gleichförmigkeit."

   Diese Ebene gilt deshalb NICHT überall. Sie gehört den Momenten, die
   Prinzip 2 benennt — Treffer, Ergebnis, Aktivierung. Der Code-Bildschirm,
   der Einsatz und der Notfallmodus bleiben ruhig: dort wird entschieden und
   gearbeitet, nicht gefeiert.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Versatzkontur ────────────────────────────────────────── Guide S. 15 ──
   Die gemeinsame Bauart aller vier Beispiele: eine weiße Form als Träger,
   dahinter dieselbe Form in Cyan nach der einen und in Pink nach der anderen
   Seite versetzt. Kein Verlauf, kein Schatten — drei harte Ebenen.
   Deshalb auch kein Verstoß gegen „Cyan und Pink nie ineinander": sie
   überlagern sich nicht, sie stehen versetzt nebeneinander.              */

.versatz {
  position: relative;
  display: inline-block;
  isolation: isolate;
}
.versatz > .lage {
  grid-area: 1 / 1;
}
.versatz > .lage-c,
.versatz > .lage-p {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.versatz > .lage-c { color: var(--cyan); transform: translate(calc(var(--v, 9px) * -1), calc(var(--v, 9px) * -1)); }
.versatz > .lage-p { color: var(--pink); transform: translate(var(--v, 9px), var(--v, 9px)); }

/* ── Plakette ─────────────────────────────────────────────── Guide S. 15 ──
   Das „250"-Element: Zahl in Versatzkontur, Explosionsstern oben links,
   Zackenschwanz unten. Für Punktzahlen im Siegmoment.                    */

.plakette {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 34px;
  /*
   * Kein eigener Träger. Auf der schwarzen Bühne wäre ein schwarzer Grund
   * unsichtbar, und auf Blatt 13 tragen die Versatzkonturen die Form selbst —
   * die Elemente dort stehen frei auf Schwarz.
   */
}
.plakette .zahl { position: relative; z-index: 1; }

/* Speed-Zacken rechts neben der Plakette */
.zacken {
  position: absolute;
  right: -46px;
  top: 22%;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.zacken > i {
  display: block;
  height: 8px;
  background: var(--weiss);
  clip-path: polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
}
.zacken > i:nth-child(1) { width: 64px; }
.zacken > i:nth-child(2) { width: 42px; }
.zacken > i:nth-child(3) { width: 24px; }

/* ── VS-Zeichen ───────────────────────────────────────────── Guide S. 15 ──
   Weiße Buchstaben, versetzte Konturen, der Lime-Blitz schlägt diagonal
   durch. Der Moment vor der Runde: hier stehen sich zwei gegenüber.     */

.vs {
  position: relative;
  display: inline-block;
  font-family: var(--display);
  font-size: 128px;
  font-weight: 700;
  line-height: 1;
}
/* Die Buchstaben liegen UEBER dem Blitz: `.versatz` ist durch
   `isolation: isolate` ein eigener Stapelkontext ohne z-index, und ein
   positioniertes Geschwister mit z-index 0 malt sonst darueber. Gemessen in
   apps/play — dort lag der Blitz oben, und Weiss stand auf Lime. Die Abnahme
   sah es nicht: `data-bildzeichen` nimmt die Versatzkontur vom Kontrastmass
   aus, und diese Ausnahme hat den Fehler zugedeckt. */
.vs .versatz {
  position: relative;
  z-index: 1;
}
.vs .blitz {
  position: absolute;
  left: 50%;
  top: -22%;
  width: 46px;
  height: 148%;
  margin-left: -23px;
  background: var(--lime);
  /* 22,5 Grad: die aktive Richtung des Systems, nicht irgendeine Schräge. */
  clip-path: polygon(62% 0, 100% 34%, 52% 44%, 88% 62%, 30% 100%, 46% 56%, 8% 46%, 54% 32%);
  /*
   * Hinter den Buchstaben, vor den Versatzkonturen. Lag der Blitz oben,
   * standen die Cyan- und Pink-Konturen auf Lime — 1,31:1 und 3,17:1.
   * Auf Blatt 13 läuft er dahinter durch und ist nur dort sichtbar, wo
   * kein Buchstabe steht.
   */
  z-index: 0;
}

/* ── Der Aufschlag ────────────────────────── CLAUDE.md · Signature-Element ──
   „Bei einem Rundensieg schießt die Siegerfarbe quer über den Bildschirm,
    am Aufprallpunkt entsteht der Impact-Stern aus dem Logo auf 40-facher
    Größe mit radialen Geschwindigkeitsstrichen. Dauer 600 ms."

   Drei Phasen in einer Zeitlinie:
     0–240 ms   das Band schießt quer
     220–420 ms der Stern schlägt ein
     260–600 ms die Geschwindigkeitsstriche laufen aus                    */

.aufschlag {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 30;
}

.aufschlag .band {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: var(--sieger, var(--cyan));
  transform: translateX(-101%);
}
.aufschlag.laeuft .band {
  animation: bb-schuss 620ms cubic-bezier(0.16, 0.9, 0.2, 1) both;
}
@keyframes bb-schuss {
  0%   { transform: translateX(-101%); }
  38%  { transform: translateX(0); }
  74%  { transform: translateX(0); }
  100% { transform: translateX(101%); }
}

.aufschlag .stern {
  position: absolute;
  left: var(--treffer-x, 62%);
  top: var(--treffer-y, 46%);
  width: 200px;
  height: 200px;
  margin: -100px 0 0 -100px;
  color: var(--lime);
  opacity: 0;
}
.aufschlag.laeuft .stern {
  animation: bb-einschlag 420ms cubic-bezier(0.2, 0.95, 0.25, 1) 200ms both;
}
/*
 * Der Stern zieht mit dem Band ab. Ohne das letzte Bild bliebe er stehen —
 * `fill-mode: both` behält den Endzustand, und der Siegbildschirm hätte
 * dauerhaft einen Einschlag mitten im Gesicht.
 */
/* Anlauf und Überschwingen auf dem Raster: -45 statt -60, 22,5 statt 6. */
@keyframes bb-einschlag {
  0%   { transform: scale(0.06) rotate(-45deg); opacity: 0; }
  34%  { transform: scale(1.5) rotate(22.5deg); opacity: 1; }
  62%  { transform: scale(1) rotate(0deg); opacity: 1; }
  100% { transform: scale(1.35) rotate(0deg); opacity: 0; }
}

/* Radiale Geschwindigkeitsstriche vom Aufprallpunkt weg. */
.aufschlag .striche {
  position: absolute;
  left: var(--treffer-x, 62%);
  top: var(--treffer-y, 46%);
  width: 0;
  height: 0;
}
.aufschlag .striche > i {
  position: absolute;
  left: 0;
  top: -3px;
  height: 6px;
  width: var(--l, 150px);
  background: var(--weiss);
  transform-origin: 0 50%;
  transform: rotate(var(--w)) translateX(90px) scaleX(0);
  opacity: 0;
}
.aufschlag.laeuft .striche > i {
  animation: bb-strich 380ms cubic-bezier(0.15, 0.85, 0.25, 1) 250ms both;
}
@keyframes bb-strich {
  0%   { transform: rotate(var(--w)) translateX(60px) scaleX(0); opacity: 0; }
  35%  { opacity: 1; }
  100% { transform: rotate(var(--w)) translateX(230px) scaleX(1); opacity: 0; }
}

/* ── Countdown-Dramatik ───────────────────────────────────────────────────
   Die letzte Sekunde zählt anders als die achtzigste. Ab zehn Sekunden
   schlägt die Uhr mit — ein Puls je Sekunde, synchron zum Takt.
   Kein Blinken: das liest sich als Störung, nicht als Spannung.         */

.uhr-knapp {
  color: var(--pink) !important;
  animation: bb-puls 1s steps(1, end) infinite;
}
@keyframes bb-puls {
  0%   { transform: scale(1.06); }
  22%  { transform: scale(1); }
  100% { transform: scale(1); }
}

/* ── Zahlenwechsel ────────────────────────────────────────────────────────
   Ein Punktestand, der sich ändert, springt nicht — er schlägt ein.     */

.zahl-neu { animation: bb-zahlschlag 340ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
@keyframes bb-zahlschlag {
  0%   { transform: scale(1.9); opacity: 0; }
  45%  { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .aufschlag.laeuft .band,
  .aufschlag.laeuft .stern,
  .aufschlag.laeuft .striche > i,
  .uhr-knapp,
  .zahl-neu { animation-duration: 1ms !important; }
  .uhr-knapp { animation-iteration-count: 1 !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   SEQUENZEN
   Einzelne Bildschirme können CI-treu sein und trotzdem tot wirken. Was den
   Durchgang trägt, ist der Übergang: die Runde endet, der Schlag kommt, der Stand
   wächst, die nächste Runde steht an. Das ist eine Bewegung, kein Schnitt.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Einsatzkacheln ──────────────────────────────────────────────────────
   Sie kommen gestaffelt herein — von links nach rechts, Reihe für Reihe.
   Die Verzögerung setzt app.js je Kachel, damit sie der Lesereihenfolge
   folgt und nicht dem Zufall.                                            */

.kachel.kommt {
  animation: bb-kachel-rein 260ms cubic-bezier(0.16, 0.9, 0.2, 1) both;
}
@keyframes bb-kachel-rein {
  0%   { transform: translateY(22px) scale(0.86); opacity: 0; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

/* Die Wahl ist ein Treffer, kein Zustandswechsel. */
.kachel.schlag {
  animation: bb-kachel-schlag 300ms cubic-bezier(0.2, 0.9, 0.2, 1);
  z-index: 2;
}
@keyframes bb-kachel-schlag {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}

/* Speed Lines, die von der gewählten Kachel wegzucken. */
.kachel-funken {
  position: absolute;
  pointer-events: none;
  z-index: 3;
}
.kachel-funken > i {
  position: absolute;
  left: 0;
  top: -2px;
  height: 4px;
  width: 40px;
  background: var(--funke, var(--cyan));
  transform-origin: 0 50%;
  transform: rotate(var(--w)) translateX(40px) scaleX(0);
  animation: bb-funke 320ms cubic-bezier(0.15, 0.85, 0.25, 1) both;
}
@keyframes bb-funke {
  0%   { transform: rotate(var(--w)) translateX(30px) scaleX(0); opacity: 1; }
  60%  { opacity: 1; }
  100% { transform: rotate(var(--w)) translateX(96px) scaleX(1); opacity: 0; }
}

/* Die Trennkante zündet, wenn beide gesetzt haben. */
.kante-zuendet { animation: bb-zuenden 520ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
@keyframes bb-zuenden {
  0%   { transform: scaleY(0); transform-origin: 50% 100%; }
  100% { transform: scaleY(1); transform-origin: 50% 100%; }
}

/* ── Battle Index ────────────────────────────────────────────────────────
   Eine Runde ist entschieden: die Kachel schlägt in die Teamfarbe um. Das
   ist die kleinste Bewegung im Entwurf und die, die man am häufigsten sieht. */

.numbox.faellt { animation: bb-numbox 420ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
/*
 * Ohne Drehung. Der Prüfer sieht nur Ruhezustände, deshalb fiel hier lange
 * ein -3-Grad-Kipper nicht auf — ein Winkel ausserhalb des 22,5-Grad-Rasters.
 * Prinzip 1 gilt auch für Bewegung, nicht nur für Standbilder.
 */
@keyframes bb-numbox {
  0%   { transform: scale(1); }
  26%  { transform: scale(1.34); }
  100% { transform: scale(1); }
}

/* ── Uhr am Ende ─────────────────────────────────────────────────────────
   Bei null schlägt die Uhr einmal aus, statt einfach stehenzubleiben.    */

.uhr-aus { animation: bb-uhr-aus 460ms cubic-bezier(0.2, 0.9, 0.2, 1) both; }
@keyframes bb-uhr-aus {
  0%   { transform: scale(1); color: var(--pink); }
  22%  { transform: scale(1.18); color: var(--weiss); }
  100% { transform: scale(0.92); opacity: 0.25; color: var(--steel); }
}

/* ── Hochzählen ──────────────────────────────────────────────────────────
   Der Gesamtstand springt nicht von 20 auf 26. Er läuft hoch, und die
   letzte Ziffer schlägt ein.                                             */

.zaehlt { animation: bb-zaehlt 120ms steps(1, end); }
@keyframes bb-zaehlt {
  0%   { transform: translateY(-6px); opacity: 0.55; }
  100% { transform: translateY(0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .kachel.kommt, .kachel.schlag, .kachel-funken > i, .kante-zuendet,
  .numbox.faellt, .uhr-aus, .zaehlt { animation-duration: 1ms !important; }
}

/* Die Kachel im Stechen: dieselbe Runde, nur markiert. Keine neue Nummer —
   das Stechen trägt dieselbe idx (E-032). */
.numbox.stechen {
  background: var(--graphit);
  outline: 3px solid var(--lime);
  outline-offset: -3px;
}
.numbox.stechen::before { background: var(--lime); }
.numbox.stechen > b { color: var(--lime); }
