/* =========================================================================
   eckdaten.app — Gestaltung
   =========================================================================
   Zwei Farbebenen liegen uebereinander:

   1. Die MARKE (Rasen, Signal, Kalk) traegt Logo, Grundflaechen und alles,
      was unabhaengig vom Verein ist. Werte aus dem Logo-Entwurf.
   2. Die VEREINSFARBE uebernimmt, sobald jemand seinen Verein gewaehlt hat.
      Sie kommt in ZWEI Rollen vor, und die duerfen nicht verwechselt werden:

      --verein  ist FLAECHE: das Heldenband, die Kachel. Grosse Flaechen,
                auf denen --verein-schrift steht. Jede Vereinsfarbe taugt
                dafuer, denn das Paar ist in der Tabelle geprueft.
      --akzent  ist TINTE auf dem dunklen Grund: Frist, offene Anstosszeit,
                Rahmen, Fokus — und Flaeche dort, wo das Element klein ist
                (Kopieren-Knopf, aktiver Filter, Heim-Marke); darauf steht
                dann --akzent-schrift.

      Warum getrennt: Gladbach (#1A1A1A) erreicht gegen den Grund 1,1:1.
      Als Flaeche mit weisser Schrift ist das tadellos, als Tinte war der
      Kopieren-Knopf unsichtbar. Vier Vereine waren davon betroffen.

   Beide Schriftfarben kommen aus der Vereinstabelle im Server, nicht aus
   einer Kontrastformel: auf Dortmunder Gelb gehoert dunkle Schrift, auf
   Bayern-Rot weisse.

   Schrift: bewusst systemeigen. Der Logo-Entwurf nennt Familjen Grotesk und
   Spline Sans Mono — die kaemen von fremden Servern und sind hier deshalb
   nicht eingebunden (siehe CLAUDE.md, offener Punkt).
   ========================================================================= */

:root {
  /* Marke.
     Das Zeichen stand bis zum 25.08.2026 auf Rasengrün (#0C4A33). Gemessen
     hatten die orangen Balken darauf nur 2,83:1 — der schlechteste Wert
     aller geprüften Farbwege; bei 42 Pixeln auf dem Homebildschirm matschten
     Fahne und Fläche ineinander. Anthrazit bringt sie auf 4,85:1 und passt
     zur dunklen Oberfläche der App. */
  --marke: #16191C;
  --signal: #E8552F;
  --kalk: #F2F5EE;
  --tief: #091310;

  /* Flaechen */
  --grund: #0C100E;
  --flaeche: #141A17;
  --flaeche-2: #1A211D;
  --rand: #232D28;
  --text: #E6EBE7;
  --leise: #8FA098;

  /* Rueckfall, solange kein Verein gewaehlt ist.
     Das war das Mittelgrün der alten Marke und trug auf der Fläche nur
     2,75:1 — als Schriftfarbe also unlesbar nach jedem Maßstab. Mit dem
     anthrazitfarbenen Zeichen ist das Signalorange die Farbe der Marke;
     es misst 4,85:1 und besteht damit AA.
     Die Schrift AUF der Orangefläche muss dunkel sein: #12100B kommt auf
     5,22:1, Weiß nur auf 3,64:1. */
  --verein: var(--signal);
  --verein-schrift: #12100B;
  --akzent: var(--signal);
  /* Schrift und dünne Zeichen. Derselbe Ton, aber hell genug für 4,5:1 auf
     der Karte — siehe `textfarbe()` in server/vereine.js. Das Signalorange
     schafft es schon von selbst (4,85:1). */
  --akzent-text: var(--signal);
  --akzent-schrift: #12100B;

  color-scheme: dark;
}

* { box-sizing: border-box; }

/* `hidden` MUSS gewinnen.
   Die Regel des Browsers dafuer ist `[hidden] { display: none }` — eine
   Attributregel mit dem Gewicht 0,1,0. Jede Klassenregel mit `display:`
   schlaegt sie. Das ist hier zweimal passiert: Die Reiterleiste
   (`.reiter { display: flex }`) stand auf der Vereinsauswahl, obwohl sie
   verborgen sein sollte, und die Benachrichtigungskarte blieb sichtbar,
   nachdem sie ein <details> geworden war.
   Einmal grundsaetzlich statt bei jedem neuen Element von Hand — sonst
   faellt der naechste wieder darauf herein. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--grund);
  color: var(--text);
  font: 1.0625rem/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

.huelle { width: min(100% - 2.25rem, 46rem); margin-inline: auto; }

h1, h2, h3 { letter-spacing: -.02em; line-height: 1.15; margin: 0; }

/* ── Kopfzeile ───────────────────────────────────────────────────────────── */

.kopf {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .85rem max(1.125rem, env(safe-area-inset-left));
  /* `env(safe-area-inset-top)` ist Pflicht, sobald die App im Standalone-
     Betrieb laeuft: Mit `apple-mobile-web-app-status-bar-style:
     black-translucent` beginnt die Seite GANZ OBEN, also hinter Uhr und
     Akkuanzeige. Ohne diesen Zuschlag liegt die komplette Kopfzeile darunter
     und „Verein wechseln" ist nicht zu treffen — im Browser faellt das nicht
     auf, weil der Zuschlag dort 0 ist.

     1,4 rem statt 0,85: Mit dem knappen Wert blieben zwischen der Dynamic
     Island und dem Logo nur 18 Pixel. Gemessen reicht das zwar, gefuehlt
     klebt es. */
  padding-top: calc(1.4rem + env(safe-area-inset-top));
  /* DECKEND, NICHT DURCHSCHEINEND. Bei 88 % schimmerte der Inhalt, der
     darunter wegscrollt, hinter Logo und Knopf hindurch — auf der
     Vereinsansicht ausgerechnet das grelle Farbband. Das sah aus, als waere
     die Kopfzeile verdeckt. Der Weichzeichner bleibt fuer die Kante zum
     Inhalt, traegt aber nichts mehr aus dem Hintergrund herein. */
  background: color-mix(in srgb, var(--grund) 98%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--rand);
}

.marke { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none; color: var(--kalk); }
.marke__zeichen { width: 1.75rem; height: 1.75rem; flex: none; }
.marke__wort { font-size: 1.25rem; font-weight: 700; letter-spacing: -.045em; }
.marke__wort em { font-style: normal; color: var(--signal); }

.wechseln {
  min-height: 2.25rem; padding: 0 .9rem;
  border: 1px solid var(--rand); border-radius: 999px;
  background: transparent; color: var(--leise);
  font: inherit; font-size: .85rem; cursor: pointer;
}
.wechseln:hover { color: var(--text); border-color: var(--akzent); }

/* ── Einstieg ────────────────────────────────────────────────────────────── */

.einstieg { padding: clamp(2.5rem, 8vw, 4.5rem) 0 2rem; }
.einstieg h1 { font-size: clamp(2.1rem, 8vw, 3.25rem); font-weight: 700; margin-bottom: 1rem; }
.fuehrung { color: var(--leise); max-width: 34rem; }

.bereichstitel {
  font-size: .75rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .16em; color: var(--leise); margin-bottom: .9rem;
}

.vereinsraster {
  display: grid; gap: .625rem;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  padding-bottom: 3rem;
}

/* Die Kachel IST die Vereinsfarbe — das ist der Wiedererkennungswert.
   Der Streifen links traegt die Zweitfarbe. Ohne ihn waeren zehn der
   achtzehn Kacheln dasselbe Rot: Bayern, Leipzig, Leverkusen, Frankfurt,
   Stuttgart, Freiburg, Koeln, Union, Mainz und Elversberg liegen alle
   zwischen #C3141E und #ED1C24. Erst der Streifen macht daraus rot-blau,
   rot-schwarz, rot-weiss und rot-gelb. */
.vereinskachel {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: .15rem;
  min-height: 5.25rem; padding: .85rem .9rem .85rem 1.4rem;
  border: 0; border-radius: .875rem;
  background: var(--kachel); color: var(--kachel-schrift);
  font: inherit; text-align: left; cursor: pointer;
  transition: transform 140ms cubic-bezier(.32,.72,0,1), box-shadow 140ms;
}
.vereinskachel::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: .375rem;
  background: var(--kachel-zweit);
}
.vereinskachel:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -12px rgba(0,0,0,.9); }
.vereinskachel:active { transform: translateY(0); }
.vereinskachel__kurz { font-size: 1.1rem; font-weight: 700; letter-spacing: -.02em; }
.vereinskachel__name { font-size: .75rem; opacity: .82; }

/* ── Vereinsansicht ──────────────────────────────────────────────────────── */

.held {
  margin: 0 -1.125rem 1.5rem;
  padding: clamp(2rem, 7vw, 3.25rem) 1.125rem clamp(1.5rem, 5vw, 2.25rem);
  background: var(--verein); color: var(--verein-schrift);
}
.held h1 { font-size: clamp(1.75rem, 6vw, 2.5rem); font-weight: 700; }
.augenbraue {
  margin: 0 0 .5rem; font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .16em; opacity: .8;
}

.karte {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: 1rem; padding: 1.35rem; margin-bottom: 1rem;
}
.karte h2 { font-size: 1.05rem; font-weight: 650; margin-bottom: .65rem; }
.karte p { margin: 0 0 .7rem; }
.karte p:last-child { margin-bottom: 0; }

.karte--abo { border-color: var(--akzent); }
.naechstes { border-left: 4px solid var(--akzent); }
.naechstes__paarung { font-size: 1.15rem; font-weight: 700; margin-bottom: .3rem; }
/* Die vollen Vereinsnamen im aufgeklappten Teil. Kleiner als der Kurzname
   im Kopf — sie sind hier die Nachfrage, nicht die Ansage. */
.naechstes__voll { font-size: .95rem; font-weight: 600; color: var(--leise); margin-bottom: .5rem; }
.naechstes__wann { font-size: 1.05rem; font-weight: 600; margin-bottom: .15rem; }

/* ── Der Kopf der Kachel „Nächstes Spiel“ ───────────────────────
   Zwei Zeilen statt eines Absatzes: oben die Lage, unten die Paarung mit
   Uhrzeit oder Stand. Wetter, Spieltag und Ticker sind Nachfragen und stehen
   hinter dem Dreieck.

   EIN RASTER, KEIN FLEX. Mit `display:flex` im `summary` bekam die Paarung
   245 statt der verfügbaren 290 Pixel und wurde mitten im Vereinsnamen
   abgeschnitten, obwohl rechts Platz frei stand — das Pfeil-`::after` mit
   `margin-left:auto` und das wachsende Kind stritten um dieselbe Lücke.
   Das Raster benennt die Spalten und lässt nichts zu verhandeln.

   `minmax(0, 1fr)` statt `1fr`: Eine Rasterspalte wird von sich aus nicht
   schmaler als ihr Inhalt. Ohne das schöbe „Borussia Mönchengladbach“ die
   Uhrzeit aus der Kachel heraus, statt selbst zu kürzen. */
/* `.karte.naechstes` statt `.naechstes`: `.klapp > summary` steht weiter
   unten in dieser Datei und hat dasselbe Gewicht (0,1,1) — bei Gleichstand
   gewinnt die spätere Regel. Die Kachel blieb deshalb im Flex-Layout, und
   die Paarung bekam 91 statt 225 Pixel. Zwei Klassen heben das Gewicht auf
   (0,2,1) und beenden die Frage. */
.karte.naechstes > summary,
.karte.heute > summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "lage lage pfeil" "paarung wert pfeil";
  gap: .1rem .7rem;
  padding: .85rem 1.15rem;
}
.karte.naechstes > summary::after,
.karte.heute > summary::after { grid-area: pfeil; align-self: center; margin-left: 0; }

.nk__lage {
  grid-area: lage;
  display: flex; align-items: center; gap: .35rem;
  font-size: .8rem; font-weight: 600; color: var(--leise);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nk__paarung {
  grid-area: paarung; align-self: baseline;
  font-size: 1.05rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nk__wert {
  grid-area: wert; align-self: baseline;
  font-variant-numeric: tabular-nums; font-weight: 650; font-size: 1.05rem;
}
.nk__wert--stand { font-size: 1.3rem; color: var(--akzent-text); }
.nk__wert--offen { font-size: .85rem; font-weight: 500; color: var(--leise); }

/* Läuft ein Spiel oder ist es gerade abgepfiffen, trägt die Kachel den
   Akzent auch im Rahmen — sie ist dann kein Ausblick mehr, sondern das,
   weswegen jemand die Seite aufmacht. */
.naechstes--warm { border-color: var(--akzent); }
.naechstes--warm .nk__lage { color: var(--akzent-text); }

.leise { color: var(--leise); font-size: .95rem; }
.klein { font-size: .85rem; color: var(--leise); }

.adresse {
  display: flex; flex-wrap: wrap; align-items: center; gap: .7rem;
  background: var(--grund); border: 1px solid var(--rand);
  border-radius: .625rem; padding: .7rem .85rem;
}
.adresse code {
  flex: 1 1 15rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .875rem; overflow-wrap: anywhere;
}

/* `#kopieren` war einmal ein grosser Knopf. Seit die Abo-Kachel zwei
   richtige Knoepfe hat (Apple, Google), ist es nur noch ein Textlink in der
   Fussnote — die alte Pillenform stand ihm sonst weiter im Weg und liess die
   Zeile aussehen, als gaebe es drei Knoepfe. Die Gestaltung steht jetzt
   allein in `.text-knopf`. */

.hinweis { margin-top: .7rem; color: var(--akzent-text); font-size: .875rem; }

.anleitung { margin-top: 1rem; border-top: 1px solid var(--rand); padding-top: .8rem; }
.anleitung summary { cursor: pointer; font-size: .9rem; color: var(--leise); }
.anleitung summary::marker { color: var(--akzent-text); }
.anleitung ol { margin: .8rem 0 0; padding-left: 1.2rem; color: var(--leise); font-size: .9rem; }
.anleitung li { margin-bottom: .45rem; }

/* ── Spielplan ───────────────────────────────────────────────────────────── */

.bereich-kopf {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: .75rem; margin: 2rem 0 .9rem;
}
.bereich-kopf h2 { font-size: 1.05rem; font-weight: 650; }

.filter { display: flex; flex-wrap: wrap; gap: .4rem; }
.filter__knopf {
  min-height: 2.1rem; padding: 0 .8rem;
  border: 1px solid var(--rand); border-radius: 999px;
  background: var(--flaeche); color: var(--leise);
  font: inherit; font-size: .82rem; cursor: pointer;
}
.filter__knopf:hover { color: var(--text); }
.filter__knopf.ist-aktiv { background: var(--akzent); border-color: var(--akzent); color: var(--akzent-schrift); font-weight: 600; }

.ladehinweis { color: var(--leise); padding: 1.25rem 0; }

.monat {
  margin: 1.5rem 0 .6rem; font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em; color: var(--leise);
}
.monat:first-child { margin-top: 0; }

.spiel {
  display: grid; grid-template-columns: 5.5rem 1fr; gap: .75rem; align-items: center;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-left: 3px solid var(--rand);
  border-radius: .75rem; padding: .75rem .95rem; margin-bottom: .45rem;
}
.spiel--heim { border-left-color: var(--akzent-text); }
.spiel--offen { border-style: dashed; }
.spiel--vorbei { opacity: .5; }

.spiel__wann { display: flex; flex-direction: column; }
.spiel__tag { font-size: .72rem; color: var(--leise); }
.spiel__datum { font-weight: 600; font-size: .95rem; }
.spiel__zeit { font-size: .85rem; color: var(--leise); font-variant-numeric: tabular-nums; }
.spiel__zeit--offen { color: var(--akzent-text); font-weight: 600; }

.spiel__spieltag { font-size: .72rem; color: var(--leise); margin-bottom: .1rem; }
.spiel__paarung { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; }
.gegner { font-weight: 600; }

/* H oder A statt einer Beschriftung: spart Platz und ist sofort lesbar. */
.ort-marke {
  flex: none; width: 1.35rem; height: 1.35rem;
  display: grid; place-items: center;
  border-radius: .35rem; background: var(--flaeche-2);
  font-size: .68rem; font-weight: 700; color: var(--leise);
}
.spiel--heim .ort-marke { background: var(--akzent); color: var(--akzent-schrift); }

.ergebnis {
  font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--flaeche-2); border-radius: .35rem; padding: 0 .4rem;
}

.fuss { margin-block: 2.5rem; padding-top: 1.25rem; border-top: 1px solid var(--rand); color: var(--leise); font-size: .8rem; }
.fuss a { color: var(--leise); }

:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; border-radius: .4rem; }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; }
}

@media (max-width: 26rem) {
  .spiel { grid-template-columns: 4.5rem 1fr; }
}

/* ── Ansichten und Reiterleiste ──────────────────────────────────────────────
   Umgeschaltet wird mit `.ansicht-aus`, nicht mit `hidden`: An einzelnen
   Elementen steht `hidden` schon aus inhaltlichem Grund (kein naechstes
   Spiel), und beides zu vermischen blendete beim Wechsel Leeres ein. */

.ansicht-aus { display: none; }

.reiter {
  position: fixed; inset: auto 0 0 0; z-index: 30;
  display: flex; justify-content: center; gap: .25rem;
  padding: .375rem .5rem;
  /* `env(safe-area-inset-bottom)` ist Pflicht. Ohne den Zuschlag laege die
     Leiste auf iPhones unter dem Wischstreifen und waere nicht zu treffen. */
  padding-bottom: calc(.375rem + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--grund) 92%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--rand);
}

.reiter__knopf {
  flex: 1 1 0; max-width: 7rem;
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
  min-height: 2.9rem; padding: .35rem .25rem;
  border: 0; border-radius: .625rem; background: transparent;
  color: var(--leise); font: inherit; font-size: .7rem; cursor: pointer;
}
.reiter__knopf svg { width: 1.25rem; height: 1.25rem; flex: none; }
.reiter__knopf.ist-aktiv { color: var(--akzent-text); }
.reiter__knopf.ist-aktiv .reiter__wort { font-weight: 650; }

/* Platz fuer die Leiste, sonst deckt sie die letzte Zeile ab. */
body:has(.reiter:not([hidden])) { padding-bottom: 4.5rem; }

/* ── Tabelle ─────────────────────────────────────────────────────────────── */

.tabelle { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.tabelle th {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--leise); text-align: right;
  padding: 0 .3rem .5rem; white-space: nowrap;
}
.tabelle th:nth-child(1), .tabelle th:nth-child(2) { text-align: left; }
.tabelle td { padding: .5rem .3rem; border-top: 1px solid var(--rand); text-align: right; }
.tabelle td:nth-child(1), .tabelle td:nth-child(2) { text-align: left; }

.tab__platz { width: 2.2rem; color: var(--leise); font-size: .85rem; position: relative; padding-left: .55rem !important; }
/* Der Zonenstreifen steht links am Platz — Champions League bis Abstieg.
   Farbe kommt aus der Quelle bzw. aus zoneNachPlatz(); keine eigene Erfindung. */
.tab__zone { position: absolute; inset: 0 auto 0 0; width: .1875rem; border-radius: 999px; }
.tab__verein { font-weight: 600; }
.tab__punkte { font-weight: 700; }
.tabelle td.tab__weich { color: var(--leise); font-size: .9rem; }

/* Die eigene Mannschaft hervorheben — dafuer ist die App da. */
.tabelle tr.ist-eigen td { background: color-mix(in srgb, var(--akzent) 14%, transparent); }
.tabelle tr.ist-eigen .tab__verein { color: var(--akzent-text); }

.zonen { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-top: 1rem; }
.zonen__eintrag { display: inline-flex; align-items: center; gap: .4rem; font-size: .78rem; color: var(--leise); }
.zonen__fleck { width: .625rem; height: .625rem; border-radius: 2px; flex: none; }

/* Auf schmalen Geraeten fallen die selten gelesenen Spalten weg: Siege,
   Unentschieden und Niederlagen stehen auch im Torverhaeltnis. */
@media (max-width: 30rem) {
  .tabelle .weglassbar { display: none; }
}

/* ── Bilanz ──────────────────────────────────────────────────────────────────
   Kennzahlen sind KEIN Diagramm. Spiele, Siege, Tore, Punkte beantworten je
   eine Frage mit einer Zahl — dafuer ist die Kachel die richtige Form, nicht
   ein Balken, der eine Groessenbeziehung behauptet, die es nicht gibt.

   DIE FORMKURVE IST EINE STATUSFOLGE, KEINE KATEGORIE. Sieg, Unentschieden
   und Niederlage sind Zustaende; sie haben eine eigene, reservierte Palette,
   die sich nicht mit den Vereinsfarben mischt. Nachgerechnet gegen die
   dunkle Flaeche (#141A17): alle drei ueber 3:1, dunkle Schrift darauf 4,6
   bis 6,2:1.

   GRUEN-GELB-ROT IST DER KLASSISCHE ROT-GRUEN-FALL. Gemessen liegt das Paar
   Sieg/Unentschieden bei Protanopie nur bei ΔE 6,5 — erlaubt ist das
   ausschliesslich mit zweiter Kodierung. Deshalb steht in JEDEM Feld der
   Buchstabe S, U oder N. Wer die Buchstaben entfernt, macht die Formkurve
   fuer einen von zwanzig Maennern unlesbar. */

:root {
  --sieg: #31A85E;
  --unentschieden: #C08A1E;
  --niederlage: #E04352;
  --status-schrift: #12100B;
}

.kennzahlen {
  display: grid; gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  margin-bottom: 1rem;
}
.kennzahl {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: .75rem; padding: .8rem .7rem;
}
.kennzahl__wert { font-size: 1.5rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.kennzahl__wort { font-size: .7rem; text-transform: uppercase; letter-spacing: .1em; color: var(--leise); margin-top: .2rem; }
.kennzahl--gross .kennzahl__wert { font-size: 2.25rem; color: var(--akzent-text); }

.formkurve { display: flex; flex-wrap: wrap; gap: .3rem; }
.formfeld {
  width: 1.9rem; height: 1.9rem; flex: none;
  display: grid; place-items: center;
  border-radius: .4rem;
  font-size: .8rem; font-weight: 700; color: var(--status-schrift);
}
.formfeld--S { background: var(--sieg); }
.formfeld--U { background: var(--unentschieden); }
.formfeld--N { background: var(--niederlage); }

.bilanzliste { display: grid; gap: .4rem; margin-top: .3rem; }
.bilanzzeile { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; font-size: .92rem; }
.bilanzzeile dt { color: var(--leise); }
.bilanzzeile dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }

.leerhinweis {
  background: var(--flaeche); border: 1px dashed var(--rand);
  border-radius: 1rem; padding: 1.5rem 1.35rem; color: var(--leise);
}
.leerhinweis strong { color: var(--text); display: block; margin-bottom: .35rem; }

/* ── Liga ────────────────────────────────────────────────────────────────── */

.blaetter { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin-bottom: .9rem; }
.blaetter__wort { font-weight: 650; font-size: 1rem; }
.blaetter__knopf {
  width: 2.4rem; height: 2.4rem; flex: none;
  border: 1px solid var(--rand); border-radius: 999px;
  background: var(--flaeche); color: var(--text);
  font: inherit; font-size: 1.15rem; line-height: 1; cursor: pointer;
}
.blaetter__knopf:hover:not(:disabled) { border-color: var(--akzent); color: var(--akzent-text); }
.blaetter__knopf:disabled { opacity: .35; cursor: default; }

.paarung {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .5rem;
  padding: .55rem .1rem; border-top: 1px solid var(--rand); font-size: .92rem;
}
.paarung:first-of-type { border-top: 0; }
.paarung__heim { text-align: right; }
.paarung__gast { text-align: left; }
.paarung__mitte {
  min-width: 3.4rem; text-align: center; font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: .9rem;
  display: flex; align-items: center; justify-content: center; gap: .35rem;
}
/* Im Ergebnisfeld steht das Statuszeichen klein daneben, nicht in der
   Gastspalte — dort sprengte es die Zeile auf drei Zeilen. */
.paarung__mitte .formfeld { width: 1.25rem; height: 1.25rem; border-radius: .25rem; font-size: .62rem; }
.paarung__zeit { font-weight: 400; font-size: .8rem; color: var(--leise); }
.paarung--eigen { background: color-mix(in srgb, var(--akzent) 12%, transparent); border-radius: .4rem; }
.paarung--eigen .paarung__heim, .paarung--eigen .paarung__gast { font-weight: 650; }
.spieltag__wann { font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; color: var(--leise); margin: .9rem 0 .3rem; }
.spieltag__wann:first-child { margin-top: 0; }

/* Rangliste — Restprogramm und Formtabelle teilen sich die Form. */
.rangliste { display: grid; gap: .1rem; margin-top: .3rem; }
.rangzeile {
  display: grid; grid-template-columns: 1.6rem 1fr auto; align-items: center; gap: .6rem;
  padding: .4rem .45rem; border-radius: .4rem; font-size: .9rem;
}
.rangzeile--eigen { background: color-mix(in srgb, var(--akzent) 14%, transparent); }
.rangzeile--eigen .rangzeile__verein { color: var(--akzent-text); font-weight: 650; }
.rangzeile__rang { color: var(--leise); font-size: .8rem; font-variant-numeric: tabular-nums; }
.rangzeile__wert { font-variant-numeric: tabular-nums; color: var(--leise); font-size: .85rem; }
.rangzeile__folge { display: flex; gap: .15rem; }
.rangzeile__folge .formfeld { width: 1.15rem; height: 1.15rem; border-radius: .25rem; font-size: .6rem; }

.ziel { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; padding: .45rem 0; border-top: 1px solid var(--rand); }
.ziel:first-of-type { border-top: 0; }
.ziel__wort { font-weight: 600; }
.ziel__platz { color: var(--leise); font-size: .82rem; }
.ziel__wert { font-variant-numeric: tabular-nums; text-align: right; }
.ziel__wert--voraus { color: var(--sieg); }
.ziel__wert--fehlt { color: var(--akzent-text); font-weight: 600; }

/* ── Live ────────────────────────────────────────────────────────────────── */

.karte--vorschau { border-left: 4px solid var(--akzent); }

/* Waehrend gespielt wird, raeumt die Kachel auf: Datum, Uhrzeit und Ort
   verschwinden. Sie beantworten „wann und wo?" — und die Frage stellt
   niemand mehr, waehrend die Mannschaft auf dem Platz steht. */
.laufend { display: flex; align-items: center; gap: .9rem; flex-wrap: wrap; }
.laufend__stand { font-size: 2.5rem; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }
.laufend__minute {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .85rem; font-weight: 650; color: var(--akzent-text);
}
.laufend__punkt {
  width: .5rem; height: .5rem; border-radius: 999px; background: var(--akzent);
  animation: pochen 1.6s ease-in-out infinite;
}
@keyframes pochen { 0%,100% { opacity: 1 } 50% { opacity: .25 } }
@media (prefers-reduced-motion: reduce) { .laufend__punkt { animation: none } }

.vorschauzeile {
  display: grid; grid-template-columns: 1.9rem 1fr auto; align-items: center; gap: .7rem;
  padding: .45rem 0; border-top: 1px solid var(--rand);
}
.vorschauzeile:first-of-type { border-top: 0; }
.vorschauzeile__platz { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Benachrichtigungen ──────────────────────────────────────────────────── */

.karte--push { border-color: var(--rand); }
.anlaesse { display: grid; gap: .1rem; margin: .8rem 0; }
.anlass {
  display: flex; align-items: center; gap: .7rem;
  padding: .55rem .1rem; cursor: pointer;
}
.anlass input { width: 1.15rem; height: 1.15rem; accent-color: var(--akzent); flex: none; }
.anlass__wort { font-weight: 600; font-size: .95rem; }
.anlass__hinweis { color: var(--leise); font-size: .82rem; }
/* Luft nach oben. Die Knöpfe klebten am Auswahlfeld darüber und sahen aus,
   als gehörten sie dazu — dabei beenden sie die ganze Eingabe. */
.push-knoepfe { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.4rem; }
#push-an, #push-aus {
  min-height: 2.6rem; padding: 0 1.1rem; border: 0; border-radius: 999px;
  background: var(--akzent); color: var(--akzent-schrift);
  font: inherit; font-weight: 600; font-size: .9rem; cursor: pointer;
}
#push-aus { background: transparent; color: var(--leise); border: 1px solid var(--rand); }
#push-an:disabled { opacity: .5; cursor: default; }

/* ── Datenschutz ─────────────────────────────────────────────────────────── */

.rechtstext { padding: 2rem 0 3rem; }
.rechtstext h1 { font-size: clamp(1.6rem, 5vw, 2.25rem); margin-bottom: 1rem; }
.rechtstext h2 { font-size: 1.05rem; margin: 1.8rem 0 .5rem; }
.rechtstext p, .rechtstext li { color: var(--text); }
.rechtstext ul { padding-left: 1.2rem; }
.rechtstext li { margin-bottom: .4rem; }
.rechtstext .leise { color: var(--leise); }

/* Torschuetzen im laufenden Spiel. Fehlt der Name in der Quelle, steht dort
   nur die Minute — lieber eine Luecke als ein erfundener Name. */
.torliste { list-style: none; margin: .8rem 0 0; padding: 0; display: grid; gap: .3rem; }
.torliste li {
  display: flex; align-items: baseline; gap: .5rem;
  font-size: .92rem; padding: .25rem 0; border-top: 1px solid var(--rand);
}
.torliste li:first-child { border-top: 0; }
.torliste__minute { color: var(--leise); font-variant-numeric: tabular-nums; min-width: 2.2rem; }
.torliste__stand { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.torliste__zusatz { color: var(--leise); font-size: .8rem; }

/* Der Pokal muss sich vom Spieltag unterscheiden. „1. Runde" allein geht
   neben lauter „1. Spieltag" unter — genau daran ist ein Pokalspiel beim
   Ueberfliegen uebersehen worden. */
.marke-pokal {
  display: inline-block; padding: .05rem .35rem; margin-right: .2rem;
  border-radius: .25rem; background: var(--signal); color: #12100B;
  font-size: .62rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; vertical-align: .05em;
}
.spiel--pokal { border-left-style: double; border-left-width: 4px; }
.laufend__abschnitt { font-size: .78rem; color: var(--leise); }

/* ── Klappbare Abschnitte ────────────────────────────────────────────────────
   Gebaut mit <details>, nicht mit eigenem Auf- und Zuklappen: Der Browser
   bringt Tastaturbedienung, Vorlesbarkeit und die Suchfunktion („Auf dieser
   Seite suchen" oeffnet zugeklappte Abschnitte von selbst) mit. Nachgebaut
   waere das alles verloren.

   WAS OFFEN IST, MERKT SICH DIE SEITE. Wer die Formtabelle jedes Mal neu
   aufklappen muss, klappt sie beim dritten Mal nicht mehr auf. */

.klapp {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: 1rem; margin-bottom: 1rem;
}
.klapp > summary {
  display: flex; align-items: center; gap: .6rem;
  padding: 1.05rem 1.35rem; cursor: pointer;
  font-size: 1.05rem; font-weight: 650;
  list-style: none;
}
.klapp > summary::-webkit-details-marker { display: none; }
.klapp > summary::after {
  content: ''; margin-left: auto; flex: none;
  width: .55rem; height: .55rem;
  border-right: 2px solid var(--leise); border-bottom: 2px solid var(--leise);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 160ms cubic-bezier(.32,.72,0,1);
}
.klapp[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.klapp > summary:hover::after { border-color: var(--akzent); }
.klapp__zusatz { font-size: .8rem; font-weight: 400; color: var(--leise); }
.klapp__inhalt { padding: 0 1.35rem 1.35rem; }
.klapp__inhalt > :first-child { margin-top: 0; }
/* Innerhalb eines Klappmenues braucht die Karte keinen zweiten Rahmen. */
.klapp__inhalt .karte { background: transparent; border: 0; padding: 0; margin: 0 0 1rem; }
.klapp__inhalt .karte:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) { .klapp > summary::after { transition: none } }

/* ── Ticker ──────────────────────────────────────────────────────────────── */

.ticker { display: grid; gap: .1rem; }
.tickerzeile {
  /* Die Minutenspalte muss „90+1." tragen, nicht nur „90.". Mit 2,6 rem
     brach die Angabe um und sichtbar blieb die halbe Zahl. */
  display: grid; grid-template-columns: 3.4rem 1.4rem 1fr auto; align-items: baseline; gap: .5rem;
  padding: .45rem .35rem; border-radius: .4rem; font-size: .92rem;
}
.tickerzeile--tor { background: color-mix(in srgb, var(--akzent) 12%, transparent); font-weight: 600; }
.tickerzeile__minute {
  color: var(--leise); font-variant-numeric: tabular-nums; font-size: .85rem;
  white-space: nowrap;   /* „90+1." darf nicht umbrechen */
}
.tickerzeile__stand { font-weight: 700; font-variant-numeric: tabular-nums; }
.tickerzeile__wer { color: var(--leise); font-size: .8rem; }
.tickerzeichen { font-size: .95rem; line-height: 1; }

.statistik { display: grid; gap: .55rem; }
.statzeile { display: grid; grid-template-columns: 2.6rem 1fr 2.6rem; align-items: center; gap: .6rem; font-size: .88rem; }
.statzeile__wort { text-align: center; color: var(--leise); font-size: .78rem; }
.statzeile__zahl { font-variant-numeric: tabular-nums; font-weight: 600; }
.statzeile__zahl--gast { text-align: right; }
.statbalken { display: flex; height: .35rem; border-radius: 999px; overflow: hidden; background: var(--flaeche-2); }
.statbalken__heim { background: var(--leise); }
.statbalken__gast { background: var(--akzent); }

/* Laufende Spiele auf der Vereinskachel. Der Chip liegt oben rechts und
   nimmt die Schriftfarbe der Kachel — auf Dortmunder Gelb dunkel, auf
   Bayern-Rot hell. Eine feste Farbe waere auf der Haelfte der Kacheln
   unlesbar. */
.vereinskachel--live { box-shadow: inset 0 0 0 2px var(--kachel-schrift); }
.kachel-live {
  position: absolute; top: .5rem; right: .55rem;
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .1rem .38rem; border-radius: 999px;
  background: color-mix(in srgb, var(--kachel-schrift) 16%, transparent);
  color: var(--kachel-schrift);
  font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.kachel-live__punkt {
  width: .35rem; height: .35rem; border-radius: 999px;
  background: currentColor; animation: pochen 1.6s ease-in-out infinite;
}
.kachel-live__minute { font-weight: 400; opacity: .8; }
@media (prefers-reduced-motion: reduce) { .kachel-live__punkt { animation: none } }

/* ── Kompakte Partiezeile ────────────────────────────────────────────────────
   Fuer Listen, in denen viele Begebnungen untereinander stehen: Spieltage,
   Archiv, direkter Vergleich.

   DER PLATZ ENTSTEHT DURCH DEN KURZNAMEN, nicht durch kleinere Schrift.
   „Borussia Mönchengladbach – 1. FSV Mainz 05" braucht auf 390 Pixeln drei
   Zeilen, „Gladbach – Mainz" eine. Neun Partien wurden so von rund 27 auf
   9 Zeilen. Ausgeschrieben steht der Name weiterhin im `title`.

   Eine Spalte, eine Zeile: `overflow: hidden` mit Ellipse statt Umbruch —
   sonst verschoebe eine lange Paarung alle anderen Zeilen gegeneinander und
   die Uhrzeiten staenden nicht mehr untereinander. */

.partie {
  display: grid; grid-template-columns: 3rem 1fr auto;
  gap: .5rem; align-items: baseline;
  padding: .4rem .1rem; border-bottom: 1px solid var(--rand);
  font-size: .85rem;
}
.partie:last-child { border-bottom: 0; }
.partie__zeit { color: var(--leise); font-variant-numeric: tabular-nums; font-size: .8rem; }
.partie__paarung { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der eigene Verein faellt auf, ohne dass eine Farbe dazukommt. */
.partie__eigen { font-weight: 700; }
.partie__stand { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.partie__stand--live {
  padding: .05rem .35rem; border-radius: .3rem;
  background: var(--akzent); color: var(--akzent-schrift);
}
.partie__minute { margin-left: .3rem; font-weight: 400; font-size: .72rem; opacity: .85; }
.partie--live { background: color-mix(in srgb, var(--akzent) 10%, transparent); border-radius: .35rem; }
.partie--eigen { background: color-mix(in srgb, var(--akzent) 13%, transparent); border-radius: .35rem; }

/* ── Abo-Knoepfe ─────────────────────────────────────────────────────────────
   Ein Fingertipp statt Kopieren und Einfuegen. Zwei Knoepfe nebeneinander,
   unter 24 rem untereinander — zwei Stummel auf 320 Pixeln liest niemand. */

.abo-knoepfe { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; margin-bottom: .9rem; }
@media (max-width: 24rem) { .abo-knoepfe { grid-template-columns: 1fr; } }

.abo-knopf {
  display: flex; align-items: center; justify-content: center;
  min-height: 2.9rem; padding: 0 1rem;
  border-radius: .75rem; text-decoration: none;
  background: var(--akzent); color: var(--akzent-schrift);
  font-weight: 650; font-size: .95rem; text-align: center;
}
.abo-knopf:hover { filter: brightness(1.1); }
.abo-knopf--zweit {
  background: transparent; color: var(--text);
  border: 1px solid var(--rand);
}
.abo-knopf--zweit:hover { border-color: var(--akzent); color: var(--akzent-text); filter: none; }

.abo__fussnote {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  margin: 0; color: var(--leise); font-size: .875rem;
}
.text-knopf {
  border: 0; background: transparent; padding: 0;
  color: var(--akzent-text); font: inherit; font-size: .875rem;
  text-decoration: underline; text-underline-offset: .2em; cursor: pointer;
}
.text-knopf:hover { filter: brightness(1.15); }

/* Monatsblöcke im Spielplan. Schmaler als die uebrigen Klappmenues — es
   sind bis zu zehn untereinander, und jeder Rahmen kostet Platz. */
.klapp--monat { margin-bottom: .5rem; }
.klapp--monat > summary {
  padding: .7rem 1rem;
  font-size: .8rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em; color: var(--leise);
}
.klapp--monat[open] > summary { color: var(--text); }
.klapp--monat > .klapp__inhalt { padding: 0 .6rem .6rem; }

/* ── Spiele heute (Startseite) ───────────────────────────────────────────── */

.heute { margin-bottom: 2rem; }
/* Die Liste steckt jetzt IM aufgeklappten Teil. Ein eigener Rahmen um sie
   herum wäre ein Kasten im Kasten. */
.heute__liste { padding: 0; }
/* Auf der Startseite ist kein Verein gewaehlt — dort traegt die Marke des
   Dienstes die Hervorhebung, nicht eine Vereinsfarbe. */
.heute .partie--live { background: color-mix(in srgb, var(--signal) 14%, transparent); }
.heute .partie__stand--live { background: var(--signal); color: #12100B; }
.heute__tag {
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--leise); margin: .7rem 0 .2rem;
}
.heute__tag:first-child { margin-top: 0; }

/* ── Betriebspasswort setzen (/admin/passwort) ─────────────────────────────
   Eine einzelne Seite abseits der App. Sie borgt sich `.adresse` als Rahmen
   fuer die Eingabefelder und `.abo-knopf` fuer den Knopf, damit sie aussieht
   wie der Rest — eigene Formularschrift gibt es hier bewusst nicht. */
.feld {
  display: block; width: 100%; margin-bottom: .7rem;
  background: var(--grund); border: 1px solid var(--rand);
  border-radius: .625rem; padding: .8rem .85rem;
  color: var(--text); font: inherit; font-size: 1rem;
}
.feld::placeholder { color: var(--leise); }
.feld:focus { outline: 2px solid var(--akzent); outline-offset: 1px; border-color: transparent; }
.feld--fehler { border-color: var(--niederlage); }

.setzen-knopf { width: 100%; border: 0; cursor: pointer; margin-top: .3rem; }
.setzen-knopf[disabled] { opacity: .55; cursor: default; }

/* ── „EckDaten als App" ─────────────────────────────────────────────────────
   Die Kachel muss zwei Dinge zugleich sein: auffällig genug, dass jemand die
   Funktion überhaupt bemerkt, und klein genug, dass sie nicht im Weg steht.
   Deshalb der Akzentrahmen, aber keine Akzentfläche. */
.karte--app { position: relative; border: 1px solid var(--akzent); }
/* Rechts bleibt Platz für das Wegtipp-Kreuz — ohne ihn schöbe sich die
   Überschrift darunter. */
.appkachel__kopf { display: flex; align-items: center; gap: .85rem; padding-right: 2.2rem; }
.appkachel__kopf h2 { margin: 0 0 .2rem; font-size: 1.05rem; }
.appkachel__symbol { flex: none; width: 48px; height: 48px; border-radius: .7rem; }

/* Das Wegtippen ist ein echter Knopf mit 44 Pixeln Kante — Apples Mindestmaß
   für etwas, das ein Daumen treffen soll. Ein 16-Pixel-Kreuz trifft niemand
   beim ersten Versuch, und wer zweimal danebentippt, klappt stattdessen die
   Karte auf. */
.appkachel__weg {
  position: absolute; top: .35rem; right: .35rem;
  width: 44px; height: 44px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 50%;
  color: var(--leise); font-size: 1.5rem; line-height: 1; cursor: pointer;
}
.appkachel__weg:hover { color: var(--text); background: var(--grund); }
.appkachel__weg-vom-kopf { margin-top: .9rem; }
.appkachel__fussnote { margin-top: .7rem; }

/* Die Schritte. Die Nummer steht in einer eigenen Spalte, damit mehrzeilige
   Schritte unter der Nummer einrücken statt darunter zu laufen. */
.schritte { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.schritt { display: grid; grid-template-columns: 1.6rem 1fr; gap: .6rem; align-items: start; }
.schritt__nummer {
  display: flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; border-radius: 50%;
  background: var(--akzent); color: var(--akzent-schrift);
  font-size: .8rem; font-weight: 700;
}
.schritt__text { font-size: .95rem; line-height: 1.55; }

/* Das Zeichen sitzt IN der Zeile, nicht daneben: Es steht für das Symbol, auf
   das der Finger als Nächstes trifft, und gehört deshalb mitten in den Satz.
   `vertical-align` hebt es auf die Höhe der Kleinbuchstaben. */
.schritt__zeichen {
  display: inline-block; width: 1.15em; height: 1.15em;
  vertical-align: -.22em; margin: 0 .1em; color: var(--akzent-text);
}

/* Der Wochentag vor der Uhrzeit: klein und zurückgenommen, weil er die
   unwichtigere Angabe ist. Er stand einmal vor der Paarung und schnitt dort
   den Vereinsnamen ab. */
.nk__tag { font-size: .75rem; font-weight: 600; color: var(--leise); margin-right: .3rem; }

/* ── Umfang der Ligameldungen ──────────────────────────────────────────────
   Eingerückt und mit Kante: Das gehört zum Haken darüber und ist keine
   eigenständige Frage. Wer die Einrückung wegnimmt, macht aus einer
   Rückfrage eine fünfte Option. */
.umfang {
  margin: .8rem 0 0 1.7rem; padding-left: .9rem;
  border-left: 2px solid var(--rand);
}
.umfang > label { display: block; margin-bottom: .35rem; }
.umfang { padding-bottom: .2rem; }
.feld--wahl { margin-bottom: 0; }

/* Die Vereinsliste. Zwei Spalten, damit siebzehn Zeilen nicht die halbe
   Karte füllen — und scrollbar, damit sie die Knöpfe darunter nicht
   wegschiebt. */
.vereinswahl {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(6.8rem, 1fr));
  gap: .1rem .6rem; max-height: 13rem; overflow-y: auto;
  padding: .3rem .1rem;
}
.vereinswahl__zeile {
  display: flex; align-items: center; gap: .45rem;
  padding: .3rem 0; font-size: .9rem; cursor: pointer;
}
.vereinswahl__zeile input { flex: none; width: 1.05rem; height: 1.05rem; accent-color: var(--akzent); }
/* Der Farbpunkt ist eine Zugabe, keine Information — das Kürzel steht
   daneben. Vereinswappen wären hier ohnehin tabu. */
.vereinswahl__punkt { flex: none; width: .6rem; height: .6rem; border-radius: 50%; }

/* Gleichstand ist weder Rückstand noch Vorsprung — und deshalb weder rot
   noch grün. „0 voraus" stand vorher in Grün da, als wäre es etwas wert. */
.ziel__wert--gleich { color: var(--leise); font-weight: 600; }

/* ── Nutzungszahlen auf der Betriebsseite ──────────────────────────────────
   Balken statt Tabelle: Bei zwölf Vereinen untereinander sagt die Länge
   mehr als die Zahl, und die Zahl steht ja daneben. */
.balken {
  display: grid; grid-template-columns: minmax(0, 9rem) 1fr auto;
  align-items: center; gap: .7rem; padding: .28rem 0; font-size: .9rem;
}
.balken__wort { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--leise); }
.balken__spur { height: .55rem; background: var(--grund); border-radius: 999px; overflow: hidden; }
.balken__fuellung { height: 100%; background: var(--akzent); border-radius: 999px; }
.balken__wert { font-variant-numeric: tabular-nums; font-weight: 650; min-width: 3.2rem; text-align: right; }

/* Der Tagesgang. Vierundzwanzig Säulen passen auf 390 Pixel, wenn man auf
   Beschriftung verzichtet — jede sechste Stunde reicht zur Orientierung. */
.gang { display: grid; grid-template-columns: repeat(24, 1fr); gap: 2px; height: 5.5rem; align-items: end; }
.gang__saeule { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.gang__fuellung { background: var(--akzent); border-radius: 2px 2px 0 0; }
.gang__wort { font-size: .6rem; color: var(--leise); text-align: center; height: .9rem; line-height: .9rem; }

/* Ein Kasten für Sätze, die dem widersprechen, was darunter steht — etwa
   „diese Tabelle ist noch keine Tabelle". Gedeckt, nicht alarmierend: Es ist
   kein Fehler, sondern eine Einordnung. */
.hinweis-kasten {
  margin: 0 0 .9rem; padding: .7rem .9rem;
  background: var(--flaeche); border: 1px dashed var(--rand);
  border-radius: .75rem; font-size: .9rem; color: var(--leise);
}
.hinweis-kasten strong { color: var(--text); }

/* ── Jubel ─────────────────────────────────────────────────────────────────
   Ein kleines Männchen in der Lagezeile, solange der eigene Verein vorn
   liegt. Es hüpft — aber nur, wenn das System Bewegung erlaubt. */
.jubel { width: 1.4rem; height: 1.9rem; flex: none; margin-left: .15rem; }
@media (prefers-reduced-motion: no-preference) {
  .jubel { animation: huepf 1.4s ease-in-out infinite; transform-origin: 50% 100%; }
  .jubel .jubel__arme { animation: winke 1.4s ease-in-out infinite; transform-origin: 50% 40%; }
}
@keyframes huepf { 0%,100% { transform: translateY(0); } 45% { transform: translateY(-12%); } }
@keyframes winke { 0%,100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }

/* Das Wetter steht auf einer eigenen Zeile, nicht am Ende einer Aufzählung. */
.wetterzeile {
  margin: .5rem 0 0; padding-top: .5rem;
  border-top: 1px solid var(--rand);
  font-size: .9rem; color: var(--leise);
}
.wetterzeile strong { color: var(--text); font-variant-numeric: tabular-nums; }

/* ── Lagekachel über der Tabelle ───────────────────────────────────────────
   „Wenn es so bleibt" und „Wie weit ist es?". Die erste erscheint nur,
   solange etwas läuft; die zweite immer, sobald gespielt wurde. */
.lagekarte h2 { display: flex; align-items: center; gap: .5rem; }
.lagekarte__satz { margin: .2rem 0 .5rem; font-size: 1.05rem; }
.lagekarte__satz strong { color: var(--akzent-text); }

.abstand {
  display: grid; grid-template-columns: 1fr auto;
  gap: 0 .8rem; padding: .5rem 0;
  border-bottom: 1px solid var(--rand);
}
.abstand:last-of-type { border-bottom: 0; }
.abstand__wort { font-weight: 650; font-size: .95rem; }
.abstand__wert {
  grid-column: 2; grid-row: 1 / span 2; align-self: center;
  font-weight: 700; color: var(--akzent-text); font-variant-numeric: tabular-nums;
}
.abstand__wer { grid-column: 1; font-size: .82rem; color: var(--leise); }

/* Die Formkurve in der Tabellenzeile — kleiner als die in der Bilanz, aber
   nach denselben Regeln: eigene Statuspalette, und in JEDEM Feld steht der
   Buchstabe. Grün-Gelb-Rot ist der klassische Rot-Grün-Fall; ohne die zweite
   Kodierung wäre die Spalte für einen von zwanzig Männern unlesbar. */
.tab__form { white-space: nowrap; }
.formfleck {
  display: inline-grid; place-items: center;
  width: 1.05rem; height: 1.05rem; margin-right: .12rem;
  border-radius: .22rem;
  font-size: .62rem; font-weight: 700; color: var(--status-schrift);
}
.formfleck--S { background: var(--sieg); }
.formfleck--U { background: var(--unentschieden); }
.formfleck--N { background: var(--niederlage); }

/* Stadion und Fassungsvermögen über dem Ticker. Es ändert sich während des
   Spiels nicht — deshalb oben und ruhig, während darunter alles läuft. */
.spielort {
  margin: 0 0 .6rem; padding-bottom: .5rem;
  border-bottom: 1px solid var(--rand);
  font-size: .92rem; font-weight: 650;
}

/* ── Damals und heute ──────────────────────────────────────────────────────
   Zwei Zahlen nebeneinander und ein Pfeil dazwischen. Ein Balkendiagramm
   für zwei Werte wäre Zierrat — der Vergleich steckt im Vergleich. */
.damals {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: .8rem; margin: .5rem 0 .8rem;
}
.damals__spalte { text-align: center; }
.damals__wert { font-size: 2rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.damals__wort { font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--leise); margin-top: .3rem; }
.damals__pfeil { font-size: 1.3rem; }

/* ── Die Pille ─────────────────────────────────────────────────────────────
   Sie trägt die eine Angabe, die sich ständig ändert, und sagt schon durch
   ihre Aufmachung, in welchem Zustand die Partie ist. Aus der Bocholt-App
   übernommen, wo sich die drei Gesichter bewährt haben. */
.nk__lage { gap: .45rem; }
.nk__rest { overflow: hidden; text-overflow: ellipsis; }

.pille {
  flex: none;
  display: inline-flex; align-items: center;
  padding: .16rem .55rem;
  border: 1px solid var(--rand); border-radius: 999px;
  font-size: .74rem; font-weight: 700; letter-spacing: .04em;
  text-transform: none; white-space: nowrap;
  color: var(--leise);
}

/* Vorfreude: Der Umriss atmet leise mit. Kein Blinken — es passiert ja noch
   nichts, es steht nur etwas bevor. */
.pille--kommend { color: var(--akzent-text); border-color: var(--rand); }
@media (prefers-reduced-motion: no-preference) {
  .pille--kommend { animation: vorfreude 2.6s ease-in-out infinite; }
}
@keyframes vorfreude {
  0%, 100% { border-color: var(--rand); transform: scale(1); }
  50%      { border-color: var(--akzent); transform: scale(1.04); }
}

/* Es läuft: ausgefüllt statt Umriss, mit pulsierendem Punkt. Das Atmen hört
   auf — jetzt passiert wirklich etwas, und zwei Bewegungen nebeneinander
   heben sich gegenseitig auf. */
.pille--live {
  background: var(--akzent); border-color: var(--akzent);
  color: var(--akzent-schrift); animation: none;
}
.pille--live::before {
  content: ''; width: .42rem; height: .42rem; margin-right: .38rem;
  border-radius: 50%; background: currentColor; flex: none;
}
@media (prefers-reduced-motion: no-preference) {
  .pille--live::before { animation: puls 1.6s ease-in-out infinite; }
}
@keyframes puls { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* Nach dem Abpfiff steht der Endstand ruhig da. Kein Atmen — es gibt nichts
   mehr zu erwarten —, aber eine deutliche Plakette, damit klar ist, dass die
   Zahl daneben ein Ergebnis ist und keine Vorschau. */
.pille--beendet { border-color: var(--leise); color: var(--text); animation: none; }

/* ── Zwei Wege aus der Kachel ──────────────────────────────────────────────
   Nur, solange in der Liga gespielt wird. Sonst täten sie dasselbe wie die
   Reiterleiste darunter — also nichts. */
.weiter { display: flex; gap: .6rem; margin-top: 1rem; }
.weiter__knopf {
  flex: 1 1 0; min-height: 2.7rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .1rem; padding: .45rem .6rem;
  background: transparent; border: 1px solid var(--rand); border-radius: .8rem;
  color: var(--text); font: inherit; font-size: .88rem; font-weight: 650;
  cursor: pointer; text-align: center;
}
.weiter__knopf:hover { border-color: var(--akzent); }
.weiter__zahl {
  font-size: .7rem; font-weight: 700; color: var(--akzent-text);
  text-transform: uppercase; letter-spacing: .06em;
}

/* ── Das BUILD-Fähnchen ────────────────────────────────────────────────────
   Nur auf der Build-Instanz, gesetzt von `zeigeBuildFaehnchen()`. Rot, weil
   Rot hier nichts anderes bedeutet: Die Vereinsfarben sind zwar oft rot, die
   Statuspalette benutzt aber ein eigenes Rot für Niederlagen — und das steht
   nie am Bildschirmrand.

   `position: fixed` und ein sehr hoher Stapelwert: Das Fähnchen muss über
   allem liegen, auch über der Reiterleiste. Wer es übersieht, hält das
   Build-System für die echte Seite. */
.buildflagge {
  position: fixed; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  width: 2rem; min-height: 5.2rem; padding: .6rem 0;
  background: #C81E1E; color: #FFFFFF;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .5);
  cursor: grab; touch-action: none; user-select: none;
  transform: translateY(-50%);
}
.buildflagge[data-seite="rechts"] { right: 0; border-radius: .5rem 0 0 .5rem; }
.buildflagge[data-seite="links"]  { left: 0;  border-radius: 0 .5rem .5rem 0; }
.buildflagge--zieht { cursor: grabbing; opacity: .85; }

/* Der Schriftzug steht quer — sonst bräuchte das Fähnchen die halbe
   Bildschirmbreite. */
.buildflagge__wort {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-size: .72rem; font-weight: 800; letter-spacing: .22em;
}
.buildflagge[data-seite="links"] .buildflagge__wort { transform: rotate(180deg); }

/* Ein schmaler roter Streifen oben schließt die letzte Lücke: Wer nur ein
   Bildschirmfoto vom oberen Rand sieht, erkennt es trotzdem. */
:root[data-system="build"] body::before {
  content: ''; position: fixed; inset: 0 0 auto 0; height: 3px;
  background: #C81E1E; z-index: 9998; pointer-events: none;
}

/* Die Zusatzzeile in der Kachel — Spieltag und, wo nötig, ein Hinweis auf
   die geschätzte Minute. Sie ersetzt die volle Paarung, die dort einmal
   stand und die Angabe aus dem Kopf nur wiederholte. */
.naechstes__zusatz { margin: 0 0 .6rem; }

/* Das Ausgangszeichen sitzt neben der Pille. Am Stand nahm es der Paarung
   23 Pixel, und „Augsburg – Schalke" wurde zu „Augsburg – Sch…". */
.nk__lage .formfleck { flex: none; width: 1rem; height: 1rem; font-size: .6rem; }

/* ── Probelauf ─────────────────────────────────────────────────────────────
   Ein Streifen ganz oben, der blinkt. Sonst gilt hier: Blinken zieht das
   Auge von allem anderen ab — genau das soll es. Wer erfundene Ergebnisse
   für echte hält, erzählt sie weiter.

   Wer im System Bewegung reduziert hat, bekommt ihn ohne Blinken. Dann trägt
   die Farbe allein; die Aussage steckt im Text, nicht im Takt. */
.probelauf {
  position: fixed; inset: 0 0 auto 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: .1rem .6rem;
  padding: .4rem .8rem calc(.4rem + env(safe-area-inset-top));
  background: #B3211F; color: #FFFFFF;
  font-size: .8rem; text-align: center;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .5);
}
.probelauf__wort { font-weight: 800; letter-spacing: .12em; }
.probelauf__text { opacity: .95; }
.probelauf__schritt { font-variant-numeric: tabular-nums; opacity: .8; }

@media (prefers-reduced-motion: no-preference) {
  .probelauf { animation: probeblink 1.2s step-end infinite; }
}
@keyframes probeblink {
  0%, 49%   { background: #B3211F; }
  50%, 100% { background: #7A1614; }
}

/* Die Kopfzeile rückt nach unten, sonst läge sie unter dem Streifen. */
body.mit-probelauf .kopf { top: 2.1rem; }
body.mit-probelauf { padding-top: 2.1rem; }

/* Bewegungspfeile in der Live-Tabelle. Ein Zeichen ZUSÄTZLICH zur Farbe —
   Grün und Rot allein wären für einen von zwanzig Männern gleich. */
.tab__hoch, .tab__runter { font-size: .6rem; margin-left: .2rem; vertical-align: .1em; }
.tab__hoch { color: var(--sieg); }
.tab__runter { color: var(--niederlage); }

/* Wer gerade spielt, pulsiert. Der Punkt sitzt hinter dem Vereinsnamen —
   nicht davor, sonst verschöbe er bei jedem Anpfiff die ganze Spalte.
   Wer Bewegung reduziert hat, sieht ihn ruhig; sichtbar bleibt er. */
.tab__laeuft {
  display: inline-block; width: .45rem; height: .45rem; margin-left: .4rem;
  border-radius: 50%; background: var(--akzent-text); vertical-align: .1em;
}
@media (prefers-reduced-motion: no-preference) {
  .tab__laeuft { animation: puls 1.6s ease-in-out infinite; }
}

/* ── Glocke und Brief in der Vereinsleiste ─────────────────────────────────
   Die beiden Fragen, die man am häufigsten hat, dort wo der Verein steht. */
.held__zeile { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.held__knoepfe { display: flex; gap: .3rem; flex: none; margin-top: .2rem; }

/* 44 Pixel Kantenlänge — Apples Mindestmaß für etwas, das ein Daumen treffen
   soll. Ein 20-Pixel-Symbol trifft niemand beim ersten Versuch. */
.held__knopf {
  position: relative;
  width: 2.75rem; height: 2.75rem; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 50%;
  color: var(--verein-schrift); cursor: pointer;
}
.held__knopf svg { width: 1.4rem; height: 1.4rem; }
.held__knopf:hover { background: rgb(255 255 255 / 14%); }
/* AUSGESCHALTET HEISST DURCHGESTRICHEN, nicht blass.
   Erst war es beides; das Blasse tat aber nichts, weil man den Unterschied
   zwischen 55 % und 100 % Deckkraft nur sieht, wenn beide Zustände
   nebeneinanderliegen — und das tun sie nie. Der Strich sieht man auch
   allein. Die volle Deckkraft bleibt, damit die Glocke nicht wie ein
   abgeschalteter Knopf aussieht: Sie ist ja bedienbar. */
.held__knopf--aus { opacity: 1; }

/* Der Strich bekommt einen Saum in der Vereinsfarbe. Ohne ihn verschwindet
   er dort, wo er über die Glockenlinien läuft. */
.glocke__strich {
  paint-order: stroke;
  stroke: currentColor;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 1.5px var(--verein));
}

/* Die Zahl der ungelesenen Meldungen. Sie sitzt AUF dem Brief, nicht daneben:
   Daneben wäre sie eine eigene Angabe, darauf gehört sie zum Symbol. */
.held__zahl {
  position: absolute; top: .25rem; right: .2rem;
  min-width: 1.05rem; height: 1.05rem; padding: 0 .2rem;
  display: grid; place-items: center;
  border-radius: 999px; background: var(--signal); color: #12100B;
  font-size: .65rem; font-weight: 800; line-height: 1;
}

/* ── Das Postfach ──────────────────────────────────────────────────────────
   Was ankam, auch wenn es auf dem Sperrbildschirm längst weggewischt ist. */
.postfach {
  margin: 0 0 1rem; padding: .9rem 1.1rem 1rem;
  background: var(--flaeche); border: 1px solid var(--rand); border-radius: 1rem;
}
.postfach__kopf { display: flex; align-items: center; gap: .7rem; margin-bottom: .5rem; }
.postfach__kopf h2 { margin: 0; font-size: 1rem; flex: 1; }
.postfach__zu {
  width: 2rem; height: 2rem; flex: none; padding: 0;
  background: transparent; border: 0; border-radius: 50%;
  color: var(--leise); font-size: 1.3rem; line-height: 1; cursor: pointer;
}
.postfach__zu:hover { color: var(--text); background: var(--grund); }

.postzeile {
  display: grid; grid-template-columns: 1.4rem 1fr auto;
  gap: .1rem .6rem; align-items: start;
  padding: .5rem 0; border-bottom: 1px solid var(--rand);
}
.postzeile:last-child { border-bottom: 0; }
.postzeile__zeichen { font-size: .95rem; line-height: 1.4; }
.postzeile__titel { font-size: .92rem; font-weight: 650; }
.postzeile__text { font-size: .85rem; color: var(--leise); }
.postzeile__zeit { font-size: .75rem; color: var(--leise); font-variant-numeric: tabular-nums; }

/* Neu gegen gelesen. Zwei Kodierungen, nicht nur Farbe: ein Punkt UND
   kräftigere Schrift — Farbe allein macht für einen von zwanzig Männern
   keinen Unterschied. */
.postzeile--neu .postzeile__titel { color: var(--text); font-weight: 750; }
.postzeile:not(.postzeile--neu) .postzeile__titel { color: var(--leise); font-weight: 600; }
.postzeile:not(.postzeile--neu) .postzeile__text { opacity: .75; }
.postzeile__punkt {
  display: inline-block; width: .45rem; height: .45rem; margin-right: .35rem;
  border-radius: 50%; background: var(--signal); vertical-align: .1em;
}
.postfach__fuss { margin: .7rem 0 0; padding-top: .5rem; border-top: 1px solid var(--rand); }
