/* ==========================================================================
   Modul Anzeigen & Ausgaben

   Zwei Welten in einer Datei, und der Unterschied ist grundsätzlich:

   **Anzeigen** (Halle, TV, Gesamtübersicht, Overlay) werden aus mehreren
   Metern gelesen. Für sie gilt die Dichte-Regel aus ARCHITEKTUR.md,
   Abschnitt 1 ausdrücklich *nicht* — hier zählt Größe, Kontrast und wenig pro
   Bild. Die Schriftgrößen hängen deshalb an der Bildschirmgröße (`vw`, `vh`,
   `clamp`), nicht an einer festen Punktzahl: Derselbe Aufbau muss auf einem
   32-Zoll-Fernseher und auf einem Beamer mit 4 Metern Bildbreite stimmen.

   **Bedienoberflächen** (Livewertung am Telefon, Turnierbaum, Monitor,
   Ansichtenübersicht) folgen den normalen Regeln: mobil zuerst, ab 360 px,
   Fingerflächen ab 44 px, breitere Bildschirme bekommen mehr Spalten.
   ========================================================================== */

/* --- 1  Gemeinsames ------------------------------------------------------- */

.an-seite {
  min-height: 100dvh;
  background: var(--page);
  color: var(--ink);
}

.an-leer {
  padding: var(--s7) var(--s5);
  color: var(--ink-3);
  text-align: center;
}

.an-leer.gross { font-size: clamp(1.2rem, 3vw, 2rem); }

.an-hinweisseite {
  display: grid;
  place-items: center;
  padding: var(--s6);
  text-align: center;
}

.an-hinweisseite section {
  max-width: 46ch;
  display: grid;
  gap: var(--s4);
}

.an-hinweisfeld {
  margin: var(--s4) var(--s4) 0;
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--gold);
  border-radius: var(--r1);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 0.9rem;
}

/* Ein Verbindungsabbruch reißt die Anzeige nicht weg — er meldet sich nur
   am unteren Rand. Auf einem Beamer wäre ein leerer Bildschirm schlimmer
   als ein Stand von vor zehn Sekunden. */
.an-stoerung {
  position: fixed;
  right: var(--s4);
  bottom: var(--s4);
  z-index: 50;
  padding: var(--s2) var(--s4);
  border-radius: var(--r-pill);
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.8rem;
  font-weight: 700;
}

.an-partei { min-width: 0; }
.an-partei b { display: block; overflow-wrap: anywhere; }
.an-partei i { color: var(--gold-ink); font-style: normal; }
.an-partei small { display: block; color: var(--ink-3); font-size: 0.8em; }

.an-marke {
  padding: 1px var(--s2);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--ink-3);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.an-werbung { display: grid; place-items: center; }
.an-werbung img { max-height: 12vh; max-width: 100%; object-fit: contain; }


/* --- 2  Hallenübersicht ---------------------------------------------------
   Beamer. Drei Felder gleichzeitig, blättert alle acht Sekunden weiter.
   -------------------------------------------------------------------------- */

.an-halle {
  display: grid;
  grid-template-rows: auto auto auto minmax(0, 1fr);
  gap: var(--s3);
  padding: var(--s4);
  background: var(--nav-bg);
  color: #fff;
}

.an-kopf {
  display: flex;
  align-items: center;
  gap: var(--s5);
}

.an-kopf-text { flex: 1; min-width: 0; }
.an-kopf-text h1 { font-size: clamp(1.3rem, 3.2vw, 2.6rem); color: #fff; }
.an-kopf-text p { color: var(--nav-ink-2); font-size: clamp(0.8rem, 1.2vw, 1.1rem); }

.an-uhr {
  font-size: clamp(1.6rem, 4vw, 3.4rem);
  font-weight: 800;
  color: var(--gold-bright);
  line-height: 1;
}

.an-naechste {
  display: grid;
  gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  background: rgba(255, 255, 255, 0.07);
}

.an-naechste-titel {
  color: var(--gold-bright);
  font-size: clamp(0.7rem, 1vw, 0.95rem);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.an-naechste-liste {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s2);
}

.an-naechste-liste article b {
  display: block;
  font-size: clamp(0.9rem, 1.5vw, 1.3rem);
  overflow-wrap: anywhere;
}
.an-naechste-liste article i { color: var(--nav-ink-2); font-style: normal; }
.an-naechste-liste article small {
  color: var(--nav-ink-2);
  font-size: clamp(0.7rem, 1vw, 0.95rem);
}

.an-seitenkopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  color: var(--nav-ink-2);
  font-size: clamp(0.8rem, 1.2vw, 1.1rem);
  font-weight: 650;
}

.an-blaettern {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.an-blaettern button {
  display: grid;
  place-items: center;
  min-width: var(--touch);
  min-height: var(--touch);
  border-radius: var(--r2);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.4rem;
  line-height: 1;
}

.an-blaettern button:hover { background: rgba(255, 255, 255, 0.22); }

.an-feldraster {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s3);
  min-height: 0;
}

.an-feld {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  gap: var(--s2);
  min-height: 0;
  padding: var(--s4);
  border: 2px solid transparent;
  border-radius: var(--r3);
  background: rgba(255, 255, 255, 0.06);
}

.an-feld.laeuft { border-color: var(--gold); }
.an-feld.pause { border-color: var(--warn); }
.an-feld.frei { background: rgba(255, 255, 255, 0.03); }

.an-feld-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  color: var(--gold-bright);
  font-size: clamp(1rem, 2vw, 1.8rem);
  font-weight: 800;
  letter-spacing: 0.02em;
}

.an-feld-kopf strong { color: var(--nav-ink-2); font-size: 0.7em; text-transform: uppercase; }

.an-feld .an-disziplin {
  color: var(--nav-ink-2);
  font-size: clamp(0.75rem, 1.2vw, 1.1rem);
}

.an-feld-frei {
  display: grid;
  place-items: center;
  color: var(--nav-ink-2);
  font-size: clamp(2rem, 6vw, 5rem);
}

.an-stand { display: grid; gap: var(--s2); align-content: center; }

.an-stand-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
}

.an-halle .an-stand-zeile b { font-size: clamp(1rem, 2.2vw, 2rem); line-height: 1.15; }
.an-halle .an-stand-zeile small { color: var(--nav-ink-2); }

.an-punkte {
  font-size: clamp(1.8rem, 5vw, 4.4rem);
  font-weight: 800;
  line-height: 1;
}

/* Der Sieger flächig, nicht fett: Eine Fläche ist aus zehn Metern
   erkennbar, eine Schriftstärke nicht. */
.an-stand-zeile.sieger { background: rgba(154, 168, 90, 0.24); }

.an-saetze {
  color: var(--nav-ink-2);
  font-size: clamp(0.8rem, 1.3vw, 1.2rem);
}


/* --- 3  TV-Feldansicht ----------------------------------------------------
   Drei Darstellungen, eine Regel: Jede Partei hat ihre eigene Farbe. Aus zehn
   Metern erkennt man daran, welche Zahl zu wem gehört, ohne den Namen zu
   lesen. Oben/links ist grün, unten/rechts orange — feste Zuordnung, damit
   sich niemand je Feld neu orientieren muss.
   -------------------------------------------------------------------------- */

.an-tv {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  place-items: center;
  padding: var(--s4);
  background: var(--nav-bg);
  color: #fff;

  /* Kräftige Farben, bewusst außerhalb des übrigen Farbschemas: Ein Beamer
     frisst Sättigung, und diese beiden müssen sich auch bei schlechtem
     Bildwurf sicher unterscheiden. Schwarze Schrift darauf kommt auf über
     10:1 Kontrast — nachgemessen, nicht geschätzt. */
  --tv-a: #35e07f;
  --tv-b: #ff5f38;
  --tv-auf-farbe: #08120c;
}

.an-tv-frei,
.an-tv-karte {
  display: grid;
  gap: var(--s4);
  width: 100%;
  max-width: 1600px;
  text-align: center;
}

.an-tv-frei h1 { font-size: clamp(2rem, 9vw, 7rem); color: var(--nav-ink-2); }
.an-tv-frei span { color: var(--gold-bright); font-size: clamp(0.9rem, 2vw, 1.6rem); }

/* --- 3a  Links-/Rechts-Ansicht (classic) ---
   **Das Bild wird aufgeteilt, nicht zusammengeschoben.** Kopf und Dauer sitzen
   oben, die Satzkästen unten, und dazwischen steht der Block aus Punktestand
   und Namen in der Mitte des übrigen Platzes. Vorher verteilte das Raster alle
   Zeilen gleichmäßig um die Bildmitte — unten blieb eine leere Fläche, und die
   Namen wirkten neben dem großen Stand zu klein.

   Die Schriftgrößen wachsen mit der **Breite der Karte** (`cqw`) und nicht mit
   der des Fensters: So bleibt das Verhältnis von Stand zu Namen gleich, ganz
   gleich ob der Fernseher 16:9 oder 4:3 zeigt. */

.an-tv-classic {
  place-items: stretch;
  padding: 0;
}

/* „Feld frei“ füllt dieselbe Fläche, bleibt darin aber mittig — es ist eine
   Meldung und keine Aufteilung. */
.an-tv-classic .an-tv-frei {
  align-content: center;
  justify-items: center;
  padding: var(--s5);
}

.an-tv-classic .an-tv-karte {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2.4cqw, 34px);
  max-width: none;
  min-height: 100dvh;
  padding: clamp(20px, 4vw, 70px);
  container-type: inline-size;
}

/* Punktestand und Namen: der eigentliche Inhalt, mittig im freien Platz. */
.an-tv-classic .an-tv-mitte {
  display: grid;
  align-content: center;
  gap: clamp(18px, 3.2cqw, 56px);
  flex: 1 1 auto;
  min-height: 0;
}

/* Feld — Disziplin — Status.
 *
 * Raster mit gleich breiten Außenspalten statt `space-between`: Beim Verteilen
 * des Restplatzes sitzt die Mitte nur dann wirklich mittig, wenn links und
 * rechts gleich viel steht. „Feld 1“ ist aber kürzer als „Beendet“, und die
 * Disziplin rutschte dadurch sichtbar nach links — auffällig vor allem gegen
 * die Dauer direkt darunter, die auf die Bildmitte zentriert ist.
 *
 * minmax(0, 1fr) für die Außenspalten, damit ein langer Status die Mitte
 * nicht doch noch verschiebt: Ohne die 0 als Mindestbreite wächst die Spalte
 * mit ihrem Inhalt.
 */
.an-tv-kopf {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--s4);
  color: var(--nav-ink-2);
  font-size: clamp(18px, 2cqw, 32px);
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.an-tv-kopf > :first-child { text-align: left; }
.an-tv-kopf > :nth-child(2) { text-align: center; }
.an-tv-kopf > :last-child { text-align: right; }

.an-tv-dauer {
  color: var(--gold-bright);
  font-size: clamp(20px, 2cqw, 34px);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
}

.an-tv-grossstand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--s4), 3cqw, var(--s8));
  color: var(--gold-bright);
  font-size: clamp(120px, 22cqw, 260px);
  font-weight: 800;
  line-height: 0.9;
}

.an-tv-grossstand i {
  color: var(--nav-ink-2);
  font-size: 0.4em;
  font-style: normal;
  letter-spacing: 0.1em;
}

.an-tv-namen {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5);
}

.an-tv-partei {
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  min-width: 0;
}

.an-tv-partei b {
  display: block;
  font-size: clamp(34px, 4.2cqw, 70px);
  line-height: 1.02;
  overflow-wrap: anywhere;
}

.an-tv-partei small {
  display: block;
  margin-top: clamp(4px, 0.6cqw, 10px);
  color: var(--nav-ink-2);
  font-size: clamp(16px, 2.2cqw, 24px);
  font-weight: 600;
}

/* Die linke Partei steht links im Bild, die rechte rechts — wie auf dem Feld. */
.an-tv-namen .an-tv-partei:first-child { text-align: left; }
.an-tv-namen .an-tv-partei:last-child { text-align: right; }

.an-tv-partei.sieger { background: rgba(154, 168, 90, 0.22); }

.an-tv-satzkaesten {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(10px, 1.4cqw, 24px);
}

.an-tv-satzkasten {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  min-height: clamp(56px, 7vh, 92px);
  padding: clamp(8px, 1.2cqw, 18px) clamp(16px, 2cqw, 30px);
  border-radius: var(--r2);
  background: rgba(255, 255, 255, 0.06);
  color: var(--nav-ink);
  font-size: clamp(22px, 2.4cqw, 40px);
  font-weight: 800;
}

.an-tv-satzkasten sup {
  color: var(--nav-ink-2);
  font-size: 0.45em;
  font-weight: 700;
}

/* Der laufende Satz hebt sich ab — golden wie der Punktestand darüber. */
.an-tv-satzkasten.laufend {
  background: rgba(217, 168, 60, 0.18);
  color: var(--gold-bright);
}

.an-aufschlag { color: var(--gold-bright); }

/* --- 3b  Oben-/unten-Ansicht und BWF-Ansicht ---
   Diese beiden füllen den Bildschirm ganz aus: Der Fernseher am Feld zeigt
   nichts anderes, und zwei Zeilen über die volle Höhe sind aus der letzten
   Zuschauerreihe noch zu lesen. Die Links-/Rechts-Ansicht bleibt dagegen
   mittig — sie lebt vom großen Punktestand in der Mitte. */

.an-tv-topdown,
.an-tv-bwf {
  /* **Feste** Höhe, nicht bloß eine Mindesthöhe. Nur eine bestimmte Höhe lässt
     sich aufteilen: Mit `min-height` allein bleibt sie für das Raster
     unbestimmt, `1fr` verhält sich dann wie `auto`, die Tabelle wird nur so
     hoch wie ihr Inhalt — und der Rest des Bildschirms bleibt schwarz. Genau
     das war der Fehler. Der Vorgänger löst es ebenso (`.tv-table-page` mit
     `height: 100vh`). */
  height: 100dvh;
  padding: 0;
  overflow: hidden;

  /* Drei Zeilen mit **fest zugewiesenen** Plätzen: Die Kinder wechseln je
     Spielstand (der Hinweis „Zuletzt gespielt“ und die Werbefläche kommen und
     gehen), und ohne feste Zuweisung rutschte die Tabelle in die Zeile des
     fehlenden Geschwisters. */
  grid-template-rows: auto minmax(0, 1fr) auto;
  place-items: center;

  /* Die Kopfzeile ist fest bemaßt, damit die beiden Spielerzeilen exakt die
     Hälfte des Rests bekommen — wie beim Vorgänger. */
  --tv-kopfhoehe: clamp(44px, 8vh, 76px);
}

/* Gedehnt wird **nur** die Tabelle. Ohne diese Zuweisung dehnte sich jedes
   Kind auf die Höhe seiner Rasterzeile — die Werbefläche unten ebenso wie die
   Tabelle. */
.an-tv-topdown > .an-tv-tabelle,
.an-tv-bwf > .an-tv-tabelle { grid-row: 2; place-self: stretch; }

.an-tv-topdown > .an-werbung,
.an-tv-bwf > .an-werbung { grid-row: 3; }

.an-tv-tabelle { width: 100%; max-width: 1900px; display: grid; gap: var(--s4); }

.an-tv-topdown .an-tv-tabelle,
.an-tv-bwf .an-tv-tabelle {
  max-width: none;
  min-height: 0;
  gap: 0;
  grid-template-rows: minmax(0, 1fr) auto;
}

.an-tv-topdown .an-tv-tabelle table,
.an-tv-bwf .an-tv-tabelle table { height: 100%; }

/* Kopfzeile fest, die beiden Spielerzeilen je zur Hälfte. Ohne das teilt der
   Browser die Höhe nach dem Inhalt auf, und die Zeile mit dem längeren Namen
   (zweizeilig umgebrochen) wird höher als die andere. */
.an-tv-topdown .an-tv-tabelle thead th,
.an-tv-bwf .an-tv-tabelle thead th { height: var(--tv-kopfhoehe); }

.an-tv-topdown .an-tv-tabelle tbody tr,
.an-tv-bwf .an-tv-tabelle tbody tr {
  height: calc((100% - var(--tv-kopfhoehe)) / 2);
}

.an-tv-topdown .an-tv-schiri,
.an-tv-bwf .an-tv-schiri { margin: var(--s2) auto; }

.an-tv-tabelle table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.an-tv-tabelle th[scope="col"] {
  padding: var(--s2) var(--s4);
  color: var(--nav-ink);
  font-size: clamp(0.8rem, 2.2vw, 2.2rem);
  font-weight: 800;
  text-align: center;
}

.an-tv-tabelle thead th:first-child {
  text-align: left;
  color: #fff;
}

.an-tv-tabelle thead th:first-child small {
  display: block;
  color: var(--nav-ink-2);
  font-size: 0.5em;
  font-weight: 600;
}

.an-tv-tabelle tbody th {
  padding: var(--s4);
  text-align: left;
  min-width: 0;
}

.an-tv-tabelle tbody th b {
  display: block;
  font-size: clamp(1.2rem, 3.4vw, 3.4rem);
  line-height: 1.1;
  overflow-wrap: anywhere;
}

.an-tv-tabelle tbody th small {
  display: block;
  font-size: clamp(0.7rem, 1.3vw, 1.3rem);
  opacity: 0.75;
}

.an-tv-tabelle td {
  width: 18%;
  padding: var(--s2);
  font-size: clamp(2rem, 8vw, 7rem);
  font-weight: 800;
  line-height: 1;
  text-align: center;
}

/* Ein noch nicht gespielter Satz. Der Gedankenstrich steht in der vollen
   Zifferngröße sonst als breiter Balken im Bild und sieht aus wie ein
   Ergebnis. */
.an-tv-tabelle td.leer { font-size: clamp(1rem, 2.5vw, 2.2rem); opacity: 0.45; }

/* Oben-/unten-Ansicht: beide Zeilen durchgehend in ihrer Farbe. Kein
   zusätzliches Hervorheben — ohne Schiedsrichter ist nicht verlässlich
   bekannt, wer gerade aufschlägt, und eine geratene Markierung wäre
   schlimmer als keine. */
.an-tv-topdown tbody tr { color: var(--tv-auf-farbe); }
.an-tv-topdown tbody tr.seite-a th { background: var(--tv-a); }
.an-tv-topdown tbody tr.seite-a td { background: color-mix(in srgb, var(--tv-a) 74%, #fff); }
.an-tv-topdown tbody tr.seite-b th { background: var(--tv-b); }
.an-tv-topdown tbody tr.seite-b td { background: color-mix(in srgb, var(--tv-b) 74%, #fff); }
.an-tv-topdown tbody th small { opacity: 0.7; }

/* BWF-Ansicht: dunkler Grund, Zahlen in der Farbe der Partei. Flächig wird
   nur hervorgehoben, wer gerade am Zug ist — Name und laufender Satz. Diese
   Angabe ist verlässlich, weil sie aus der Schiedsrichter-Zählansicht kommt. */
.an-tv-bwf .an-tv-tabelle table { border-spacing: 0; }
.an-tv-bwf tbody th,
.an-tv-bwf tbody td { border: 2px solid var(--nav-bg); background: #0a0f0c; }
.an-tv-bwf tbody tr.seite-a { color: var(--tv-a); }
.an-tv-bwf tbody tr.seite-b { color: var(--tv-b); }

/* Flächig hervorgehoben wird zweierlei, und beides mit demselben Mittel:
   wer **gerade** am Zug ist (Name und laufender Satz) und wer einen Satz
   **gewonnen** hat. Das eine löst das andere ab, ohne die Bildsprache zu
   wechseln — nach dem Satzende bleibt die Zahl stehen, die den Satz entschied
   (`satzsieger` in `anzeigen/feld.js`). */
.an-tv-bwf tbody tr.seite-a.amzug th,
.an-tv-bwf tbody tr.seite-a td.amzug,
.an-tv-bwf tbody tr.seite-a td.satzsieger { background: var(--tv-a); color: var(--tv-auf-farbe); }
.an-tv-bwf tbody tr.seite-b.amzug th,
.an-tv-bwf tbody tr.seite-b td.amzug,
.an-tv-bwf tbody tr.seite-b td.satzsieger { background: var(--tv-b); color: var(--tv-auf-farbe); }

.an-tv-schiri { color: var(--nav-ink-2); font-size: clamp(0.75rem, 1.3vw, 1.2rem); }


/* --- 4  Öffentliche Live-Spielstände --------------------------------------
   Die einzige Anzeige, die überwiegend am Telefon geöffnet wird.
   -------------------------------------------------------------------------- */

.an-live { padding: var(--s4); padding-bottom: calc(var(--s8) + var(--safe-bottom)); }

.an-live-kopf {
  display: grid;
  gap: var(--s4);
  margin-bottom: var(--s5);
}

.an-live-kopf h1 { font-size: 1.3rem; }
.an-live-kopf p { color: var(--ink-3); font-size: 0.9rem; }

.an-live-suche { position: relative; }
.an-live-suche input { padding-right: 44px; }

.an-live-suche button {
  position: absolute;
  top: 50%;
  right: var(--s2);
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--r-pill);
  color: var(--ink-3);
  transform: translateY(-50%);
}

.an-kopf-knoepfe { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* Auf einem Fernseher fallen die Sprünge in andere Ansichten weg.
   `an-vom-fernseher` setzt der Rahmen, wenn das Gerät über die kurze Adresse
   hereingekommen ist (`seiten/anzeige.js`). Dort hat sich jemand mit der
   Fernbedienung für **diese** Ansicht entschieden; Knöpfe zu anderen wären
   nicht bedienbar und nähmen nur Bildfläche weg. Zurück führt allein
   „Ansicht wechseln“ am Bildrand.

   Am Telefon eines Zuschauers bleiben sie stehen: Wer den QR-Code vom Aushang
   scannt, landet in einer Ansicht und will sich umsehen. */
body.an-vom-fernseher .an-kopf-knoepfe { display: none; }

.an-live-block { margin-bottom: var(--s6); }

.an-live-block h2 {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin-bottom: var(--s3);
  font-size: 1rem;
}

.an-live-block h2 span { color: var(--ink-3); font-size: 0.85rem; font-weight: 600; }

.an-kartenraster {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s3);
}

.an-karte {
  display: grid;
  gap: var(--s2);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-2);
  border-radius: var(--r3);
  background: var(--surface);
  box-shadow: var(--sh1);
}

.an-karte.laeuft { border-left-color: var(--st-live); }
.an-karte.bereit { border-left-color: var(--st-ready); }
.an-karte.fertig { border-left-color: var(--st-done); }
.an-karte.pause { border-left-color: var(--warn); }

.an-karte-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  color: var(--ink-2);
  font-size: 0.85rem;
  font-weight: 650;
}

.an-karte .an-disziplin { color: var(--ink-3); font-size: 0.82rem; }

.an-karte .an-stand-zeile { padding: var(--s1) var(--s2); }
.an-karte .an-stand-zeile b { font-size: 0.98rem; }
.an-karte .an-punkte { font-size: 1.6rem; color: var(--ink); }
.an-karte .an-saetze { color: var(--ink-3); font-size: 0.82rem; }
.an-karte .an-stand-zeile.sieger { background: var(--brand-soft); }

.an-satzspalte { color: var(--ink-2); font-size: 0.95rem; letter-spacing: 0.14em; }


/* --- 5  Turnierleiter-Monitoring ------------------------------------------ */

.an-monitor { padding: var(--s4); }

.an-monitor-kopf {
  display: grid;
  gap: var(--s4);
  margin-bottom: var(--s5);
}

.an-monitor-kopf h1 { font-size: 1.25rem; }
.an-monitor-kopf p { color: var(--ink-3); font-size: 0.85rem; }

.an-monitor-zahlen {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
}

.an-kennzahl {
  display: grid;
  gap: 2px;
  padding: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface);
}

.an-kennzahl strong { font-size: 1.5rem; line-height: 1; }
.an-kennzahl span { color: var(--ink-3); font-size: 0.76rem; }

.an-monitor-schalter { display: flex; gap: var(--s2); }

.an-monitor-schalter button {
  flex: 1;
  min-height: var(--touch);
  padding: 0 var(--s4);
  border: 1px solid var(--line-2);
  border-radius: var(--r2);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 0.88rem;
  font-weight: 650;
}

.an-monitor-schalter button.aktiv {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

.an-monitor-raster { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }

.an-monitor-tafel {
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--surface);
}

.an-monitor-tafel h2 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s3);
  font-size: 0.95rem;
}

.an-monitor-tafel h2 span { color: var(--ink-3); font-size: 0.82rem; font-weight: 600; }

.an-monitor-liste { display: grid; gap: var(--s2); }

.an-monitor-zeile {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  background: var(--surface-2);
  font-size: 0.88rem;
}

.an-monitor-zeile.laeuft { box-shadow: inset 3px 0 0 var(--st-live); }
.an-monitor-zeile.fertig { box-shadow: inset 3px 0 0 var(--st-done); }
.an-monitor-zeile.bereit { box-shadow: inset 3px 0 0 var(--st-ready); }
.an-monitor-zeile.abgehakt { opacity: 0.45; }

/* Ein Spiel im Nachlauf: eben beendet, steht noch drei Minuten unter „Auf den
   Feldern“ — aber das Feld ist frei.

   Die Zeile tritt deshalb sichtbar zurück: gestrichelter Rahmen statt voller
   Fläche, gedämpfter Grund. Aus zwei Metern erkennt der Turniertisch daran,
   dass hier nichts mehr läuft, ohne die Beschriftung lesen zu müssen — sonst
   wäre der Nachlauf schlimmer als das sofortige Verschwinden. */
.an-monitor-zeile.nachlauf {
  background: transparent;
  box-shadow: inset 3px 0 0 var(--st-done);
  outline: 1px dashed var(--line-2);
  outline-offset: -1px;
}

.an-monitor-zeile.nachlauf .an-monitor-zeit b { color: var(--st-done); }

.an-monitor-feld {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r2);
  background: var(--surface-3);
  font-weight: 800;
}

.an-monitor-paarung { min-width: 0; }
.an-monitor-paarung strong { display: block; overflow-wrap: anywhere; font-size: 0.92rem; }
.an-monitor-paarung i { color: var(--ink-3); font-style: normal; font-weight: 400; }
.an-monitor-paarung small { color: var(--ink-3); font-size: 0.78rem; }

.an-monitor-saetze,
.an-monitor-punkte { display: none; color: var(--ink-2); }

.an-monitor-zeit { display: grid; justify-items: end; }
.an-monitor-zeit b { font-size: 0.78rem; }
.an-monitor-zeit small { color: var(--ink-3); font-size: 0.76rem; }

.an-haken {
  display: grid;
  place-items: center;
  width: var(--touch);
  height: var(--touch);
  border-radius: var(--r2);
  color: var(--ink-3);
  font-size: 1rem;
}

.an-haken[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand-ink); }

.an-monitor-spalte { display: grid; gap: var(--s5); }

.an-feldpunkte { display: flex; flex-wrap: wrap; gap: var(--s2); }

.an-feldpunkt {
  display: grid;
  place-items: center;
  min-width: 38px;
  min-height: 38px;
  border-radius: var(--r2);
  font-weight: 700;
}

.an-feldpunkt.frei { background: var(--brand-soft); color: var(--brand-ink); }
.an-feldpunkt.belegt { background: var(--st-live-soft); color: var(--st-live); }
.an-feldpunkt.aus { background: var(--surface-2); color: var(--ink-3); opacity: 0.6; }

.an-bereitliste { display: grid; gap: var(--s2); margin: 0; padding-left: var(--s6); }
.an-bereitliste strong { display: block; font-size: 0.9rem; }
.an-bereitliste i { color: var(--ink-3); font-style: normal; font-weight: 400; }
.an-bereitliste small { color: var(--ink-3); font-size: 0.78rem; }


/* --- 6  Komprimierte Gesamtübersicht --------------------------------------
   Alles auf ein Bild. Die Zeilenhöhe folgt der Zeilenzahl, damit auch bei
   vielen Feldern nichts unter den Rand rutscht — auf einem Fernseher kann
   niemand scrollen.
   -------------------------------------------------------------------------- */

.an-gesamt {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: var(--s2);
  height: 100dvh;
  padding: var(--s3);
  background: var(--nav-bg);
  color: #fff;
  overflow: hidden;

  /* Die verfügbare Höhe geteilt durch die Zeilenzahl, gedeckelt, damit
     wenige Zeilen nicht albern groß werden. */
  --zeilenhoehe: min(96px, calc((100dvh - 90px) / var(--zeilen)));

  /* **Die Breite zählt genauso wie die Höhe.** Vorher hing die Schrift allein
     an der Zeilenhöhe: Bei wenigen Zeilen wurde sie so groß, dass Sätze, Stand
     und Status die ganze Zeile ausfüllten — die Namen wurden auf null
     gequetscht und die Disziplin lief über den Satzstand. Genau das war auf
     einem hochkant gehaltenen Tablet zu sehen. Der zweite Wert deckelt sie
     deshalb an der Fensterbreite. */
  --gesamt-schrift: clamp(0.68rem,
                          min(calc(var(--zeilenhoehe) * 0.34), 2.1vw),
                          2rem);
}

.an-gesamt-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  padding: 0 var(--s2);
}

.an-gesamt-kopf h1 { font-size: clamp(1rem, 2.4vw, 2rem); color: #fff; }
.an-gesamt-kopf span { color: var(--nav-ink-2); font-size: clamp(0.72rem, 1.2vw, 1.1rem); }

/* Auf einem Fernseher passt alles nebeneinander. Auf einem schmalen Gerät
   nicht — und dann muss der Kasten scrollen, statt die Zeilen abzuschneiden.
   Die Seite selbst bleibt unverschiebbar. */
.an-gesamt-liste {
  display: grid;
  gap: 4px;
  align-content: start;
  min-height: 0;
  overflow: auto;
}

.an-gesamt-zeile {
  min-width: 620px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--s3);
  height: var(--zeilenhoehe);
  padding: 0 var(--s3);
  border-radius: var(--r2);
  background: rgba(255, 255, 255, 0.06);
  font-size: var(--gesamt-schrift);
}

.an-gesamt-zeile.laeuft { box-shadow: inset 4px 0 0 var(--gold); }
.an-gesamt-zeile.bereit { box-shadow: inset 4px 0 0 var(--st-ready); }
.an-gesamt-zeile.pause { box-shadow: inset 4px 0 0 var(--warn); }

.an-gesamt-feld {
  display: grid;
  place-items: center;
  min-width: 2.2em;
  color: var(--gold-bright);
  font-size: 1.4em;
  font-weight: 800;
}

/* `overflow: hidden` ist die Sicherung: Was hier zu breit wird, wird
   abgeschnitten und schiebt sich **nie** über die Nachbarspalte. Ohne sie
   konnte die Disziplin über den Satzstand laufen, und auf dem Bildschirm stand
   dann Unsinn wie „2Ⱥ1D0“. Lieber ein gekürzter Name als zwei Angaben
   übereinander. */
.an-gesamt-paarung {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  min-width: 0;
  overflow: hidden;
}

.an-gesamt-paarung b {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* Die Namen sind der Inhalt der Zeile — sie geben zuletzt nach. Ohne
     Grundbreite schrumpften sie auf null, während die Disziplin danebenstand. */
  flex: 1 1 4em;
  min-width: 0;
}

.an-gesamt-paarung i {
  color: var(--nav-ink-2);
  font-style: normal;
  font-size: 0.8em;
  flex: 0 0 auto;
}

.an-gesamt-paarung small {
  color: var(--nav-ink-2);
  font-size: 0.75em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* Die Disziplin steht als Erste zurück: Sie ist die Angabe, die man am
     ehesten entbehren kann — das Feld daneben sagt schon, welches Spiel es ist. */
  flex: 0 1 auto;
  min-width: 0;
}

.an-gesamt-saetze { display: flex; gap: var(--s2); color: var(--nav-ink-2); }
.an-gesamt-saetze em { font-style: normal; min-width: 3.4em; text-align: right; }

.an-gesamt-stand { font-size: 1.5em; font-weight: 800; min-width: 3.5em; text-align: right; }

.an-gesamt-status { display: grid; justify-items: end; color: var(--nav-ink-2); font-size: 0.8em; }

/* --- Hochkant auf Telefon und Tablet ---------------------------------------
   Nebeneinander passt es dort nicht mehr: Fünf Spalten auf 400 Punkten heißt
   entweder Gequetsche oder seitliches Schieben, und beides taugt nichts. Die
   Zeile wird deshalb zweizeilig — oben Feld, Paarung und Stand, darunter
   Disziplin, Sätze und Status. Gescrollt werden darf hier: Ein Telefon ist
   kein Fernseher, es hat einen Daumen.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .an-gesamt-zeile {
    min-width: 0;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "feld paarung stand"
      "feld saetze status";
    align-items: center;
    row-gap: 2px;
    height: auto;
    min-height: var(--zeilenhoehe);
    padding: var(--s2) var(--s3);
    font-size: clamp(0.82rem, 3.4vw, 1.15rem);
  }

  .an-gesamt-feld { grid-area: feld; }
  .an-gesamt-paarung { grid-area: paarung; }
  .an-gesamt-saetze { grid-area: saetze; font-size: 0.85em; }
  .an-gesamt-stand { grid-area: stand; }
  .an-gesamt-status { grid-area: status; }

  /* Die Paarung bekommt zwei Zeilen statt einer Ellipse: Auf einem Telefon
     liest man die Namen, nicht die Spaltenbreite. */
  .an-gesamt-paarung { flex-wrap: wrap; row-gap: 0; }
  .an-gesamt-paarung b { flex: 1 1 100%; }
  .an-gesamt-paarung small { flex: 1 1 100%; }

  /* Ohne feste Breite: Drei leere Satzfelder nähmen sonst die halbe Zeile. */
  .an-gesamt-saetze em { min-width: 2.6em; }
}


/* --- 7  Streaming-Overlay -------------------------------------------------
   Wird in OBS als Bildquelle eingebunden. Zwei Hintergründe
   (UEBERGABE.md, Abschnitt 10.1):

     transparent  für die Browser-Quelle in OBS, die Transparenz von sich aus
                  kann — dann liegt das Kamerabild darunter.
     greenscreen  für Fensteraufnahmen und alles andere ohne Alphakanal. Die
                  Farbe steht in `--overlay-grund` und wird beim Zeichnen
                  gesetzt (web/js/anzeigen/overlay.js).

   Alles hier ist **fest bemaßt und nicht am Farbschema der Anwendung
   ausgerichtet**: Ein Overlay läuft in einem Videobild fester Größe, nicht auf
   dem Telefon eines Zuschauers. Ein heller Systemmodus darf die Tafel im
   Stream nicht umfärben.
   -------------------------------------------------------------------------- */

body.an-durchsichtig,
body.an-durchsichtig .app-root { background: transparent !important; }

/* Kein Schlagschatten auf dem Greenscreen.
 *
 * Ein Schatten ist Schwarz mit Teildeckung. Über einem durchsichtigen
 * Hintergrund ist das genau richtig: Die Browser-Quelle in OBS reicht den
 * Alphakanal durch, der Schatten legt sich weich über das Kamerabild.
 *
 * Über dem Greenscreen wird daraus etwas anderes — dort mischt sich das
 * Schwarz **in das Grün**, und der Schatten ist am Ende ein Kranz aus
 * dunklerem Grün. Ein Chroma-Key entscheidet nicht nach „grün oder nicht“,
 * sondern nach dem Abstand zur Schlüsselfarbe im Farbanteil: Je dunkler ein
 * Grün wird, desto mehr nähert es sich der grauen Mitte und desto weniger
 * sieht der Key es als seine Farbe an. Der Schatten fällt also **teilweise**
 * heraus — außen, wo er schwach ist, ganz, innen gar nicht. Zurück bleibt ein
 * grauer Saum um die Tafel. Wer die Toleranz so weit aufdreht, dass auch der
 * Saum verschwindet, greift die Tafel selbst an.
 *
 * Deshalb: Der Schatten hängt an `--ov-hebung` und wird hier auf einen
 * Schatten ohne Ausdehnung und ohne Farbe gesetzt. Nicht auf `none` — die
 * Tafel setzt ihn stellenweise mit einer Kante zusammen (`0 0 0 1px …,
 * var(--ov-hebung, …)`), und ein `none` in einer solchen Aufzählung macht die
 * ganze Angabe ungültig. Ein durchsichtiger Nullschatten ist ebenso
 * unsichtbar und bleibt gültig.
 *
 * Kanten und innenliegende Ringe bleiben unberührt: Sie sind deckend und
 * liegen **auf** der Tafel, nicht auf dem Grün. */
body:not(.an-durchsichtig) .an-overlay { --ov-hebung: 0 0 0 rgba(0, 0, 0, 0); }

.an-overlay {
  display: grid;
  align-items: start;
  min-height: 100dvh;
  padding: 24px;
  background: var(--overlay-grund, transparent);
  font-family: var(--font);
}

.an-overlay.leer { background: var(--overlay-grund, transparent); }

/* Das Vereinslogo vor dem Namen. `leer` hält den Platz auf der Gastseite
   frei, damit die Namen beider Zeilen untereinander stehen. */
.an-overlay-logo {
  width: 40px;
  height: 40px;
  object-fit: contain;
}

/* Die leere Zelle hält die Spalte, damit Heim- und Gastzeile dieselbe
   Spaltenfolge behalten. Ist gar kein Logo hinterlegt, verschwindet die
   Spalte in beiden Zeilen — sonst klaffte links eine Lücke. */
.an-overlay-logo.leer { display: inline-block; }
.an-overlay.ohne-logo .an-overlay-logo { width: 0; }
.an-overlay.ohne-logo .an-overlay-zeile { grid-template-columns: 18px 0 minmax(0, 1fr) 44px 68px; }
.an-overlay.ohne-logo .an-overlay-zeile > .an-overlay-logo { margin-right: -8px; }

/* Klassisch: das Logo steht in der Namenszelle vor dem Namen, in der Höhe
   der Schrift. Ohne Logo hält die leere Zelle die Breite, damit Heim- und
   Gastzeile ihre Namen an derselben Stelle beginnen. */
/* 46 px: Die Zelle ist so hoch wie die Zeile, und die geben die großen
   Zahlen rechts vor — abzüglich der Innenabstände bleibt genau so viel Platz.
   Das Logo wird damit deutlich erkennbar, ohne die Tafel zu vergrößern. */
.an-kl-name > .an-overlay-logo {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  margin-right: 12px;
}
.an-overlay.ohne-logo .an-kl-name > .an-overlay-logo { margin-right: 0; }

/* Die frühere umschließende Karte samt Kopfzeile ist entfallen: Im Stream
   wirkte sie wie ein aufgeklebtes Fenster. Geblieben sind die zwei Zeilen —
   jede mit eigenem Grund, damit sie über hellem wie dunklem Bild lesbar ist. */
.an-overlay-zeilen {
  display: grid;
  gap: 3px;
  width: min(560px, 100%);
}

.an-overlay-zeile {
  display: grid;
  /* Aufschlag, Logo, Name, Sätze, Punkte. Die Logospalte fällt auf null,
     wenn keines zu zeigen ist (`ohne-logo` am Rahmen). 40 px füllen die
     Innenhöhe der Zeile aus, die der Name samt Verein darunter ohnehin
     vorgibt — die Zeile wird davon nicht höher. */
  grid-template-columns: 18px 40px minmax(0, 1fr) 44px 68px;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 6px;
  background: rgba(12, 16, 14, 0.88);
  color: #fff;
  box-shadow: var(--ov-hebung, 0 3px 14px rgba(0, 0, 0, 0.35));
}

.an-overlay-zeile.heim { border-left: 8px solid var(--heimfarbe); }
.an-overlay-zeile.gast { border-left: 8px solid rgba(255, 255, 255, 0.35); }
.an-overlay-zeile.sieger { background: rgba(20, 32, 22, 0.92); }

.an-overlay-aufschlag { color: #ffd766; font-size: 14px; text-align: center; }

/* 20 px ist die größte Schrift; kleiner setzt sie nur `namenEinpassen`, für
   beide Zeilen gleich. Reicht auch die Untergrenze nicht, bekommt im Doppel
   jeder Spieler eine eigene Zeile (`zweizeilig`) — dieselben Stufen wie in
   Klassisch und im Sendebalken. */
.an-overlay-name b {
  display: block;
  font-size: var(--tafel-schrift, 20px);
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Zweizeilig wächst die Zeile der Tafel um eine Namenszeile. Anders als beim
   Sendebalken gibt es hier keinen großen Punktestand, der die Höhe ohnehin
   vorgäbe — und ein abgeschnittener Name ist schlimmer als eine etwas höhere
   Einblendung. */
.an-overlay-zeilen.zweizeilig .an-overlay-name b {
  font-size: var(--tafel-schrift, 15px);
  line-height: 1.1;
}
.an-overlay-zeilen.zweizeilig .an-schraeg { display: none; }
.an-overlay-zeilen.zweizeilig .an-spieler {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.an-overlay-name small { display: block; color: #b9c2bd; font-size: 12px; }

.an-overlay-saetze { color: #b9c2bd; font-size: 20px; font-weight: 700; text-align: center; }

.an-overlay-punkte {
  font-size: 34px;
  font-weight: 800;
  line-height: 1;
  text-align: center;
}

/* Helle Fassung der Tafel (Schalter „Farbfassung“, Migration 022).
 *
 * Die dunkle Fassung oben ist die Grundform — sie war zuerst da und bleibt
 * es, damit ein Overlay ohne gesetzte Fassung aussieht wie bisher. Hier steht
 * nur, was sich ändert.
 *
 * Der schwarze Ring außen ersetzt, was im Dunkeln der Schlagschatten tat: Er
 * grenzt die Zeile gegen ein helles Kamerabild ab. Ohne ihn verschwämme eine
 * helle Zeile vor einer weißen Hallenwand.
 *
 * Er ist **1 px stark und der Abstand der Zeilen wächst mit**. Ein Ring liegt
 * außerhalb der Zeile, also fressen zwei Zeilen zweimal seine Stärke aus dem
 * Zwischenraum: Bei 2 px Ring und 3 px Abstand stießen die beiden Ringe
 * aneinander, und aus zwei Balken wurde einer mit einem Strich in der Mitte.
 * 1 px Ring und 6 px Abstand lassen 4 px Luft dazwischen — die Zeilen bleiben
 * zwei. */
.an-overlay.hell .an-overlay-zeilen { gap: 6px; }

.an-overlay.hell .an-overlay-zeile {
  background: #f4f6f4;
  color: #101513;
  box-shadow: 0 0 0 1px #101513, var(--ov-hebung, 0 3px 14px rgba(0, 0, 0, 0.28));
}

.an-overlay.hell .an-overlay-zeile.gast { border-left-color: rgba(16, 21, 19, 0.35); }
.an-overlay.hell .an-overlay-zeile.sieger { background: #fff3cf; }
.an-overlay.hell .an-overlay-aufschlag { color: #8a5a00; }
.an-overlay.hell .an-overlay-name small,
.an-overlay.hell .an-overlay-saetze { color: #4a5450; }


/* --- 7b  Design „Klassisch“ ------------------------------------------------
   Die Vorlage des Auftraggebers: rote Heimzeile mit weißer, mittig gesetzter
   Schrift, graue Gastzeile, rechts zwei schmale Spalten mit dunklen
   Kopfzellen „Sätze“ und „Punkte“. Die Farbe der Heimzeile kommt über
   --heimfarbe aus den drei Stufen (UEBERGABE.md, Abschnitt 10.1).
   -------------------------------------------------------------------------- */

.an-kl {
  width: min(660px, 100%);
  /* Scharfe Rechtecke, kein Schatten: So sieht die Vorlage aus. Eine Rundung
     ließe es nach heutiger Anwendung aussehen, nicht nach Sportgrafik. */
}

/* Eine **feste** Breite, die nie mit dem Namen wächst: Im Stream soll die
   Tafel bei jedem Spiel an derselben Stelle in derselben Größe stehen. Passt
   ein Name nicht hinein, wird die Schrift kleiner und im Doppel die Zelle
   zweizeilig (`namenEinpassen` in `overlay.js`) — bis 18 px, darunter
   kürzt ein „…“.

   660 px wie in der Vorlage: 780 und 700 px waren ausprobiert und dem
   Auftraggeber zu breit. Die Namensspalte hat damit rund 450 px für Text.
   Ein Doppel mit zwei Flaggen braucht bei 28 px etwa ebenso viel — was
   länger ist, fangen Verkleinern und zwei Zeilen auf. Mit der Altersklasse
   wird die Tafel um genau deren Box breiter; sonst ginge die Box von der
   Namenszelle ab. */
.an-kl.mit-ak { width: min(746px, 100%); }

.an-kl-kopf,
.an-kl-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px 84px;
  align-items: stretch;
  gap: 2px;
  margin-bottom: 2px;
}

/* Die Kopfzeile bleibt über der Namensspalte **leer** — sie beschriftet nur
   die beiden Zahlenspalten. Genau das macht die Vorlage aus. */
.an-kl-kopf .an-kl-name { background: none; }

.an-kl-kopf .an-kl-wert {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 0;
  background: #4a4a4c;
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: none;
}

/* Linksbündig, nicht mittig: Mit Flaggen davor beginnt jede Zeile dann an
   derselben Stelle, und die beiden Flaggen der Heim- und der Gastzeile stehen
   in einer Spalte untereinander. Mittig gesetzt rückte jede Zeile je nach
   Namenslänge anders ein. */
.an-kl-name {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 9px 20px;
  color: #fff;
  /* 28 px ist die größte Schrift. Kleiner setzt sie nur `namenEinpassen`,
     für beide Zeilen gleich. */
  font-size: var(--kl-schrift, 28px);
  font-weight: 600;
  line-height: 1.1;
  overflow: hidden;
  text-align: left;
}

/* Der Text in der Zelle — ein eigenes Element, weil ein „…“ nur an einem
   Block mit Fließtext entsteht und nicht an einer Flex-Zelle. Außerdem misst
   `namenEinpassen` an ihm, ob der Name hineinpasst. */
.an-kl-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Ohne Flaggen steht der Schrägstrich eng wie im Anzeigenamen („A/B“); mit
   Flaggen braucht er Luft, sonst klebt die zweite Flagge daran. */
.an-schraeg.eng { margin: 0; }

/* Zweizeilig (Stufe 2 in `namenEinpassen`): Im Doppel steht jeder Spieler auf
   einer eigenen Zeile seiner Zelle. 24 px höchstens — zwei Zeilen davon
   passen samt knapperem Innenabstand in die Höhe, die die Zahlen der Zeile
   ohnehin vorgeben; die Tafel wird dadurch nicht höher. Der Aufschlagpunkt
   steht links neben beiden Zeilen, er gehört zum Paar und nicht zu einem
   der beiden. */
.an-kl.zweizeilig .an-kl-name {
  padding-top: 5px;
  padding-bottom: 5px;
  font-size: var(--kl-schrift, 24px);
  line-height: 1.08;
}
.an-kl.zweizeilig .an-kl-text {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.35em;
}
/* Die beiden Zeilen stehen linksbündig untereinander, der Block als Ganzes
   bleibt mittig in der Zelle: So stehen die Flaggen in einer Spalte, statt
   je nach Namenslänge versetzt. */
.an-kl.zweizeilig .an-kl-paar { min-width: 0; text-align: left; }
.an-kl.zweizeilig .an-schraeg { display: none; }
.an-kl.zweizeilig .an-spieler {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.an-kl-zeile.heim .an-kl-name { background: var(--heimfarbe); }
.an-kl-zeile.gast .an-kl-name { background: #b9b6b9; }

/* Bei heller Vereinsfarbe kippt die Schrift ins Dunkle. Welche Farbe hell
   genug dafür ist, entscheidet `heimzeileIstHell` in `overlay.js` — dort
   liegen die Farbwerte, hier nur die Darstellung. */
.an-overlay.heim-hell .an-kl-zeile.heim .an-kl-name { color: #161b19; }

/* Feste Breite, damit der Punkt beim Aufschlagwechsel nichts verschiebt:
   Die Zelle steht in beiden Zeilen, auch wo gerade kein Aufschlag ist — dort
   unsichtbar statt weg, sonst rückte die Zeile um seine Breite. */
.an-kl-aufschlag {
  flex: 0 0 auto;
  width: 0.8em;
  margin-right: 6px;
  font-size: 0.55em;
  font-style: normal;
  line-height: 1;
  text-align: center;
}
.an-kl-aufschlag.leer { visibility: hidden; }

.an-kl-wert {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 9px 0;
  color: #fff;
  font-size: 34px;
  font-weight: 600;
  text-align: center;
}

/* Die beiden Zahlenspalten unterscheiden sich im Grauwert — dunkel für die
   Sätze, heller für die Punkte. Das trennt sie ohne Trennlinie. */
.an-kl-zeile .an-kl-wert.saetze { background: #58585a; }
.an-kl-zeile .an-kl-wert.punkte { background: #8a8a8c; }


/* --- 7c  Design „Sendebalken“ ----------------------------------------------
   Waagerechter Balken im Stil einer Sportübertragung: Logo, Name, Satzkästen,
   großer Punktestand rechts, der Aufschlag als Marke vor dem Namen.
   -------------------------------------------------------------------------- */

.an-sb {
  width: min(760px, 100%);
  overflow: hidden;
  border-radius: 4px;
  box-shadow: var(--ov-hebung, 0 6px 24px rgba(0, 0, 0, 0.4));
}

.an-sb-zeile {
  display: grid;
  grid-template-columns: 22px auto minmax(0, 1fr) auto auto 76px;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  color: #fff;
}

/* Ohne Logo entfällt auch die Lücke davor — `gap` wirkt sonst weiter. */
.an-overlay.ohne-logo .an-sb-zeile { grid-template-columns: 22px 0 minmax(0, 1fr) auto auto 76px; gap: 0 10px; }
.an-overlay.ohne-logo .an-sb-zeile > .an-overlay-logo { margin-right: -10px; }

.an-sb-zeile.heim { background: var(--heimfarbe); }
.an-sb-zeile.sieger .an-sb-name { text-decoration: none; }

/* Die untere Zeile ist hell, nicht dunkel.
 *
 * Darunter liegt die schwarze Beizeile mit Konkurrenz, Runde und Feld. Eine
 * dunkle Gastzeile lief in sie hinein — im Stream sah der Balken unten aus
 * wie ein Block, und die Beizeile war nicht mehr als eigene Zeile zu erkennen.
 *
 * `#e9edea` und nicht `#fff`: Reines Weiß ist im Sendeweg heikel. Es liegt am
 * oberen Anschlag des Signals, blüht bei der Kompression aus und zieht auf
 * manchen Geräten einen Rand um die Schrift. Sendegrafik bleibt deshalb
 * unterhalb davon. Der Grünstich ist derselbe, den die Beizeile (`#0c100e`)
 * und die frühere Gastzeile hatten — der Balken bleibt eine Familie.
 *
 * Die 1-px-Linie oben ist für die Vereinsfarben da, nicht für die Optik: Ein
 * Verein mit hellem Gelb oder Weiß in `--heimfarbe` hätte sonst zwei helle
 * Zeilen ohne Grenze dazwischen.
 */
.an-sb-zeile.gast {
  background: #e9edea;
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.22);
}

.an-sb-marke { color: #ffd766; font-size: 18px; text-align: center; }

/* Auf einer hellen Zeile kehren sich alle Aufhellungen um: Was sonst mit Weiß
 * aufgehellt wird, wird hier mit Schwarz abgedunkelt — sonst verschwände
 * ausgerechnet der laufende Satz. Das Gold der Aufschlagmarke wird dabei
 * nicht heller, sondern tiefer: Gelb auf Weiß ist aus zwei Metern nichts.
 *
 * Die Regeln gelten für **beide** hellen Fälle: die Gastzeile, die immer hell
 * ist, und die Heimzeile, wenn die Vereinsfarbe hell ist (`heim-hell` kommt
 * aus `overlay.js`). Ein Verein in Gelb bekäme sonst denselben unlesbaren
 * Balken, den die dunkle Gastzeile vorher hatte. */
.an-sb-zeile.gast,
.an-overlay.heim-hell .an-sb-zeile.heim { color: #161b19; }

.an-sb-zeile.gast .an-sb-marke,
.an-overlay.heim-hell .an-sb-zeile.heim .an-sb-marke { color: #8a5a00; }

.an-sb-zeile.gast .an-sb-saetze em,
.an-overlay.heim-hell .an-sb-zeile.heim .an-sb-saetze em {
  background: rgba(0, 0, 0, 0.1);
}

.an-sb-zeile.gast .an-sb-punkte,
.an-overlay.heim-hell .an-sb-zeile.heim .an-sb-punkte {
  background: rgba(0, 0, 0, 0.14);
}

.an-sb-name {
  /* 24 px ist die größte Schrift; kleiner setzt sie nur `namenEinpassen`. */
  font-size: var(--sb-schrift, 24px);
  font-weight: 700;
  overflow: hidden;
}

/* Wie in Klassisch: ein eigenes Element für den Text, weil ein „…“ nur an
   einem Block mit Fließtext entsteht — und weil `namenEinpassen` daran misst,
   ob der Name hineinpasst. */
.an-sb-text {
  /* **Ausdrücklich ein Block.** Als Inline-Element meldete es Breite null,
     und `namenEinpassen` hielt jeden Namen für passend — der Name wurde
     abgeschnitten, statt kleiner oder zweizeilig zu werden. In Klassisch
     fällt das nicht auf, weil die Namenszelle dort ein Flex-Behälter ist und
     ihr Kind dadurch ohnehin zum Block wird. */
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Zweizeilig: 17 px, damit zwei Zeilen unter der Höhe bleiben, die der große
   Punktestand daneben ohnehin vorgibt (34 px). Der Balken wird dadurch nicht
   höher — er soll im Stream an derselben Stelle in derselben Größe stehen. */
.an-sb.zweizeilig .an-sb-name {
  font-size: var(--sb-schrift, 17px);
  line-height: 1.05;
}
.an-sb.zweizeilig .an-schraeg { display: none; }
.an-sb.zweizeilig .an-spieler {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Der Gesamtstand in Sätzen, links neben den einzelnen Satzergebnissen.
 *
 * Je Zeile **eine** Zahl und kein Paar „1:0“: In diesem Balken trägt jede
 * Spalte den Wert *einer* Partei, und die beiden Zeilen übereinander gelesen
 * ergeben den Stand von selbst. Ein Paar stünde zweimal im Bild — einmal je
 * Zeile, beide Male dasselbe — und bräuchte die doppelte Breite.
 *
 * Schwarz und weiß in **beiden** Zeilen und beiden Farbfassungen, statt sich
 * der Parteifarbe anzupassen: Genau das macht die Plakette zu einer eigenen
 * Spalte, die man beim Überfliegen findet. Sie ist die einzige Zahl im Balken,
 * die nicht zum laufenden Satz gehört.
 *
 * Deshalb ein **eigener dunkler Ton** und keine Abdunklung des Untergrunds:
 * Ein halbdurchsichtiges Schwarz nimmt die Farbe an, auf der es liegt. Auf der
 * hellen Gastzeile wurde daraus ein Mittelgrau, und weiße Schrift kam dort auf
 * 3,9:1 — zu wenig für einen Stream. Mit dem festen Ton steht sie auf jedem
 * Untergrund über 11:1. Die Restdurchsicht bleibt, damit die Parteifarbe
 * darunter noch durchschimmert. */
.an-sb-satzstand {
  min-width: 32px;
  padding: 3px 9px;
  border-radius: 5px;
  background: rgba(10, 14, 12, 0.86);
  color: #fff;
  font-family: var(--font-num);
  font-size: 21px;
  font-weight: 800;
  text-align: center;
}

.an-sb-saetze { display: flex; gap: 5px; }

.an-sb-saetze em {
  display: grid;
  place-items: center;
  min-width: 34px;
  padding: 2px 0;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.28);
  font-family: var(--font-num);
  font-size: 19px;
  font-style: normal;
  font-weight: 700;
}

.an-sb-punkte {
  background: rgba(0, 0, 0, 0.3);
  border-radius: 3px;
  font-size: 34px;
  font-weight: 800;
  line-height: 1.05;
  text-align: center;
}

.an-sb-fuss {
  padding: 5px 14px;
  background: rgba(12, 16, 14, 0.9);
  color: #b9c2bd;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Dunkle Fassung des Sendebalkens — die frühere Gestalt, unverändert.
 *
 * Die helle Gastzeile oben ist die Grundform geworden, weil sie sich besser
 * von der schwarzen Beizeile absetzt. Wer den Balken über hellem Bild
 * einblendet, will trotzdem die dunkle: Über einer weißen Hallenwand trägt
 * sie weiter. Hier steht deshalb der alte Zustand wieder her.
 *
 * `heim-hell` bleibt davon unberührt: Ob die **Heim**zeile dunkle Schrift
 * braucht, entscheidet die Vereinsfarbe und nicht die Fassung. */
.an-overlay.dunkel .an-sb-zeile.gast {
  background: #24292a;
  color: #fff;
  box-shadow: none;
}

.an-overlay.dunkel .an-sb-zeile.gast .an-sb-marke { color: #ffd766; }
.an-overlay.dunkel .an-sb-zeile.gast .an-sb-saetze em { background: rgba(0, 0, 0, 0.28); }
.an-overlay.dunkel .an-sb-zeile.gast .an-sb-punkte { background: rgba(0, 0, 0, 0.3); }


/* --- 7d  Design „Satzübersicht“ --------------------------------------------
   Mittig im Bild, mit **allen** Satzergebnissen ausgeschrieben („21:15
   16:21  3:7“). Gedacht für die Satzpause und das Spielende — die drei
   anderen Designs hängen klein in einer Bildecke und zeigen nur den
   laufenden Stand.

   Helle Tafel mit schwarzen Konturen
   ----------------------------------
   Diese Tafel hängt anders als die übrigen: Sie steht mittig und groß im
   Bild, oft minutenlang während der Satzpause. Eine fast schwarze Fläche
   dieser Größe wirkt dabei schwer und mit der Zeit langweilig — auf einer
   hellen fällt der Blick auf die Zahlen, und das ist der Zweck.

   Zusammengehalten wird sie von **Konturen statt Flächen**: ein breiter
   schwarzer Rahmen außen, ein schwarzes Band für die Beizeile, um jeden
   Satzblock eine eigene Linie. Das ist die Bildsprache heutiger
   Sportgrafik — und sie trägt weiter als ein Farbverlauf, weil eine Linie
   auch nach der Kompression eines Streams noch eine Linie ist.

   Die alte dunkle Fassung liegt in `docs/Overlay-Satzuebersicht-dunkel.md`.
   -------------------------------------------------------------------------- */

.an-overlay-satzuebersicht,
.an-overlay-satzuebersicht_transparent { align-items: center; justify-items: center; }

.an-su {
  width: min(860px, 100%);
  padding: 20px 26px 24px;
  overflow: hidden;
  border: 5px solid #101513;
  border-radius: 14px;
  background: #f4f6f4;
  color: #101513;
  text-align: center;
  box-shadow: var(--ov-hebung, 0 10px 40px rgba(0, 0, 0, 0.45));
}

/* Die Beizeile ist ein Band über die ganze Breite und keine Zeile im Kasten.
   Sie zieht die Kontur des Rahmens nach innen weiter und gibt der Tafel oben
   einen Abschluss — die negativen Ränder heben genau die Polsterung der Tafel
   auf, `overflow: hidden` beschneidet das Band an den Ecken. */
.an-su-kopf {
  margin: -20px -26px 0;
  padding: 9px 26px;
  background: #101513;
  color: #e9edea;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.an-su-namen {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 16px;
  font-size: 30px;
  font-weight: 700;
  line-height: 1.15;
}

/* Der Strich unter dem Namen ist breiter als vorher: Auf hellem Grund ist er
   das einzige Farbfeld der Tafel und darf die Vereinsfarbe auch zeigen. */
.an-su-partei { display: inline-flex; align-items: center; gap: 8px; }
.an-su-partei.heim { border-bottom: 6px solid var(--heimfarbe); }
.an-su-partei.gast { border-bottom: 6px solid rgba(16, 21, 19, 0.35); }

/* Der Sieger steht auf Gold, statt in Gold geschrieben zu sein: Ein
   dunkleres Gold als Schriftfarbe wirkte auf der hellen Tafel trüb, die
   Fläche trägt dagegen weit.

   Mit dem laufenden Satz kollidiert das nicht, obwohl beide dasselbe Gold
   tragen — es gibt keinen Bildschirm, auf dem beides zugleich steht: Solange
   ein Satz läuft, gibt es keinen Sieger, und steht der Sieger fest, läuft
   kein Satz mehr. Gold heißt auf dieser Tafel deshalb immer genau eines. */
.an-su-partei.sieger {
  padding: 0 10px;
  border-radius: 5px;
  background: #ffd766;
  color: #101513;
}
.an-su-gegen { color: #5d6763; font-size: 18px; font-weight: 500; }
.an-su-aufschlag { color: #8a5a00; font-size: 0.5em; font-style: normal; }

/* Die Standzeile: Vereinslogo, die Satzkästen, Vereinslogo.

   Die Logos stehen außen und nicht mehr vor den Namen — dort waren sie so
   klein wie die Schrift und kaum zu erkennen, während neben den Satzkästen
   ohnehin Platz frei blieb. Die leere Zelle bleibt auch ohne Logo stehen,
   damit die Kästen mittig bleiben; ist gar keines hinterlegt, fällt sie über
   `ohne-logo` am Rahmen auf null zusammen. */
.an-su-stand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 20px;
}

.an-su-stand > .an-overlay-logo {
  width: 88px;
  height: 88px;
}

.an-su-saetze {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

/* Ein Satz ist ein Block: die beiden Zahlen mit Doppelpunkt, darunter klein
   „Satz 2“. Ausgeschrieben statt gerafft — das ist der ganze Zweck.

   Umrissen statt gefüllt: Fünf gefüllte Kästen auf hellem Grund wären fünf
   graue Flecken. Die Linie hält den Block zusammen, ohne der Zahl darin
   Kontrast zu nehmen. */
.an-su-satz {
  display: grid;
  justify-items: center;
  min-width: 148px;
  padding: 11px 16px 8px;
  border: 3px solid #101513;
  border-radius: 10px;
  background: #fff;
}

/* Die beiden Zahlen stehen **nebeneinander** mit Doppelpunkt dazwischen —
   „21:15“, so wie man ein Satzergebnis schreibt. Untereinander sähe es aus
   wie zwei getrennte Werte. */
.an-su-paar {
  display: flex;
  align-items: baseline;
  font-size: 46px;
  font-weight: 800;
  line-height: 1;
}

.an-su-paar em { font-style: normal; }
.an-su-paar i { padding: 0 5px; font-style: normal; color: #7d8783; }
.an-su-satz small {
  margin-top: 6px;
  color: #4a5450;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Der laufende Satz ist der einzige, dessen Zahlen noch wachsen — und der
   einzige gefüllte Block. Das Gold ist dasselbe, das im Overlay schon
   „hier hinsehen“ heißt: Aufschlag und Sieger tragen es auch. Gefüllt statt
   nur umrandet, weil ein Blick von vier Metern eine Fläche findet und eine
   Linienstärke nicht. */
.an-su-satz.laufend {
  background: #ffd766;
  box-shadow: var(--ov-hebung, 0 0 0 3px rgba(255, 215, 102, 0.35));
}

.an-su-satz.laufend small { color: #6b4a00; }
.an-su-satz.laufend .an-su-paar i { color: #8a5a00; }

.an-su-leer { margin-top: 18px; color: #4a5450; font-size: 20px; }

/* Dunkle Fassung der Satzübersicht — die frühere Gestalt, unverändert.
 *
 * Sie ist mehr als eine Umfärbung: Die helle Tafel trägt ihre Struktur in
 * Konturen, die dunkle in Flächen. Deshalb fallen hier der Rahmen und die
 * Linien um die Satzblöcke wieder weg, und die Beizeile ist wieder eine
 * Zeile im Kasten statt ein Band darüber. Genau so sah sie aus, bevor es die
 * helle Fassung gab (`docs/Overlay-Satzuebersicht-dunkel.md`).
 */
.an-overlay.dunkel .an-su {
  padding: 22px 28px 26px;
  border: 0;
  border-radius: 10px;
  background: rgba(12, 16, 14, 0.9);
  color: #fff;
  box-shadow: var(--ov-hebung, 0 10px 40px rgba(0, 0, 0, 0.5));
}

.an-overlay.dunkel .an-su-kopf {
  margin: 0;
  padding: 0;
  background: none;
  color: #b9c2bd;
}

.an-overlay.dunkel .an-su-namen { margin-top: 10px; }
.an-overlay.dunkel .an-su-partei.heim { border-bottom-width: 4px; }
.an-overlay.dunkel .an-su-partei.gast {
  border-bottom: 4px solid rgba(255, 255, 255, 0.4);
}

/* Im Dunkeln ist der Sieger in Gold **geschrieben**; die goldene Fläche der
   hellen Fassung braucht es hier nicht, weil Gold auf Dunkel von selbst
   heraussticht. */
.an-overlay.dunkel .an-su-partei.sieger {
  padding: 0;
  border-radius: 0;
  background: none;
  color: #ffd766;
}

.an-overlay.dunkel .an-su-gegen { color: #8f9a94; }
.an-overlay.dunkel .an-su-aufschlag { color: #ffd766; }
.an-overlay.dunkel .an-su-saetze { gap: 18px; margin-top: 18px; }

.an-overlay.dunkel .an-su-satz {
  padding: 12px 16px 9px;
  border: 0;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
}

.an-overlay.dunkel .an-su-paar i { color: #8f9a94; }
.an-overlay.dunkel .an-su-satz small { color: #b9c2bd; }

.an-overlay.dunkel .an-su-satz.laufend {
  background: rgba(255, 215, 102, 0.16);
  box-shadow: inset 0 0 0 2px rgba(255, 215, 102, 0.5);
}

.an-overlay.dunkel .an-su-satz.laufend small { color: #b9c2bd; }
.an-overlay.dunkel .an-su-satz.laufend .an-su-paar i { color: #8f9a94; }
.an-overlay.dunkel .an-su-leer { color: #b9c2bd; }


/* --- 7e  Design „Satzübersicht (transparent)“ -------------------------------
   Dieselbe Tafel wie 7d — **derselbe Rahmen, dieselbe Größe, dasselbe Band**
   für die Beizeile. Weg ist allein die Füllung dazwischen: Wo sonst die helle
   Fläche liegt, sieht man im Stream das Kamerabild, beim Greenscreen das Grün.

   Was bleibt, sind die Teile, die etwas tragen. Die beiden Namen bekommen
   einen eigenen Balken, die Satzblöcke behalten ihre Füllung. Der Grund
   verschwindet, die Lesbarkeit darf nicht mitgehen: Eine Zahl ohne eigene
   Fläche stünde je nach Kamerabild auf Hell oder Dunkel — und wäre mal lesbar
   und mal nicht. Frei wird der **Zwischenraum**, nicht der Inhalt.

   Der Balken um die Namen trägt keine Kontur. Der Rahmen außen umfasst schon
   das Ganze; eine zweite Linie darin teilte die Tafel in zwei Kästen, statt
   den Namen eine Fläche zu geben.

   Zur Schreibweise der Selektoren
   -------------------------------
   Jeder Selektor hier nennt `.an-overlay`, das Design **und** die Fassung,
   obwohl `.an-overlay` immer danebensteht und nichts auswählt. Das ist
   Absicht: Die Regeln müssen die der Fassung oben schlagen
   (`.an-overlay.dunkel .an-su …`), und ohne die dritte Klasse wären beide
   gleich stark — dann entschiede allein die Reihenfolge im Blatt. Wer später
   Abschnitte verschiebt, bräche das, ohne es zu merken.
   -------------------------------------------------------------------------- */

/* Hell: Rahmen, Maße und Band stehen schon in 7d. Hier fällt nur die
   Füllung weg. */
.an-overlay.an-overlay-satzuebersicht_transparent.hell .an-su {
  background: none;
}

/* Dunkel: Dieselbe Gestalt herstellen. Die dunkle Fassung nimmt der Tafel
   Rahmen und Band, weil sie ihre Struktur sonst über Flächen trägt — hier
   gibt es aber keine Fläche mehr, die das könnte. */
.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su {
  padding: 20px 26px 24px;
  border: 5px solid #101513;
  border-radius: 14px;
  background: none;
  box-shadow: var(--ov-hebung, 0 10px 40px rgba(0, 0, 0, 0.45));
}

/* Das Band trägt hier ein mittleres Grau statt Schwarz. In der hellen Fassung
   ist es der dunkle Gegenpol zur hellen Tafel; in der dunklen stünde Schwarz
   auf Fast-Schwarz — Band, Namensbalken und Satzblöcke fielen zu einer Fläche
   zusammen. Das Grau hebt die Beizeile heraus, ohne heller zu werden als die
   Schrift darauf (Kontrast 8,4:1). */
.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su-kopf {
  margin: -20px -26px 0;
  padding: 9px 26px;
  background: rgba(69, 78, 74, 0.94);
}

/* Der Balken um die beiden Namen hängt **am Band der Beizeile**: oben ohne
   Abstand und mit rechten Winkeln, unten gerundet. So liest sich der Kopf der
   Tafel als ein Stück — Beizeile und Paarung gehören zusammen —, und das
   gerundete Ende sagt, wo er aufhört. Frei schwebend mit vier runden Ecken
   sah er aus wie ein zweiter, kleinerer Kasten in der Tafel. */
.an-overlay.an-overlay-satzuebersicht_transparent .an-su-namen {
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
  padding: 8px 20px;
  border-radius: 0 0 12px 12px;
}

.an-overlay.an-overlay-satzuebersicht_transparent.hell .an-su-namen {
  background: #f4f6f4;
  color: #101513;
}

.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su-namen {
  background: rgba(12, 16, 14, 0.92);
  color: #fff;
}

/* Ohne Grund darunter braucht jeder Satzblock im Dunkeln eine eigene
   deckende Fläche — die Aufhellung um 8 % der dunklen Fassung setzt die
   Tafelfläche voraus und stünde hier fast unsichtbar im Bild. */
.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su-satz {
  background: rgba(12, 16, 14, 0.92);
}

.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su-satz.laufend {
  background: rgba(58, 48, 14, 0.94);
}

/* Der Leerhinweis ist sonst nackter Text auf dem Kamerabild. */
.an-overlay.an-overlay-satzuebersicht_transparent .an-su-leer {
  width: fit-content;
  margin: 16px auto 0;
  padding: 8px 20px;
  border-radius: 12px;
}

.an-overlay.an-overlay-satzuebersicht_transparent.hell .an-su-leer {
  background: #f4f6f4;
}

.an-overlay.an-overlay-satzuebersicht_transparent.dunkel .an-su-leer {
  background: rgba(12, 16, 14, 0.92);
}


/* --- 7f  Altersklasse neben dem Scoreboard ---------------------------------
   Bei Jugend- und Seniorenturnieren steht links neben dem Scoreboard eine Box
   mit der Altersklasse — „U17“, „U13“, „O35“ (Migration 092). Ob es eine gibt,
   entscheidet der Server; hier steht nur, wie sie aussieht.

   **Sie gehört zum Design, nicht daneben.** Jede Variante hat ihre eigene
   Bildsprache, und die Box übernimmt sie: dieselbe Fläche, dieselbe Rundung,
   derselbe Rahmen, derselbe Schatten wie die Teile des Scoreboards, neben
   denen sie steht. Eine einheitliche Box für alle wäre in mindestens drei
   Designs ein Fremdkörper.

   Bei Tafel und Sendebalken steht die Box als eigenes Element **vor** dem
   Scoreboard und reicht über dessen volle Höhe (`align-items: stretch`); bei
   Klassisch neben den Spielerzeilen, bei den Satzübersichten als kleine Marke
   neben den Namen. Ohne Altersklasse sieht jedes Design aus wie vorher.
   -------------------------------------------------------------------------- */

.an-ov-mit-ak {
  --ak-breite: 72px;
  display: flex;
  align-items: stretch;
  gap: 6px;
}

.an-ov-ak {
  display: grid;
  place-items: center;
  flex: 0 0 var(--ak-breite);
  font-size: 26px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  line-height: 1;
}

/* Tafel: wie eine dritte Zeile, nur hochkant. In der dunklen Grundform
   dieselbe fast schwarze Fläche mit Schatten, in der hellen dieselbe helle
   Fläche mit dem 1-px-Ring — und derselbe Abstand wie zwischen den Zeilen,
   damit die Box nicht enger an der Tafel klebt als die Zeilen aneinander. */
.an-overlay-tafel .an-ov-mit-ak { gap: 3px; }

.an-overlay-tafel .an-ov-ak {
  border-radius: 6px;
  background: rgba(12, 16, 14, 0.88);
  color: #fff;
  box-shadow: var(--ov-hebung, 0 3px 14px rgba(0, 0, 0, 0.35));
}

.an-overlay-tafel.hell .an-ov-mit-ak { gap: 6px; }

.an-overlay-tafel.hell .an-ov-ak {
  background: #f4f6f4;
  color: #101513;
  box-shadow: 0 0 0 1px #101513, var(--ov-hebung, 0 3px 14px rgba(0, 0, 0, 0.28));
}

/* Klassisch: eine Zelle wie die Kopfzellen „Sätze“ und „Punkte“ — scharfe
   Ecken, derselbe dunkle Grauton, weiße Schrift. Sie steht neben den
   Spielerzeilen, die Kopfzeile reicht darüber hinweg.

   `margin-bottom: 2px`: Jede Zeile trägt unten 2 px Abstand. Ohne diesen
   Ausgleich stünde die Box um genau diesen Abstand unter der letzten Zeile
   heraus. */
.an-kl-koerper { gap: 2px; }
.an-kl-koerper > .an-kl-zeilen { flex: 1 1 auto; min-width: 0; }

.an-overlay-klassisch .an-ov-mit-ak { --ak-breite: 84px; }

.an-overlay-klassisch .an-ov-ak {
  margin-bottom: 2px;
  font-size: 30px;
  background: #4a4a4c;
  color: #fff;
}

/* Sendebalken: dieselbe Fläche wie die Beizeile darunter, dieselbe Rundung
   und derselbe Schatten wie der Balken. Die Beizeile ist in beiden
   Farbfassungen dunkel, die Box deshalb auch. */
.an-overlay-sendebalken .an-ov-ak {
  border-radius: 4px;
  background: rgba(12, 16, 14, 0.9);
  color: #fff;
  box-shadow: var(--ov-hebung, 0 6px 24px rgba(0, 0, 0, 0.4));
}

/* Satzübersicht: **keine Box neben der Tafel**, sondern eine kleine gefüllte
   Marke links neben den Namen, in der Tafel selbst.

   Eine Box in voller Höhe neben der großen, mittig stehenden Tafel war das
   schwerste Element im ganzen Bild — ausgerechnet für eine Angabe, die nur
   einordnet. Neben den Namen steht die Klasse dort, wo man ohnehin liest, wer
   spielt, und bleibt klein genug, um nicht mit ihnen zu wetteifern.

   Grau gefüllt und ohne Kontur: Die Tafel trägt schon Rahmen, Band und
   Satzkästen mit Linien; eine weitere Kontur zöge den Blick auf sich.

   Die Namen stehen dafür in einem eigenen Behälter, so breit wie ihre
   längste Zeile; die Marke steht mittig neben beiden Zeilen. Beim Doppel
   sind die Zeilen fest (`.zweizeilig`), siehe `satzuebersicht()` in
   `overlay.js`. Die Zeile um Marke und Namen bricht nicht um — sonst rutschte
   die Marke bei langen Namen allein in eine Zeile. */
.an-su-namen.mit-ak { flex-wrap: nowrap; }

.an-su-paarung {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  min-width: 0;
}
/* Im Doppel drei Zeilen untereinander — Paar, „gegen“, Paar —, jede mittig.
   Der Abstand ist kleiner als zwischen Namen nebeneinander: Untereinander
   trennt schon der Zeilenwechsel. */
.an-su-paarung.gestapelt {
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 4px;
}

.an-su-ak {
  flex: 0 0 auto;
  padding: 4px 10px;
  border-radius: 6px;
  background: #5d6763;
  color: #fff;
  font-size: 18px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  line-height: 1.1;
}

/* Im Dunkeln ein helleres Grau: Das Grau der hellen Fassung ginge auf der
   fast schwarzen Fläche unter. Weiße Schrift steht auf beiden über 5,5:1. */
.an-overlay.dunkel .an-su-ak { background: #454e4a; }


/* --- 7g Landesflaggen vor den Namen ---------------------------------------
   Ein **festes Feld** für jede Flagge, in das sie ganz hineingelegt wird
   (`object-fit: contain`). Das Feld bleibt gleich breit, egal wie die
   Vorlage geschnitten ist — die Schweiz ist quadratisch, Katar sehr lang —,
   damit die Namen in beiden Zeilen eines Scoreboards an derselben Stelle
   beginnen.

   Vorher stand hier `cover`. Das füllt das Feld aus, schneidet dafür aber
   ab, was nicht hineinpasst: Von der quadratischen Schweizer Flagge fehlte
   oben und unten je ein Viertel, das Kreuz sah gestaucht aus. Eine Flagge
   darf nicht beschnitten und schon gar nicht verzerrt werden — lieber
   bleibt links und rechts ein wenig Luft.

   Die Größe hängt an der Schrift (`em`), damit jedes Design die passende
   Flagge bekommt. Der feine Ring hält weiße Flaggen (Japan, Polen) auf der
   hellen Tafel zusammen; auf dunklem Grund geht er unter und stört nicht.
   Er sitzt am Bild und nicht am Feld, damit er die Flagge umschließt und
   nicht die Luft daneben. */
.an-flagge {
  display: inline-block;
  width: 1.15em;
  height: 0.8em;
  margin-right: 0.35em;
  border-radius: 2px;
  object-fit: contain;
  vertical-align: -0.08em;
  filter: drop-shadow(0 0 0.5px rgba(16, 21, 19, 0.55))
          drop-shadow(0 0 0.5px rgba(16, 21, 19, 0.35));
}
.an-schraeg { margin: 0 0.3em 0 0.15em; }

/* --- 8  Turnierbaum -------------------------------------------------------
   Drei Darstellungen derselben Daten. Die Zeichnung scrollt in einem eigenen
   Kasten — die Seite selbst scrollt nie waagerecht
   (ARCHITEKTUR.md, Abschnitt 1).
   -------------------------------------------------------------------------- */

.an-baumseite { padding: var(--s4); padding-bottom: calc(var(--s8) + var(--safe-bottom)); }

.an-baum-steuerung { display: grid; gap: var(--s3); margin-bottom: var(--s4); }

.an-sichtwahl { display: flex; gap: var(--s2); }

.an-sichtwahl button {
  flex: 1;
  min-height: var(--touch);
  padding: 0 var(--s3);
  border: 1px solid var(--line-2);
  border-radius: var(--r2);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 0.85rem;
  font-weight: 650;
}

.an-sichtwahl button.aktiv {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

.an-baum-reiter {
  display: flex;
  gap: var(--s2);
  margin-bottom: var(--s4);
  padding-bottom: var(--s2);
  overflow-x: auto;
  scrollbar-width: thin;
}

.an-baum-reiter button {
  flex: 0 0 auto;
  min-height: 40px;
  padding: 0 var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 0.85rem;
  font-weight: 650;
  white-space: nowrap;
}

.an-baum-reiter button.aktiv {
  background: var(--gold);
  border-color: var(--gold);
  color: #1a1206;
}

/* Die Zeichnung */
.an-baum-huelle { position: relative; }

.an-baum-rollfeld {
  overflow: auto;
  max-height: calc(100dvh - 220px);
  padding-bottom: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--surface-2);
}

.an-baum { position: relative; }

.an-baum-linien {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.an-baum-linien path {
  fill: none;
  stroke: var(--gold);
  stroke-width: 2;
  opacity: 0.7;
}

.an-baum-linien path.ende { stroke-dasharray: 4 4; }

.an-baum-runde {
  position: absolute;
  top: 0;
  color: var(--gold-ink);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-align: center;
  text-transform: uppercase;
}

.an-baum-platz { position: absolute; }

.an-baum-karte {
  display: grid;
  gap: 2px;
  padding: var(--s3);
  border: 1px solid var(--line-2);
  border-radius: var(--r3);
  background: var(--surface);
  box-shadow: var(--sh1);
  font-size: 0.85rem;
}

.an-baum-karte.freilos {
  border-style: dashed;
  background: transparent;
  box-shadow: none;
}

.an-baum-kopf {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  color: var(--ink-3);
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.an-baum-seite {
  padding: 2px var(--s2);
  border-radius: var(--r1);
  min-width: 0;
}

.an-baum-seite b { display: block; overflow-wrap: anywhere; }
.an-baum-seite small { display: block; color: var(--ink-3); font-size: 0.76em; }
.an-baum-seite i { color: var(--ink-3); font-style: italic; }

/* Olivgrün und flächig — damit der Weg durch den Baum aus einigen Metern
   Abstand erkennbar bleibt. */
.an-baum-seite.sieger { background: rgba(124, 141, 63, 0.22); }

.an-baum-saetze {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  color: var(--gold-ink);
  font-size: 0.8rem;
  font-weight: 700;
}

.an-baum-saetze i { font-style: normal; opacity: 0.6; }

.an-baum-fuss {
  display: grid;
  gap: 1px;
  padding-top: var(--s1);
  border-top: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 0.72rem;
}

.an-baum-endkarte {
  display: grid;
  gap: 2px;
  padding: var(--s4);
  border: 2px solid var(--gold);
  border-radius: var(--r3);
  background: var(--surface);
  text-align: center;
}

.an-baum-endkarte strong {
  color: var(--gold-ink);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.an-baum-endkarte b { font-size: 1rem; overflow-wrap: anywhere; }
.an-baum-endkarte small { color: var(--ink-3); font-size: 0.78rem; }

/* Übersichtskarte: bei großen Bäumen die einzige Orientierung. */
.an-baum-mini {
  position: absolute;
  right: var(--s3);
  bottom: var(--s5);
  width: 180px;
  height: 110px;
  padding: var(--s2);
  border: 1px solid var(--line-2);
  border-radius: var(--r2);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  box-shadow: var(--sh2);
  pointer-events: none;
}

.an-baum-mini svg { width: 100%; height: 100%; }
.an-baum-mini rect { fill: var(--line-2); }
.an-baum-mini rect.ende { fill: var(--gold); }

.an-baum-mini rect.ausschnitt {
  fill: color-mix(in srgb, var(--brand) 18%, transparent);
  stroke: var(--brand);
  stroke-width: 6;
}

/* Mein Weg */
.an-weg { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }

.an-spielerliste {
  display: grid;
  gap: var(--s2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.an-spielerliste button {
  display: grid;
  gap: 1px;
  width: 100%;
  min-height: var(--touch);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface);
  text-align: left;
}

.an-spielerliste button:hover { border-color: var(--brand); }
.an-spielerliste small { color: var(--ink-3); font-size: 0.8rem; }

.an-weg-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  background: var(--brand-soft);
  color: var(--brand-ink);
}

.an-weg-kopf strong { display: block; }
.an-weg-kopf small { display: block; font-size: 0.8rem; opacity: 0.85; }

.an-weg-kette {
  display: grid;
  gap: var(--s3);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Die Kette sichtbar machen: ein Strich von Karte zu Karte. */
.an-weg-kette li { position: relative; padding-left: var(--s6); }

.an-weg-kette li::before {
  content: "";
  position: absolute;
  top: 18px;
  bottom: -12px;
  left: 9px;
  width: 2px;
  background: var(--line-2);
}

.an-weg-kette li:last-child::before { display: none; }

.an-weg-kette li::after {
  content: "";
  position: absolute;
  top: 14px;
  left: 4px;
  width: 12px;
  height: 12px;
  border: 2px solid var(--line-2);
  border-radius: var(--r-pill);
  background: var(--surface);
}

.an-weg-kette li.naechstes::after { border-color: var(--brand); background: var(--brand); }
.an-wegkarte.gewonnen { border-left-color: var(--brand); }
.an-wegkarte.verloren { border-left-color: var(--st-done); }
.an-weg-kette li.naechstes .an-wegkarte { border-color: var(--brand); }

/* --- Wer noch kommen kann ---------------------------------------------------
   In einer offenen Paarung steht am Telefon nur „Sieger aus Spiel #13“. Ein
   Tippen klappt darunter die Namen auf, die dort noch stehen können; ein
   weiteres Tippen führt auf deren Weg. Die Trefferflächen bleiben bei 44 px
   (ARCHITEKTUR.md, Abschnitt 1) — hier wird im Stehen bedient. */

.an-weg-aufklapp {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  width: 100%;
  min-height: var(--touch);
  margin-top: var(--s2);
  padding: var(--s2) var(--s3);
  border: 1px dashed var(--line-2);
  border-radius: var(--r2);
  background: transparent;
  color: var(--ink-2);
  font-size: 0.85rem;
  text-align: left;
}

.an-weg-aufklapp:hover { border-color: var(--brand); color: var(--ink); }
.an-weg-aufklapp[aria-expanded="true"] { border-style: solid; color: var(--ink); }

/* Die Kette gehört dem Weg, nicht dieser Liste: Ohne das Abschalten bekäme
   jeder mögliche Gegner den Punkt und den Strich der Wegstationen. */
.an-weg-moegliche li { padding-left: 0; }
.an-weg-moegliche li::before,
.an-weg-moegliche li::after { display: none; }

.an-weg-moegliche {
  display: grid;
  gap: var(--s2);
  margin: var(--s2) 0 0;
  padding: 0;
  list-style: none;
}

.an-weg-moegliche button {
  display: grid;
  gap: 1px;
  width: 100%;
  min-height: var(--touch);
  padding: var(--s2) var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface-2);
  text-align: left;
  font-size: 0.9rem;
}

.an-weg-moegliche button:hover { border-color: var(--brand); }
.an-weg-moegliche small { color: var(--ink-3); font-size: 0.78rem; }

.an-weg-gegner b { overflow-wrap: anywhere; }
.an-weg-gegner small { display: block; color: var(--ink-3); font-size: 0.8rem; }

/* Runde für Runde */
.an-rundenwahl {
  display: flex;
  gap: var(--s2);
  margin-bottom: var(--s3);
  overflow-x: auto;
}

.an-rundenwahl button {
  flex: 0 0 auto;
  min-width: var(--touch);
  min-height: var(--touch);
  padding: 0 var(--s3);
  border: 1px solid var(--line-2);
  border-radius: var(--r2);
  background: var(--surface);
  color: var(--ink-2);
  font-weight: 700;
}

.an-rundenwahl button.aktiv {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

.an-rundentitel { margin-bottom: var(--s3); color: var(--ink-3); font-size: 0.85rem; }

/* Gruppenraster */

/* minmax(0, 1fr) statt 1fr, und zwar überall dort, wo ein breiter Inhalt in
   einem Raster steckt: Ein Rasterbereich ist von Haus aus mindestens so breit
   wie sein breitester Inhalt. Eine Kreuztabelle mit sechs Spalten würde die
   Spalte sonst aufblähen und die ganze Seite waagerecht scrollen lassen —
   bei 360 px waren es gemessene 2 Pixel zu viel, und genau die verbietet
   ARCHITEKTUR.md, Abschnitt 1. Gescrollt wird im Kasten, nicht auf der Seite. */
.an-baum-inhalt { min-width: 0; }

.an-gruppe {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s5);
}

.an-raster-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  margin-bottom: var(--s3);
}

.an-raster-kopf h2 { font-size: 1rem; }
.an-raster-kopf p { color: var(--ink-3); font-size: 0.82rem; }
.an-raster-kopf small { color: var(--ink-3); font-size: 0.78rem; white-space: nowrap; }

.an-raster-rollfeld {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--surface);
}

.an-rastertabelle {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.an-rastertabelle th,
.an-rastertabelle td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  text-align: left;
}

.an-rastertabelle thead th {
  background: var(--surface-2);
  font-size: 0.78rem;
  white-space: nowrap;
}

.an-rastertabelle tbody th { min-width: 140px; }
.an-rastertabelle tbody th b { display: block; overflow-wrap: anywhere; }
.an-rastertabelle small { display: block; color: var(--ink-3); font-weight: 400; font-size: 0.74rem; }

.an-raster-nummer {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  margin-right: var(--s2);
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 0.74rem;
  font-weight: 700;
}

.an-raster-zelle {
  min-width: 52px;
  color: var(--ink-2);
  text-align: center;
  cursor: default;
}

.an-raster-diagonale { background: var(--surface-2); color: var(--ink-3); text-align: center; }

/* --- Das Ergebnis in der Kreuzzelle -----------------------------------------
   Wer eine Gruppentabelle liest, sucht das Ergebnis dort, wo sich die beiden
   Namen kreuzen — nicht in einer Liste darunter. Solange nicht gespielt ist,
   steht die Spielnummer da; danach der Satzstand aus Sicht der Zeile.

   Farbe statt Fläche: Ein grüner Zellhintergrund würde mit der
   Kreuz-Hervorhebung streiten, die beim Überfahren die ganze Zeile und Spalte
   einfärbt. */

.an-raster-satz {
  display: block;
  font-size: 0.95rem;
  line-height: 1.2;
}

.an-raster-zelle.gewonnen .an-raster-satz { color: var(--brand-ink); }
.an-raster-zelle.verloren .an-raster-satz { color: var(--ink-3); font-weight: 500; }

.an-raster-punkte {
  display: block;
  margin-top: 2px;
  color: var(--ink-3);
  font-size: 0.72rem;
  font-weight: 400;
  line-height: 1.3;
  /* Auf schmalen Geräten dürfen die Sätze untereinander stehen, statt die
     Spalte breitzuziehen. */
  overflow-wrap: anywhere;
}

.an-raster-nochoffen { color: var(--ink-3); }

/* Die Kreuz-Hervorhebung — ausdrücklicher Wunsch des Auftraggebers. */
.an-rastertabelle .kreuz,
.an-spielliste li.kreuz { background: var(--warn-soft); }
.an-rastertabelle td.kreuz { box-shadow: inset 0 0 0 2px var(--warn); }

.an-tabellenliste,
.an-platzliste {
  display: grid;
  gap: var(--s2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.an-tabellenliste li,
.an-tabellenliste .an-tabellenzeile {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 0.86rem;
}

/* Trägt die Zeile einen Knopf, ist der Knopf die Zeile: Das <li> gibt seinen
   Rahmen ab, sonst stünde ein Kasten im Kasten. Die Klasse steht am Element
   und nicht in einem `:has()` — dieselbe Auskunft, aber ohne die Frage, ab
   welcher Browserfassung sie gilt. */
.an-tabellenliste li.anklickbar {
  display: block;
  padding: 0;
  border: 0;
  background: none;
}

.an-tabellenliste .an-tabellenzeile {
  width: 100%;
  min-height: var(--touch);
  text-align: left;
  color: inherit;
  font: inherit;
  font-size: 0.86rem;
  cursor: pointer;
}

.an-tabellenliste .an-tabellenzeile:hover,
.an-tabellenliste .an-tabellenzeile:focus-visible { border-color: var(--brand); }

.an-tabellenliste strong { color: var(--gold-ink); font-size: 1rem; }
.an-tabellenliste b { display: block; overflow-wrap: anywhere; }
.an-tabellenliste small { display: block; color: var(--ink-3); font-size: 0.76rem; }
.an-tabellenliste em { font-style: normal; color: var(--ink-2); min-width: 3.2em; text-align: right; }

.an-spielliste ol {
  display: grid;
  gap: var(--s2);
  margin: var(--s3) 0 0;
  padding: 0;
  list-style: none;
}

.an-spielliste li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  background: var(--surface-2);
  font-size: 0.85rem;
}

.an-spielliste strong { color: var(--ink-3); }
.an-spielliste i { color: var(--ink-3); font-style: normal; }
.an-spielliste em { font-style: normal; color: var(--ink-2); }

.an-gruppe-hinweis {
  display: grid;
  gap: var(--s3);
  justify-items: start;
  padding: var(--s4);
  border: 1px dashed var(--line-2);
  border-radius: var(--r3);
  color: var(--ink-3);
  font-size: 0.86rem;
}

.an-schweizer { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
.an-schweizer-runde h2 { margin-bottom: var(--s3); font-size: 0.95rem; }

/* Platzierungen */
.an-platzliste li {
  display: grid;
  /* Breit genug für „Plätze 25–32“: Nach einem vorzeitigen Ende teilen sich
     mehrere Meldungen einen Bereich, und der Bereich steht da, wo sonst der
     einzelne Platz steht. Umbrechen darf er nicht — die Zeile wird sonst
     doppelt so hoch wie die daneben. */
  grid-template-columns: 118px minmax(0, 1fr);
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface);
}

.an-platzliste li.offen { border-style: dashed; color: var(--ink-3); }
.an-platzliste strong {
  color: var(--gold-ink);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
.an-platzliste b { display: block; overflow-wrap: anywhere; }
.an-platzliste small { display: block; color: var(--ink-3); font-size: 0.8rem; }


/* --- 9  Ansichtenübersicht (angemeldet) ----------------------------------- */

.an-kachelraster {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s4);
}

.an-kachel {
  display: grid;
  gap: var(--s3);
  align-content: start;
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--surface);
  box-shadow: var(--sh1);
}

.an-kachel-bereich {
  color: var(--gold-ink);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.an-kachel h3 { font-size: 1.02rem; }
.an-kachel p { color: var(--ink-3); font-size: 0.86rem; }

.an-kachel-link {
  padding: var(--s2) var(--s3);
  border-radius: var(--r1);
  background: var(--surface-2);
}

.an-kachel-link code,
.an-overlayliste code {
  font-family: var(--font-num);
  font-size: 0.76rem;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}

.an-qr {
  display: grid;
  justify-items: center;
  padding: var(--s4);
  border-radius: var(--r2);
  background: #fff;
}

.an-qr .qr { width: min(220px, 100%); height: auto; }

.qr-fehler { color: var(--danger); font-size: 0.8rem; }

.an-overlayliste {
  display: grid;
  gap: var(--s2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.an-overlayliste li {
  display: grid;
  gap: var(--s2);
  padding: var(--s3);
  border-radius: var(--r2);
  background: var(--surface-2);
}

.an-schalter {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--touch);
}

.an-schalter input { width: 22px; height: 22px; min-height: 0; }


/* --- 10  Größere Bildschirme ---------------------------------------------- */

@media (min-width: 600px) {
  .an-kartenraster { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
  .an-kachelraster { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
  .an-monitor-zahlen { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .an-naechste-liste { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .an-live-kopf { grid-template-columns: minmax(0, 1fr) minmax(240px, 320px); align-items: end; }
  .an-baum-steuerung { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); align-items: end; }
  /* Vier Spalten: Feld, ON-AIR-Marke, Adresse, Knöpfe. Die Marke bekommt eine
     eigene Spalte fester Breite — läge sie mit der Adresse in derselben,
     schöbe sie den Link bei jedem Anspringen um ihre Breite zur Seite. */
  .an-overlayliste li {
    grid-template-columns: 80px 5.5em minmax(0, 1fr) auto;
    align-items: center;
  }

  /* Die Erklärliste der Designs hat keine Marke und braucht die Spalte nicht. */
  .an-overlayliste li:not(:has(.an-onair-platz)) {
    grid-template-columns: 12em minmax(0, 1fr);
  }
}

@media (min-width: 900px) {
  /* Die Hallenübersicht zeigt ihre Felder erst hier nebeneinander — auf einem
     schmalen Gerät wäre eine Dreierspalte unlesbar, und die Hallenansicht
     läuft dort ohnehin nur zur Kontrolle. */
  .an-feldraster { grid-template-columns: repeat(var(--felder), minmax(0, 1fr)); }

  .an-monitor-raster { grid-template-columns: minmax(0, 1fr) minmax(280px, 360px); align-items: start; }

  /* Höhere Dichte am Turniertisch: mehr Zeilen auf einen Blick. */
  .an-monitor-zeile {
    grid-template-columns: auto minmax(0, 1fr) 8em 4.5em auto auto;
    font-size: 0.84rem;
  }
  .an-monitor-saetze,
  .an-monitor-punkte { display: block; text-align: right; }

  .an-live { padding: var(--s6); }
  .an-baumseite { padding: var(--s6); }
  .an-monitor { padding: var(--s6); }
  .an-halle { padding: var(--s5); gap: var(--s4); }
}

@media (min-width: 1200px) {
  .an-rastertabelle { font-size: 0.9rem; }
  .an-baum-rollfeld { max-height: calc(100dvh - 260px); }
}

/* Fingerbedient heißt große Flächen, unabhängig von der Breite. */
@media (pointer: coarse) {
  .an-baum-reiter button { min-height: var(--touch); }
  .an-raster-zelle { min-height: var(--touch); }
}

@media print {
  .an-baum-rollfeld { max-height: none; overflow: visible; }
  .an-baum-mini,
  .an-baum-reiter,
  .an-sichtwahl { display: none; }
}


/* --- 11  Auswahlseite am Fernseher (UEBERGABE.md, Abschnitt 10.3) ----------
   Hinter der kurzen Adresse `/t/248625`. Bedient wird sie mit einer
   **Fernbedienung**, und das ist keine Kleinigkeit:

     * Der Fokusrahmen muss aus mehreren Metern erkennbar sein — dick, farbig
       und in der Fläche, nicht der dünne Standard des Browsers.
     * Die Ziffer steht groß auf der Kachel, weil die Zifferntaste der
       schnellste Weg ist.
     * Die Schrift ist absolut bemaßt: Der Betrachter sitzt weit weg, und die
       Schriftgröße des Fernsehers sagt darüber nichts aus.
   -------------------------------------------------------------------------- */

.tv-seite {
  display: grid;
  align-content: start;
  gap: 28px;
  min-height: 100dvh;
  padding: clamp(20px, 4vw, 56px);
  background: var(--nav-bg);
  color: var(--nav-ink);
}

.tv-kopf h1 {
  margin: 0;
  font-size: clamp(28px, 4vw, 52px);
  line-height: 1.1;
}

.tv-kopf p {
  margin: 10px 0 0;
  color: var(--nav-ink-2);
  font-size: clamp(15px, 1.6vw, 22px);
}

/* Die Mindestbreite ist auf den **längsten Titel** ausgelegt, nicht auf eine
   möglichst dichte Reihe: „Hallenübersicht“ braucht neben Ziffer, Abstand und
   Polsterung rund 380 px, sonst wird das Wort getrennt — bei 260 px auf einem
   Fernseher sogar über drei Zeilen. Lieber vier breite Kacheln und eine in der
   zweiten Reihe als fünf schmale mit zerhackten Wörtern.

   `min(380px, 100%)` und nicht `380px`: Eine feste Mindestbreite ist eine
   Mindestbreite auch dann noch, wenn das Fenster schmaler ist als sie — die
   Spur ragte dann über den Rand hinaus, und die Seite ließ sich waagerecht
   schieben (ARCHITEKTUR.md, Abschnitt 1). Mit `min()` gibt die Spur auf
   schmalen Geräten nach. */
.tv-kacheln {
  display: grid;
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr));
}

/* Der Listenpunkt ist nur ein Behälter — er reicht die Höhe seiner Rasterzeile
   an den Knopf darin weiter. Ohne das richtete sich jeder Knopf nach seinem
   eigenen Text: Eine Beschreibung, die in zwei statt in drei Zeilen passt,
   ergäbe eine sichtbar niedrigere Kachel in derselben Reihe. */
.tv-kacheln > li { display: grid; }

.tv-kachel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "ziffer titel" "ziffer text";
  gap: 4px 20px;
  width: 100%;
  height: 100%;
  min-height: 120px;
  padding: 20px 24px;
  border: 3px solid transparent;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.07);
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-align: left;
}

.tv-kachel:hover { background: rgba(255, 255, 255, 0.13); }

/* Der Fokusrahmen ist hier das wichtigste Gestaltungsmittel überhaupt: Er ist
   die einzige Rückmeldung, die eine Fernbedienung gibt. */
.tv-kachel:focus-visible,
.tv-kachel:focus {
  border-color: var(--gold-bright);
  background: rgba(232, 181, 63, 0.18);
  outline: 4px solid var(--gold-bright);
  outline-offset: 3px;
}

.tv-ziffer {
  grid-area: ziffer;
  display: grid;
  place-items: center;
  align-self: center;
  width: 60px;
  height: 60px;
  border-radius: 12px;
  background: var(--gold-bright);
  color: #1a1207;
  font-family: var(--font-num);
  font-size: 32px;
  font-weight: 800;
}

/* „Hallenübersicht“ und „Gesamtübersicht“ sind länger als die Textspalte einer
   schmalen Kachel — und ein Wort bricht von sich aus nicht. Es lief deshalb
   über den Rand der Kachel hinaus.

   `hyphens: auto` trennt zuerst nach den Regeln der Sprache (das Blatt steht
   unter `<html lang="de">`), also „Hallen-übersicht“ statt mitten im Wort.
   `overflow-wrap: anywhere` ist die Rückfallebene für den Fall, dass auch die
   Silbe nicht mehr passt: Dann sieht der Umbruch schlechter aus, aber nichts
   steht außerhalb seiner Kachel. */
.tv-titel {
  grid-area: titel;
  font-size: clamp(20px, 2.2vw, 30px);
  font-weight: 700;
  hyphens: auto;
  overflow-wrap: anywhere;
}

.tv-text {
  grid-area: text;
  color: var(--nav-ink-2);
  font-size: clamp(14px, 1.3vw, 18px);
  hyphens: auto;
  overflow-wrap: anywhere;
}

/* Feldkacheln tragen nur „Feld 7“ — trotzdem **nicht** schmaler als die
   übrigen. Bei 180 px blieben nach Ziffer, Abstand und Polsterung rund 70 px
   für die Beschriftung, und selbst das kurze Wort „Feld“ passte nicht mehr in
   eine Zeile: Es wurde zu „Fe-“ und „ld“ getrennt. Eine Trennung mitten in
   einem Wort mit vier Buchstaben sieht nach Fehler aus, und auf einem
   Fernseher ist Platz genug — die Kachel darf lieber größer sein. */
.tv-felder { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
.tv-feld { min-height: 110px; }

.tv-fuss {
  color: var(--nav-ink-2);
  font-size: clamp(13px, 1.2vw, 17px);
}

.tv-zurueck {
  padding: 12px 22px;
  min-height: var(--touch);
  border: 2px solid var(--nav-ink-2);
  border-radius: 10px;
  background: transparent;
  color: var(--nav-ink);
  cursor: pointer;
  font: inherit;
  font-size: 18px;
}

.tv-zurueck:focus-visible { outline: 4px solid var(--gold-bright); outline-offset: 3px; }

.tv-laden,
.tv-leer { color: var(--nav-ink-2); font-size: 22px; }

.tv-hinweis h1 { margin: 0 0 12px; font-size: clamp(26px, 3.4vw, 44px); }
.tv-hinweis p { margin: 0; color: var(--nav-ink-2); font-size: clamp(15px, 1.6vw, 22px); max-width: 40em; }

/* „Ansicht wechseln“ — klein, am Rand, aber dauerhaft sichtbar. Ohne ihn käme
   ein Fernseher nie wieder aus seiner gemerkten Ansicht heraus. */
.an-wechseln {
  position: fixed;
  right: 10px;
  bottom: calc(10px + var(--safe-bottom));
  z-index: 40;
  padding: 8px 14px;
  min-height: var(--touch);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--r-pill);
  background: rgba(15, 31, 26, 0.75);
  color: #e6ece9;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  opacity: 0.55;
}

.an-wechseln:hover,
.an-wechseln:focus-visible { opacity: 1; outline: 3px solid var(--gold-bright); }


/* --- 12  ON AIR und kurze Adresse in der Verwaltung -----------------------
   Die Marke blinkt grün/rot im Sekundentakt, solange auf dem Feld ein Spiel
   steht (UEBERGABE.md, Abschnitt 10.2). `steps(1, end)` schaltet hart um,
   statt weich zu blenden — genau so macht es der Vorgänger, und im
   Augenwinkel am Turniertisch fällt nur das harte Umschalten auf.
   -------------------------------------------------------------------------- */

/* Der Platz bleibt auch leer stehen: Sonst rutschte die Adresse jedes Mal
   zur Seite, wenn ein Spiel beginnt oder endet — und das tut sie den ganzen
   Turniertag über. */
.an-onair-platz { display: inline-flex; align-items: center; min-height: 1.6em; }

.an-on-air {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r1);
  color: #fff;
  font-family: var(--font-num);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  animation: an-on-air-blink 1s steps(1, end) infinite;
}

@keyframes an-on-air-blink {
  0%,  49% { background: #1f8a4c; }
  50%, 100% { background: #b3261e; }
}

/* Wer Bewegung im Bild nicht verträgt, bekommt die Auskunft ohne Blinken —
   die Farbe allein sagt dasselbe. */
@media (prefers-reduced-motion: reduce) {
  .an-on-air { animation: none; background: #b3261e; }
}

.an-kurzadresse .an-kurzcode { margin: 0; }

/* Die Knöpfe stehen auf derselben Linie wie die Ziffern, nicht mittig zur
   Beschriftung darüber: Sonst schwebt die Reihe einen Zeilenabstand zu hoch,
   seit die Zahl einen Aufsatz bekommen hat. */
.an-kurzadresse .reihe { align-items: end; }

/* Beschriftung über den Ziffern. Sie steht **über** und nicht neben ihnen,
   damit die Zahl selbst als Block zusammenbleibt: Gerade sechs gesperrte
   Ziffern liest man in einem Blick ab, mit Text daneben liest man sie in
   zweien. */
.an-tippcode {
  display: inline-grid;
  gap: 2px;
  justify-items: start;
}

.an-tippcode small {
  color: var(--ink-3);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.an-grosser-code {
  padding: var(--s2) var(--s4);
  border-radius: var(--r2);
  background: var(--surface-2);
  color: var(--ink);
  font-family: var(--font-num);
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: 0.16em;
}

.an-farbtupfer {
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-right: var(--s2);
  border: 1px solid var(--line-2);
  border-radius: 3px;
  vertical-align: -0.15em;
}

/* --- Liveticker einer Mannschaftsbegegnung ---------------------------------
 * Der Mannschaftsstand über den Einzelspielen — das Einzige, was den Ticker
 * von der Turnier-Livewertung unterscheidet (UEBERGABE.md, Abschnitt 13.7).
 * Bei einem Turnier liefert der Server hier nichts, und der Block entfällt.
 *
 * Er wird auf dem Telefon gelesen und aus einigen Metern auf einen Fernseher
 * geworfen. Deshalb sind die Zahlen das größte Element der Seite und die
 * Mannschaftsnamen brechen um, statt zu kürzen — „TSV Musterst…“ hilft
 * niemandem. */

.an-ticker {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--s3);
  margin-bottom: var(--s5);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface);
}

.an-ticker-seite {
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 1.05rem;
}

.an-ticker-seite:last-of-type { text-align: right; }
.an-ticker-seite.sieger { font-weight: 700; }

.an-ticker-stand {
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
}

.an-ticker-stand span {
  padding: 0 0.15em;
  color: var(--ink-3);
}

.an-ticker-rest {
  grid-column: 1 / -1;
  margin-top: var(--s2);
  color: var(--ink-3);
  font-size: 0.9rem;
  text-align: center;
}

@media (min-width: 900px) {
  .an-ticker-stand { font-size: 3.4rem; }
  .an-ticker-seite { font-size: 1.3rem; }
}


/* --- 11  Modul Werbung ----------------------------------------------------
   Zwei Dinge in einem Abschnitt, weil beide zur Werbung gehören und sonst
   auseinanderdrifteten:

   a) der **Reiter** an der Veranstaltung — eine Bedienoberfläche, also
      mobil zuerst, Fingerflächen, einspaltig;
   b) das **Vollbild am Feld-Fernseher** — eine Anzeige, also groß, dunkel
      und ohne Beiwerk (ARCHITEKTUR.md, Abschnitt 1: für Anzeigen gilt die
      Dichte-Regel ausdrücklich nicht).
   -------------------------------------------------------------------------- */

.hinweisfeld.warnung {
  border-left-color: var(--danger);
  color: var(--ink-2);
}

.wb-liste {
  display: grid;
  gap: var(--s4);
}

.wb-mittel {
  display: grid;
  gap: var(--s4);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--surface-2);
}

/* Ein abgeschaltetes Bild bleibt sichtbar, tritt aber zurück: Es ist weiterhin
   da und lässt sich mit einem Haken zurückholen — nur erscheint es gerade auf
   keiner Anzeige. Ausgegraut sagt das ohne ein weiteres Wort. */
.wb-mittel.aus { opacity: 0.62; }

.wb-bild {
  display: grid;
  place-items: center;
  padding: var(--s3);
  border-radius: var(--r1);
  /* Karierter Grund: Ein Sponsorenlogo ist oft ein PNG mit durchsichtigem
     Hintergrund. Auf weißer Fläche sähe man nicht, wo das Bild aufhört — und
     im dunklen Farbschema verschwände schwarze Schrift ganz. */
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #e9e9e9 25%, transparent 25%, transparent 75%, #e9e9e9 75%),
    linear-gradient(45deg, #e9e9e9 25%, transparent 25%, transparent 75%, #e9e9e9 75%);
  background-position: 0 0, 8px 8px;
  background-size: 16px 16px;
}

.wb-bild img {
  max-width: 100%;
  max-height: 120px;
  object-fit: contain;
}

.wb-angaben {
  display: grid;
  gap: var(--s3);
  min-width: 0;
}

.wb-vorschau {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}

.wb-vorschau img {
  max-width: 140px;
  max-height: 60px;
  padding: var(--s2);
  border-radius: var(--r1);
  background: #fff;
  object-fit: contain;
}

@media (min-width: 700px) {
  /* Bild links, Angaben rechts. Erst ab dieser Breite: Darunter stünde das
     Bild in einer Spalte von Daumenbreite. */
  .wb-mittel { grid-template-columns: minmax(0, 220px) minmax(0, 1fr); }
  /* Der Kasten bleibt so hoch wie das Bild und nicht so hoch wie die
     Formularspalte daneben. Bei einem Hallenbanner — sechsmal so breit wie
     hoch — stünde sonst ein handtellergroßes Karomuster neben einem
     fingerbreiten Streifen. */
  .wb-bild { align-self: start; }
}

/* b) Vollbild am Feld-Fernseher ------------------------------------------- */

.an-tv-werbung {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  place-items: center;
  padding: 2vmin;
  /* Schwarz und nicht die Seitenfarbe: Der Bildschirm zeigt jetzt nichts als
     das Sponsorenbild, und jeder Rahmen ringsum nähme ihm Fläche. */
  background: #000;
}

.an-tv-werbung img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.an-tv-werbefuss {
  padding-top: 1.5vh;
  color: rgba(255, 255, 255, 0.55);
  font-size: clamp(0.9rem, 1.6vw, 1.5rem);
  letter-spacing: 0.04em;
}


/* --- 12  Modul Ansagen ----------------------------------------------------
   Wie beim Modul Werbung zwei Dinge in einem Abschnitt, weil beide zu den
   Ansagen gehören:

   a) der **Reiter** an der Veranstaltung (`as-…`) — eine Bedienoberfläche,
      also mobil zuerst, einspaltig, mit Fingerflächen;
   b) der **Bildschirm am Lautsprecher** (`ans-…`) — eine Anzeige, und zwar
      eine besondere: Sie wird aus mehreren Metern angesehen, meist im
      Vorbeigehen, und sie muss eine einzige Frage sofort beantworten — läuft
      der Ton oder nicht. Deshalb ist der Zustand hier eine ganzseitige Fläche
      und keine Zeile am Rand (UEBERGABE.md, Abschnitt 17.6).
   -------------------------------------------------------------------------- */

/* a) Der Reiter ------------------------------------------------------------ */

.as-liste { display: grid; gap: var(--s3); }

.as-eintrag { display: grid; gap: var(--s2); }

.as-satz {
  font-size: 1.02rem;
  line-height: 1.35;
  color: var(--ink);
}

/* Erledigtes tritt zurück, bleibt aber lesbar: Die Frage „ist meine Durchsage
   durch?“ wird genau daran beantwortet, also darf es nicht verschwinden. */
.as-eintrag.gespielt .as-satz,
.as-eintrag.abgebrochen .as-satz { color: var(--ink-3); }
.as-eintrag.abgebrochen .as-satz { text-decoration: line-through; }

.as-zahlen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

.as-kennzahl { display: grid; }
.as-kennzahl b { font-size: 1.7rem; line-height: 1.1; color: var(--ink); }
.as-kennzahl small { color: var(--ink-3); font-size: 0.82rem; }

.as-arten {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

.as-fehlend summary { cursor: pointer; color: var(--ink-2); font-size: 0.9rem; }
.as-fehlend ul {
  margin: var(--s3) 0 0;
  padding-left: var(--s5);
  display: grid;
  gap: var(--s2);
  font-size: 0.9rem;
}
.as-fehlend em { color: var(--ink-3); font-style: normal; font-size: 0.85rem; }

/* Die Tabelle der Aussprachehilfen scrollt in ihrem eigenen Kasten und reißt
   die Seite bei 360 px nicht in die Breite (ARCHITEKTUR.md, Abschnitt 1). */
.as-tabelle {
  display: block;
  overflow-x: auto;
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.as-tabelle th,
.as-tabelle td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line);
  text-align: left;
  white-space: nowrap;
}
.as-tabelle th { color: var(--ink-3); font-weight: 600; }

.as-ausspracheform { display: grid; gap: var(--s3); }


/* b) Der Bildschirm am Lautsprecher ---------------------------------------- */

.ans-seite {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 2vh;
  padding: 3vmin;
}

.ans-kopf {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  align-items: baseline;
  justify-content: space-between;
}

.ans-kopf h1 { margin: 0; font-size: clamp(1.4rem, 3vw, 2.4rem); }
.ans-kopf p { margin: 0; color: var(--ink-3); font-size: clamp(0.9rem, 1.6vw, 1.3rem); }

.ans-zustand {
  display: flex;
  /* Umbrechen statt überstehen: Zustand, Stummschalter, Hintergrundschalter
     und in einer geteilten Halle der Knopf ⚙ Klang sind zusammen breiter als
     ein Telefon. Ohne Umbruch zieht der Browser die ganze Seite breiter — und
     das Menü von unten ragt rechts aus dem Bild (Abschnitt 17.20). */
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  align-items: center;
  font-size: clamp(0.9rem, 1.5vw, 1.2rem);
  color: var(--ink-2);
}

.ans-punkt {
  width: 0.9em;
  height: 0.9em;
  border-radius: var(--r-pill);
  background: var(--danger);
}
.ans-punkt.an { background: var(--brand); }
/* Stumm ist ein dritter Zustand und nicht „aus“: Der Bildschirm arbeitet, er
   gibt nur keinen Ton. Deshalb die Warnfarbe und nicht das Rot des
   Ausgeschalteten — und ein Ring statt einer vollen Fläche, damit man die
   drei auch aus einigen Metern auseinanderhält. */
.ans-punkt.stumm {
  background: transparent;
  box-shadow: inset 0 0 0 0.22em var(--warn);
}

/* Das Band unter dem Kopf, solange stumm geschaltet ist.

   Es steht dauerhaft da und nicht als kurze Meldung: Ein stummer Bildschirm
   sieht aus wie ein arbeitender — die Warteschlange leert sich, der Verlauf
   füllt sich, alles wirkt richtig. Ohne das Band fiele es erst auf, wenn
   jemand in der Halle nachfragt, warum niemand aufgerufen wird. */
.ans-stummband {
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  background: var(--warn-soft, var(--surface-2));
  color: var(--ink);
  border: 1px solid var(--warn);
  font-size: clamp(0.95rem, 1.6vw, 1.2rem);
  line-height: 1.4;
}

.ans-stummband strong { display: block; }

/* Die ganzseitige Zustandsfläche. Sie ist das größte Element der Seite, weil
   sie die einzige Frage beantwortet, die aus fünf Metern zu lesen sein muss. */
.ans-gross {
  display: grid;
  place-content: center;
  gap: 2vh;
  padding: 4vmin;
  border-radius: var(--r3);
  text-align: center;
}

.ans-marke {
  margin: 0;
  font-size: clamp(1.6rem, 5vw, 4rem);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.ans-satz {
  margin: 0;
  font-size: clamp(1.3rem, 3.4vw, 2.8rem);
  line-height: 1.3;
}

.ans-erklaerung {
  margin: 0 auto;
  max-width: 46ch;
  font-size: clamp(0.95rem, 1.7vw, 1.3rem);
  line-height: 1.5;
  color: var(--ink-2);
}

/* Rot und nicht gelb: Hier ist nichts zu beachten, hier ist etwas kaputt —
   und zwar so, dass es sonst niemandem auffällt. */
.ans-stumm {
  border: 2px solid var(--danger);
  background: var(--danger-soft);
}
.ans-stumm .ans-marke { color: var(--danger); }

.ans-bereit { background: var(--surface-2); }
.ans-bereit .ans-marke { color: var(--ink-3); }

.ans-spricht {
  border: 2px solid var(--brand);
  background: var(--brand-soft);
}
.ans-spricht .ans-marke { color: var(--brand-ink); }

.ans-aus { background: var(--surface-2); }
.ans-aus .ans-marke { color: var(--ink-3); }

/* Der Aktivierknopf ist mit Absicht überdimensioniert: Er wird einmal am Tag
   gedrückt, oft von jemandem, der nur schnell den Rechner hochgefahren hat —
   und wird er vergessen, bleibt die Halle still. */
.knopf.gross {
  min-height: 4rem;
  padding: 0 var(--s8);
  font-size: clamp(1.1rem, 2.2vw, 1.6rem);
  justify-self: center;
}

.ans-lauf {
  display: grid;
  gap: 2vh;
  align-content: start;
  min-height: 0;
  overflow-y: auto;
}

.ans-liste h2 {
  margin: 0 0 var(--s2);
  font-size: clamp(0.95rem, 1.6vw, 1.2rem);
  color: var(--ink-3);
  font-weight: 600;
}

/* **Das Polster muss mit der Schrift wachsen.** Ein Listenzeichen steht bei
   `list-style-position: outside` links außerhalb des Inhalts, also im Polster
   der Liste. Hier stand dort ein fester Wert (20px), während die Schrift bis
   1,4rem wächst — auf dem Hallenbildschirm ist „10.“ dann rund 29px breit und
   ragte neun Pixel nach links hinaus.

   Dort wurde es abgeschnitten, und zwar von `.ans-lauf`: Wer `overflow-y`
   setzt, bekommt vom Browser `overflow-x` gleich mit, und nach links lässt
   sich nicht scrollen. Aus den Nummern wurden Halbmonde.

   Deshalb in `em` und bemessen nach der breitesten Nummer, die vorkommen
   kann: „100.“ misst 1,92em, mit Abstand zum Text sind 2,2em genug. */
.ans-liste ol {
  margin: 0;
  padding-left: 2.2em;
  display: grid;
  gap: var(--s2);
  font-size: clamp(0.95rem, 1.8vw, 1.4rem);
  line-height: 1.35;
}

/* Die Bezeichnung des Spiels an einer Durchsage — „HE O19 · #13 ·
   Viertelfinale“. Sie wird nicht gesprochen; sie beantwortet am Bildschirm die
   Frage, welches Spiel gemeint ist, wenn dieselbe Paarung an einem Tag
   mehrfach vorkommt. Deshalb zurückhaltend und vorangestellt: Der gesprochene
   Satz bleibt die Hauptsache. */
.ans-spielzeile { margin: 0 0 var(--s2); }

.ans-spielmarke {
  display: inline-block;
  padding: 1px var(--s2);
  border-radius: var(--r1);
  background: var(--surface-3);
  color: var(--ink-3);
  font-size: 0.78em;
  font-weight: 700;
  white-space: nowrap;
  vertical-align: middle;
}

.ans-verlauf ol { color: var(--ink-3); }
.ans-verlauf .zahl { margin-right: var(--s3); }

/* Der Verlauf ist Werkzeug und nicht Chronik: Jede Zeile trägt rechts ihren
   Wiederholungsknopf. Er steht dort und nicht am Turniertisch, weil der Weg
   dorthin in einer Halle zu weit ist, wenn beim ersten Mal die Hälfte nicht
   hingehört hat. */
.ans-verlauf li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--s2);
}

.ans-verlauf .ans-satzteil { display: block; min-width: 0; }

/* Nicht hörbar gewesen — der eine Fall, den bisher niemand erfuhr. Er steht
   deshalb in Warnfarbe und nicht als Fußnote. */
.ans-verlauf li.missraten { color: var(--warn); }

.ans-verlauf .ans-fehler {
  display: block;
  font-size: 0.8em;
  font-weight: 600;
}

.ans-verlauf .marke { vertical-align: middle; }

@media (min-width: 900px) {
  /* Auf einem großen Bildschirm nimmt die Zustandsfläche mindestens die halbe
     Höhe ein. Darunter wäre sie eine Zeile unter anderen — genau das, was sie
     nicht sein darf. */
  .ans-lauf { grid-template-rows: minmax(45vh, auto) auto auto; }
}

/* Die drei Auslöser im Reiter „Ansagen“: Eingabe und Knopf nebeneinander,
   sobald Platz ist — darunter untereinander, weil ein Auswahlfeld mit einem
   ganzen Satz darin bei 360 px keinen Knopf neben sich duldet. */
.as-ausloesen {
  display: grid;
  gap: var(--s3);
  align-items: end;
}

@media (min-width: 620px) {
  .as-ausloesen { grid-template-columns: minmax(0, 1fr) auto; }
  .as-ausloesen:has(> button ~ button) { grid-template-columns: minmax(0, 1fr) auto auto; }
}

/* Der Regler für die Gong-Lautstärke (UEBERGABE.md, Abschnitt 17.18).
   Regler und Probeknopf in einer Zeile: Die Bewegung ist schieben, hören,
   schieben, hören — der Knopf gehört also direkt daneben und nicht darunter. */
.as-gongregler {
  display: flex;
  align-items: center;
  gap: var(--s3);
}
.as-gongregler input[type="range"] {
  flex: 1;
  min-width: 0;
  min-height: var(--touch);
  accent-color: var(--brand);
}

/* Eigene Durchsagen (UEBERGABE.md, Abschnitt 17.16).

   Eine Liste von Sätzen, keine Tabelle: Es gibt nur eine Spalte mit Inhalt,
   und Sätze sind verschieden lang. In einer Tabelle stünde die Hälfte der
   Zeilen halb leer. */
.as-durchsagen {
  display: grid;
  gap: var(--s2);
  list-style: none;
  padding: 0;
  margin: 0;
}

.as-durchsagen li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: var(--s2) var(--s3);
  align-items: center;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--surface);
}

/* Der Satz darf umbrechen — er ist bis zu vierhundert Zeichen lang, und
   abgeschnitten wäre er in einer Liste zum Wiedererkennen wertlos. Darunter
   der Hinweis, dass er noch keinen Ton hat. */
.as-durchsagen li > span {
  display: grid;
  min-width: 0;
  overflow-wrap: anywhere;
}
.as-durchsagen li > span .as-fehlt { color: var(--warn); font-size: 0.8rem; }

@media (max-width: 560px) {
  /* Auf dem Telefon rutschen die Knöpfe unter den Satz, statt ihn auf drei
     Zeichen zusammenzuquetschen. */
  .as-durchsagen li { grid-template-columns: minmax(0, 1fr) auto auto; }
  .as-durchsagen li > span { grid-column: 1 / -1; }
}

/* Die Prüfliste — der Arbeitsplatz für den Abend vor dem Turnier.
   Zweihundert Zeilen, die man von oben nach unten durchhört: Der Haken steht
   deshalb links, wo das Auge beim Abarbeiten hinspringt, und die Zeile wird
   blass, sobald er gesetzt ist. */
.as-namenfilter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  align-items: end;
}

.as-namen {
  display: grid;
  gap: var(--s2);
  /* Bei zweihundert Namen ist die eigene Bildlaufleiste angenehmer als eine
     Seite, die vier Bildschirme lang wird. */
  max-height: 32rem;
  overflow-y: auto;
  padding-right: var(--s2);
}

.as-name {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--s2) var(--s3);
  align-items: center;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--surface);
}

.as-name.abgehakt { opacity: 0.55; }

/* Arten, deren Wortlaut im Programm steht: hören und abhaken, mehr gibt es
   nicht zu tun. Die Zeile endet deshalb nach dem Abspielknopf. */
.as-name.nurhoeren { grid-template-columns: auto minmax(0, 1fr) auto; }

.as-haken { display: flex; align-items: center; }
.as-haken input { width: 1.2rem; height: 1.2rem; }

.as-namentext { display: grid; min-width: 0; }
.as-namentext small { color: var(--ink-3); font-size: 0.8rem; }
.as-namentext .as-fehlt { color: var(--warn); }

.as-name input[type="text"],
.as-name select {
  grid-column: 2 / -1;
  min-height: var(--touch);
}

@media (min-width: 860px) {
  /* Ab hier steht alles in einer Zeile: Haken, Name, Anhören, Aussprache,
     Sprache, Übernehmen. Genau das ist die Arbeitsbewegung — hören, tippen,
     abhaken, nächste Zeile. */
  .as-name {
    grid-template-columns:
      auto minmax(9rem, 1fr) auto minmax(9rem, 1fr) minmax(7rem, auto) auto;
  }
  .as-name.nurhoeren { grid-template-columns: auto minmax(0, 1fr) auto; }
  .as-name input[type="text"],
  .as-name select { grid-column: auto; min-height: 0; }
}

/* Das Menü ⚙ Klang am Bildschirm einer geteilten Halle (UEBERGABE.md,
   Abschnitt 17.20).

   Es hängt **außerhalb** der Seite am Dokument: Die Seite wird alle drei
   Sekunden neu gezeichnet, und ein Menü darin verlöre dabei mitten im
   Schieben den Regler.

   Zwei Gestalten, eine Regel dahinter — die laufende Ansage bleibt sichtbar.
   Am Laptop eine Leiste von rechts, am Tablet und Telefon eine Fläche von
   unten; dort ist der Daumen, und die Ansage steht oben. */
.ans-klang-huelle {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgb(0 0 0 / 0.35);
}

.ans-klang {
  position: fixed;
  z-index: 61;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(26rem, 92vw);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sh2, 0 8px 32px rgb(0 0 0 / 0.25));
  font-size: 1.05rem;
}

.ans-klang-kopf,
.ans-klang-fuss {
  display: flex;
  gap: var(--s3);
  align-items: center;
  justify-content: space-between;
  padding: var(--s4);
}
.ans-klang-kopf { border-bottom: 1px solid var(--line); }
.ans-klang-kopf h2 { margin: 0; font-size: 1.3rem; }
.ans-klang-fuss { border-top: 1px solid var(--line); }

.ans-klang-inhalt {
  overflow-y: auto;
  padding: var(--s4);
  display: grid;
  gap: var(--s4);
  align-content: start;
}

/* Großzügige Ziele: Bedient wird im Stehen, oft am Tablet neben dem Mischpult. */
.ans-klang select,
.ans-klang input[type="number"] { min-height: var(--touch); width: 100%; }
.ans-klang .as-gongregler input[type="range"] { min-height: calc(var(--touch) * 1.1); }

@media (max-width: 720px) {
  .ans-klang {
    top: auto;
    left: 0;
    width: auto;
    max-height: 85vh;
    border-radius: var(--r2) var(--r2) 0 0;
  }
}

/* Der Schiebeschalter „Auch im Hintergrund“ auf dem Bildschirm am
   Lautsprecher. Bewusst ein Schieber und kein Kästchen: Er wird aus einigen
   Metern angesehen, und ein Schieber sagt seinen Zustand über die Stellung,
   nicht über ein Häkchen. */
.ans-schalter {
  display: inline-flex;
  gap: var(--s2);
  align-items: center;
  cursor: pointer;
  user-select: none;
}

.ans-schalter input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.ans-schieber {
  position: relative;
  width: 2.6em;
  height: 1.4em;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--line-2);
  transition: background 0.15s;
}

.ans-schieber::after {
  content: "";
  position: absolute;
  top: 0.15em;
  left: 0.15em;
  width: 1.1em;
  height: 1.1em;
  border-radius: var(--r-pill);
  background: #fff;
  box-shadow: var(--sh1);
  transition: transform 0.15s;
}

.ans-schalter input:checked + .ans-schieber { background: var(--brand); }
.ans-schalter input:checked + .ans-schieber::after { transform: translateX(1.2em); }

/* Sichtbarer Fokusrahmen — der Schalter muss mit der Tastatur erreichbar
   bleiben (ARCHITEKTUR.md, Abschnitt 1, Regeln für den Desktop). */
.ans-schalter input:focus-visible + .ans-schieber {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* Der Ladebalken beim Freigeben des Tons. Er ist die Antwort auf „ich habe
   gedrückt, und es passiert nichts“ — dazwischen liegt eine Viertelmegabyte
   Gong, und ohne Anzeige drückt man noch einmal. */
.ans-balken {
  width: min(22rem, 70%);
  height: 0.6rem;
  margin: 0 auto;
  overflow: hidden;
  border-radius: var(--r-pill);
  background: var(--surface-3);
}

.ans-balken span {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--brand);
  transition: width 0.2s;
}

/* Kennt die Antwort ihre Länge nicht, läuft ein Streifen hin und her, statt
   eine Zahl zu erfinden. */
.ans-balken.offen span {
  width: 35% !important;
  animation: ans-warten 1.1s ease-in-out infinite alternate;
}

@keyframes ans-warten {
  from { transform: translateX(-40%); }
  to   { transform: translateX(220%); }
}

/* Die DSQ-Marke am Namen im öffentlichen Turnierbaum. Die Regel steht auch in
   turnierbetrieb.css — die Anzeigen laden dieses Blatt nicht mit, und ein
   Beamer soll dieselbe Marke zeigen wie der Turniertisch. */
.dsq-marke {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0 0.35em;
  border-radius: var(--r1);
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.7em;
  font-weight: 700;
  letter-spacing: 0.03em;
  vertical-align: 0.08em;
}


/* --- 13  Zuschaueransicht einer Mannschaftsbegegnung ----------------------
   Die Tafel für Beamer und Wandfernseher: oben der Mannschaftsstand, darunter
   je Einzelspiel eine Zeile. Übernommen aus der Vorgängeranwendung sind
   **Inhalt und Hervorhebungen**, nicht die Gestaltung.

   Sie ist dunkel wie die übrigen Hallenanzeigen und rechnet ihre Zeilenhöhe
   aus der verfügbaren Höhe: Auf einem Fernseher kann niemand scrollen, und
   acht Einzelspiele müssen ebenso auf ein Bild passen wie vier.
   ------------------------------------------------------------------------ */

.an-begegnung {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: var(--s3);
  height: 100dvh;
  padding: clamp(8px, 1.4vw, 22px);
  background: var(--nav-bg);
  color: #fff;
  overflow: hidden;

  /* Kopf und Zwischenzeile abgezogen, der Rest geteilt durch die Zeilenzahl.
     Der Deckel verhindert, dass vier Spiele albern groß werden. */
  /* Kopf, Zwischenzeile, Tabellenkopf und die Zwischenräume zwischen den
     Zeilen sind abgezogen. Zu großzügig gerechnet fällt die letzte Zeile
     unten heraus — auf einem Fernseher fehlt sie dann einfach, ohne dass es
     jemand merkt. */
  /* Je Zeile kommen zum Zellenmaß noch Rahmen (2 × 3 px), Innenabstand
     (2 × 3 px) und der Zwischenraum zur nächsten Zeile (5 px) — zusammen
     17 px. Ohne diesen Abzug fällt die letzte Zeile unten heraus, und auf
     einem Fernseher fehlt sie einfach, ohne dass es jemand merkt. */
  --zeilenhoehe: min(84px,
    calc((100dvh - clamp(180px, 25vh, 250px)
          - var(--zeilen) * 17px) / var(--zeilen)));
  --bg-schrift: clamp(0.7rem, calc(var(--zeilenhoehe) * 0.3), 1.9rem);
  --gastfarbe: #9aa7a1;
}

/* --- Kopf: Heim, Stand, Gast ------------------------------------------- */

.an-bg-kopf {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--s2);
}

.an-bg-team {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 1.2vw, 20px);
  min-width: 0;
  padding: clamp(6px, 1.2vh, 16px) var(--s4);
  border-radius: var(--r2);
  font-size: clamp(1rem, 2.6vw, 2.6rem);
  font-weight: 800;
  line-height: 1.05;
  text-align: center;
}

/* Umbrechen statt abschneiden: „TuS 1885 Musterhausen-Oberdorf II“ ist ein
   ganz gewöhnlicher Mannschaftsname, und abgeschnitten wäre er wertlos. */
.an-bg-team span { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }

/* Das Vereinslogo **links neben** dem Namen, so hoch wie die Box innen.
   
   Die Box streckt sich ohnehin auf die Höhe des Punktestands daneben, und der
   Name füllt sie bei Weitem nicht aus (Auftraggeber, 23.09.2026). `stretch`
   holt genau diesen Platz, ohne die Box höher zu machen — die Tafel bleibt
   damit bildschirmfüllend ohne Rollbalken.

   `contain` und eine Breitengrenze: Ein Wappen darf nicht beschnitten werden,
   und ein sehr breites Logo (manche Vereine führen einen Schriftzug) darf dem
   Namen nicht den Platz nehmen. */
.an-bg-logo {
  flex: 0 0 auto;
  /* Dreifache Schrifthöhe: Das nutzt den Platz, den die Box über dem Namen
     ohnehin frei lässt, und bleibt doch dem Namen untergeordnet — über die
     ganze Boxhöhe gestreckt erschlug das Wappen ihn. Weil das Maß an der
     Schrift hängt, wächst es auf dem Beamer mit und schrumpft auf dem
     Telefon. `max-height` fängt kleine Bildschirme ab, auf denen die Box
     flacher ist als das Logo hoch. */
  height: 3em;
  max-height: 100%;
  width: auto;
  max-width: 32%;
  object-fit: contain;
}

.an-bg-team.heim { background: var(--heimfarbe, #bb5757); color: #fff; }
.an-bg-team.gast { background: var(--gastfarbe); color: #10201a; }

.an-bg-punkte {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.12em;
  min-width: clamp(4.5rem, 12vw, 11rem);
  padding: 0 var(--s4);
  border-radius: var(--r2);
  background: #f2f6f4;
  color: #0d1a15;
  font-size: clamp(1.8rem, 5.4vw, 5rem);
  font-weight: 800;
  line-height: 1;
}

.an-bg-punkte i { font-style: normal; opacity: 0.35; }

/* --- Zwischenzeile ------------------------------------------------------ */

.an-bg-zeile-oben {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s5);
  margin: 0;
  padding: 0 var(--s2);
  color: var(--nav-ink-2);
  font-size: clamp(0.7rem, 1.3vw, 1.15rem);
  font-weight: 650;
}

.an-bg-zeile-oben strong { color: var(--gold-bright); }

.an-bg-entschieden {
  padding: 0.15em 0.7em;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: #1b1403;
  font-weight: 800;
}

/* --- Die Tafel ---------------------------------------------------------- */

/* **Ein Raster und keine Tabelle**, obwohl es wie eine aussieht — und der
   Grund ist der Siegerrahmen: Bei `border-collapse: separate` malt kein
   Browser einen Rahmen um eine Tabellenzeile, und Rahmen an den einzelnen
   Zellen ergäben mit den Zwischenräumen eine gestrichelte Kette statt einer
   Linie. Als Raster ist die Zeile ein eigenes Element und kann eingerahmt
   werden.

   Die Rollen (`role="table"`, `row`, `cell`, …) bleiben trotzdem: Für einen
   Screenreader ist es weiterhin eine Tabelle, und die Spaltenüberschriften
   gehören zu ihren Zellen. */
.an-bg-tafel {
  display: grid;
  gap: 5px;
  align-content: start;
  min-height: 0;
  font-size: var(--bg-schrift);
}

.an-bg-kopfzeile,
.an-bg-zeile {
  display: grid;
  grid-template-columns: var(--spalten);
  gap: 5px;
  align-items: stretch;
}

.an-bg-kopfzeile { padding: 0 3px; }

.an-bg-kopfzeile span {
  min-width: 0;
  display: grid;
  place-items: center;
  padding: 0 var(--s3) var(--s2);
  color: var(--nav-ink-2);
  font-size: clamp(0.58rem, 0.95vw, 0.9rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.an-bg-kopfzeile span:nth-child(2),
.an-bg-kopfzeile span:nth-child(3) { justify-items: start; text-align: left; }

/* Der Rahmen ist **immer da**, nur meist durchsichtig. Sonst wüchse eine
   gewonnene Zeile um sechs Pixel und die Tafel ruckelte, sobald ein Spiel
   endet. */
.an-bg-zeile {
  padding: 3px;
  border: 3px solid transparent;
  border-radius: calc(var(--r2) + 6px);
}

/* Der Siegerrahmen: die ganze Zeile in der Farbe der Mannschaft, die das
   Einzelspiel gewonnen hat. Aus zehn Metern liest man damit den Ausgang der
   Begegnung, ohne eine einzige Zahl anzusehen. */
.an-bg-zeile.sieger-a { border-color: var(--heimfarbe, #bb5757); }
.an-bg-zeile.sieger-b { border-color: var(--gastfarbe); }

.an-bg-zeile > * {
  min-width: 0;
  display: grid;
  place-items: center;
  padding: clamp(2px, 0.5vh, 8px) var(--s3);
  min-height: var(--zeilenhoehe);
  border-radius: var(--r1);
  background: rgba(255, 255, 255, 0.06);
}

/* Der laufende Zustand wird am linken Rand markiert — dieselbe Sprache wie in
   der Gesamtübersicht, damit beide Tafeln zusammengehören. */
.an-bg-zeile.laeuft > :first-child { box-shadow: inset 4px 0 0 var(--gold); }
.an-bg-zeile.pause  > :first-child { box-shadow: inset 4px 0 0 var(--warn); }
.an-bg-zeile.bereit > :first-child { box-shadow: inset 4px 0 0 var(--st-ready); }

.an-bg-rolle {
  justify-items: start;
  color: var(--gold-bright);
  font-size: 0.86em;
  font-weight: 800;
  line-height: 1.15;
  text-align: left;
}

.an-bg-rolle b { display: block; font-weight: inherit; overflow-wrap: anywhere; }
.an-bg-rolle i {
  display: block;
  color: var(--nav-ink-2);
  font-size: 0.78em;
  font-style: normal;
  font-weight: 650;
}

.an-bg-seite {
  justify-items: start;
  font-weight: 700;
  line-height: 1.15;
  text-align: left;
}

/* Im Doppel steht je Spieler eine Zeile. Zwei Namen in einer Zeile werden auf
   einem Beamer zu klein, sobald einer davon lang ist. */
.an-bg-seite span { display: block; overflow-wrap: anywhere; }

/* Hervorhebung 1: Die Siegerseite bekommt ihre Mannschaftsfarbe. */
.an-bg-seite.heim.sieger { background: var(--heimfarbe, #bb5757); color: #fff; }
.an-bg-seite.gast.sieger { background: var(--gastfarbe); color: #10201a; }

/* --- Satzzellen --------------------------------------------------------- */

/* Waagerecht, nicht als Raster: Die Zellen erben `display: grid` von der
   Zeile, und darin stünden „21“, „:“ und „15“ **untereinander**. */
.an-bg-satz {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  white-space: nowrap;
}

.an-bg-satz i { font-style: normal; opacity: 0.4; margin: 0 0.08em; }
.an-bg-satz.leer { color: rgba(255, 255, 255, 0.26); font-weight: 650; }

/* Hervorhebung 2: Die Sätze des Siegers in dessen Farbe. So liest man die
   Entscheidung, ohne zu rechnen.

   **Sätze des Verlierers bleiben schlicht** — Entscheidung vom 25.08.2026.
   Der Vorgänger markierte sie halb (Gast-Sätze hell, Heim-Sätze gar nicht),
   ein erster Entwurf hier machte das symmetrisch mit gedämpften Tönen. Beides
   ist wieder heraus: Aus zehn Metern waren die vier Abstufungen nicht mehr
   auseinanderzuhalten, und wer wissen will, wer welchen Satz geholt hat,
   liest die Zahlen daneben. */
.an-bg-zeile.sieger-a .an-bg-satz.siegersatz {
  background: var(--heimfarbe, #bb5757);
  color: #fff;
}

.an-bg-zeile.sieger-b .an-bg-satz.siegersatz {
  background: var(--gastfarbe);
  color: #10201a;
}

/* Der laufende Satz trägt schon Zahlen, ist aber nicht entschieden. Er bekommt
   deshalb keine Fläche, sondern nur einen Rahmen. */
.an-bg-satz.laufend {
  background: transparent;
  box-shadow: inset 0 0 0 2px var(--gold);
}

.an-bg-status {
  color: var(--nav-ink-2);
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
}

.an-bg-zeile.laeuft .an-bg-status { color: var(--gold-bright); }
.an-bg-zeile.fertig .an-bg-status { color: rgba(255, 255, 255, 0.55); }

/* Auf einem schmalen Gerät passt die Tafel nicht nebeneinander. Dann darf sie
   waagerecht rollen — die Seite selbst bleibt unverschiebbar.

   **Die Mindestbreite ist großzügig, und das ist der Punkt.** Zu knapp
   bemessen werden die Namensspalten so schmal, dass `overflow-wrap: anywhere`
   greift und mitten im Wort trennt: „Mia Wagne/r“, „Lina Hoffm/ann“. Lieber
   waagerecht rollen als solche Namen zeigen.

   Die feste Zeilenhöhe entfällt hier ebenfalls: Sie ist aus der Bildschirm-
   höhe gerechnet und für einen Fernseher gedacht. Auf einem hochkant
   gehaltenen Telefon ergäbe sie riesige Zeilen mit viel Leerraum. */
@media (max-width: 900px) {
  .an-begegnung { height: auto; min-height: 100dvh; overflow-x: auto; }
  .an-bg-tafel { min-width: 860px; font-size: 1rem; }
  .an-bg-zeile > * { min-height: 0; }
}
