/* Boule-Boy Webview — dunkles Anzeigetafel-Theme, für das Handy gebaut,
   auf dem Desktop großzügiger. */

:root {
  --bg: #0a1422;
  --bg-2: #0e1c2f;
  --surface: #142338;
  --surface-2: #192c45;
  --border: #21374f;
  --border-soft: rgba(33, 55, 79, .55);
  --border-hover: #35577c;
  /* Der Lichtschein oben auf der Seite (siehe body) und die halb
     durchscheinende Kopfleiste. */
  --glow: #12243c;
  --top-bg: rgba(14, 28, 47, .88);

  --text: #eaf1fa;
  --muted: #8fa4bd;
  --dim: #6b7f97;

  --gold: #f5b739;
  --silver: #c9d3e0;
  --bronze: #cd7f32;
  --accent: #3b8ef0;
  --win: #34d399;
  --err: #f87171;

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 18px;
  --shadow: 0 1px 2px rgba(0,0,0,.35), 0 8px 24px -12px rgba(0,0,0,.6);
}

/* ── Sonnenmodus ──────────────────────────────────────────────────────────
   Die Seite ist dunkel gebaut wie die Tafel im Saal. Draussen auf dem Platz,
   in der Mittagssonne, ist ein dunkler Bildschirm aber kaum zu lesen — die
   Spiegelung frisst den Kontrast. Darum ein helles Thema: Vorgabe ist die
   Wahl des Betriebssystems (prefers-color-scheme), der Knopf oben rechts
   ueberstimmt sie und merkt sich das (data-theme am <html>, siehe
   95-router.js). Dieselbe Palette steht zweimal, weil ein Medienabfrage-
   Block keinen Selektor teilen kann: einmal fuer die Systemwahl ohne
   Knopfdruck, einmal fuer den Knopf. */
:root[data-theme="light"] {
  --bg: #f3f5f8;
  --bg-2: #ffffff;
  --surface: #ffffff;
  --surface-2: #eef2f7;
  --border: #d3dbe6;
  --border-soft: rgba(211, 219, 230, .7);
  --border-hover: #9fb3cc;
  --glow: #e1e9f4;
  --top-bg: rgba(255, 255, 255, .86);

  --text: #14213a;
  --muted: #55677f;
  --dim: #7a8ba1;

  --gold: #b7820a;
  --silver: #7f8c9c;
  --bronze: #a8621a;
  --accent: #1f6fd0;
  --win: #15925f;
  --err: #d43f3f;

  --shadow: 0 1px 2px rgba(20,33,58,.08), 0 8px 24px -12px rgba(20,33,58,.2);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #f3f5f8;
    --bg-2: #ffffff;
    --surface: #ffffff;
    --surface-2: #eef2f7;
    --border: #d3dbe6;
    --border-soft: rgba(211, 219, 230, .7);
    --border-hover: #9fb3cc;
    --glow: #e1e9f4;
    --top-bg: rgba(255, 255, 255, .86);

    --text: #14213a;
    --muted: #55677f;
    --dim: #7a8ba1;

    --gold: #b7820a;
    --silver: #7f8c9c;
    --bronze: #a8621a;
    --accent: #1f6fd0;
    --win: #15925f;
    --err: #d43f3f;

    --shadow: 0 1px 2px rgba(20,33,58,.08), 0 8px 24px -12px rgba(20,33,58,.2);
  }
}

* { box-sizing: border-box; }

/* Sanftes Einblenden beim Ansichtswechsel (Klasse wird per JS neu gesetzt).
   Wer „reduzierte Bewegung" eingestellt hat, bekommt keins — Vorschrift und
   Ruecksicht zugleich. */
@keyframes fadein { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.fadein { animation: fadein .18s ease-out; }
@media (prefers-reduced-motion: reduce) { .fadein { animation: none; } }

/* Die Schriftgroesse haengt an EINER Zahl.
   `--fs` ist der Faktor, den der Knopf oben rechts verstellt (siehe
   script/app.js, `schriftStufe`). Alles andere in dieser Datei rechnet in
   `rem` — dadurch waechst mit dem Grundmass auch jede Ueberschrift, jeder
   Tabellenwert und jeder Abstand, der in `em` steht.

   18px statt 16px als Ausgangswert: Diese Seite wird auf dem Platz gelesen,
   im Stehen, oft aus zwei Metern Entfernung auf einem Bildschirm im
   Vereinsheim. Was am Schreibtisch angenehm ist, ist dort zu klein. */
html {
  -webkit-text-size-adjust: 100%;
  font-size: calc(18px * var(--fs, 1));
}

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(1200px 600px at 50% -10%, var(--glow) 0%, transparent 60%),
    var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  /* In rem, nicht in px: Sonst haenge der Text nicht am Grundmass oben und
     der Knopf verstellte alles ausser dem Fliesstext. */
  font-size: 1rem;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }

.wrap { flex: 1; width: 100%; max-width: 1100px; margin: 0 auto; padding: 20px 16px 56px; }

/* ── Kopfleiste ───────────────────────────────────────────────────────── */
.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px;
  background: var(--top-bg);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--border-soft);
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand img { border-radius: 7px; }
.brand-text { font-weight: 800; letter-spacing: .06em; font-size: 1rem; }
.gold { color: var(--gold); }

.top-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }

.iconbtn {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border); color: var(--muted);
  font-weight: 800; font-size: .92rem;
  transition: border-color .16s ease, color .16s ease, background .16s ease;
}
.iconbtn:hover { border-color: var(--gold); color: var(--gold); background: rgba(245,183,57,.08); }

/* Sprachwahl: bewusst ein schlichtes <select> — es ist auf jedem Gerät
   bedienbar und braucht kein eigenes Menü. */
.langsel {
  font: inherit; font-size: .82rem; font-weight: 600;
  color: var(--muted); background: var(--bg-2);
  border: 1px solid var(--border); border-radius: 999px;
  padding: 4px 8px; cursor: pointer;
}
.langsel:hover { border-color: var(--border-hover); color: var(--text); }

/* ── Fingerziele ──────────────────────────────────────────────────────────
   Ein Daumen trifft keinen 30-Pixel-Kreis sicher; 44 Pixel sind das Mass,
   das Apple und Google nennen. Die Knoepfe bleiben optisch klein — sie
   sollen die Kopfleiste nicht dominieren —, bekommen aber auf Touch-Geraeten
   (pointer: coarse) eine unsichtbare Trefferflaeche rundherum. Dasselbe fuer
   die „↗"-Links im Infoblock: eine Zeile Text ist am Handy zu schmal. */
@media (pointer: coarse) {
  .iconbtn, .maplink { position: relative; }
  .iconbtn::before, .maplink::before {
    content: ''; position: absolute; left: -7px; right: -7px;
    top: -7px; bottom: -7px;
  }
  .maplink::before { top: -12px; bottom: -12px; left: 0; right: 0; }
  .langwrap.open .langsel { padding: 10px 14px; font-size: .95rem; }
}

/* Sprachwahl: am Desktop das schlichte <select> direkt in der Kopfleiste.
   Auf dem Smartphone rückt es in ein kleines Overflow-Menü hinter einen
   Globus-Knopf, damit die Kopfleiste nicht überläuft. */
.langwrap { position: relative; display: flex; align-items: center; }
.langtoggle { display: none; }
@media (max-width: 640px) {
  /* Auf dem Handy ist die Kopfleiste eng: Der Schriftzug brach in
     „BOULE-" und „BOY" um, sobald rechts die vier Knoepfe standen, und bei
     360 Pixeln ragte der letzte Knopf ueber den Rand. Der Schriftzug bleibt
     eine Zeile; wenn etwas weichen muss, dann die Live-Anzeige (sie wird
     mit „…" gekuerzt), nie die Knoepfe. */
  .top { gap: 8px; padding: 10px 12px; }
  .top-right { gap: 6px; flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
  .brand { gap: 6px; flex: 0 0 auto; }
  .brand img { width: 28px; height: 28px; }
  .brand-text { white-space: nowrap; font-size: .92rem; letter-spacing: .03em; }
  .live-dot { min-width: 0; letter-spacing: .04em; }
  .live-dot.stale { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .langtoggle { display: inline-grid; }
  .langwrap .langsel {
    display: none;
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 30;
    box-shadow: var(--shadow);
  }
  .langwrap.open .langsel { display: block; }
}

.live-dot[hidden] { display: none; }
.live-dot {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .74rem; font-weight: 700; letter-spacing: .08em;
  color: var(--win); text-transform: uppercase;
}
.live-dot::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--win); box-shadow: 0 0 0 0 rgba(52,211,153,.6);
  animation: pulse 2.2s ease-out infinite;
}
/* Veralteter Stand: kein Gruen, kein Pulsieren — die Anzeige soll nicht
   weiter Aktualitaet vortaeuschen, wenn gerade nichts ankommt. */
.live-dot.stale { color: var(--dim); text-transform: none; letter-spacing: 0; }
.live-dot.stale::before { background: var(--dim); box-shadow: none; animation: none; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(52,211,153,.55); }
  70%  { box-shadow: 0 0 0 7px rgba(52,211,153,0); }
  100% { box-shadow: 0 0 0 0 rgba(52,211,153,0); }
}

/* ── Typografie ───────────────────────────────────────────────────────── */
h1 { font-size: clamp(1.5rem, 5vw, 2rem); line-height: 1.15; margin: 0 0 6px; letter-spacing: -.01em; }
h2 { font-size: .95rem; margin: 0; }
h3 { font-size: 1.06rem; margin: 0 0 6px; line-height: 1.3; }
.sub { color: var(--muted); margin: 0; }
.muted { color: var(--muted); }
.small { font-size: .86rem; }

.hero { margin-bottom: 26px; }

/* Vereinsansicht: Logo neben dem Vereinsnamen. Feste Kantenlänge mit
   object-fit, damit ein hoch- oder querformatiges Logo die Zeile nicht
   verzieht. */
.org-hero { display: flex; align-items: center; gap: 14px; }
.org-logo {
  flex: none; width: 56px; height: 56px;
  object-fit: contain;
  transform-origin: center bottom;
  /* Kurzes Wackeln beim Erscheinen — laeuft einmal und bleibt dann still.
     „prefers-reduced-motion" schaltet es ab (Ruecksicht und Vorschrift). */
  animation: logowackel .7s ease-in-out .15s both;
}
@keyframes logowackel {
  0%   { transform: rotate(0deg); }
  15%  { transform: rotate(-9deg); }
  30%  { transform: rotate(7deg); }
  45%  { transform: rotate(-5deg); }
  60%  { transform: rotate(3deg); }
  75%  { transform: rotate(-1.5deg); }
  100% { transform: rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) { .org-logo { animation: none; } }

.sec {
  display: flex; align-items: center; gap: 10px;
  margin: 30px 0 12px;
  font-size: .78rem; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dim);
}
.sec::after { content: ""; flex: 1; height: 1px; background: var(--border-soft); }

/* ── Turnierkarten ────────────────────────────────────────────────────── */
.tcard {
  position: relative; display: block;
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg-2) 100%);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 16px 44px 16px 18px;
  margin-bottom: 12px;
  box-shadow: var(--shadow);
  transition: border-color .16s ease, transform .16s ease, background .16s ease;
}
.tcard { border-left-width: 3px; }
.tcard.live { border-left-color: var(--win); }
.tcard.open { border-left-color: var(--gold); }
.tcard.soon { border-left-color: var(--accent); }
.tcard.ready { border-left-color: #2dd4bf; }
.tcard.done { border-left-color: var(--border); }
.tcard:hover { border-color: var(--border-hover); }
@media (hover: hover) {
  .tcard { will-change: transform; }
  .tcard:hover { transform: translateY(-2px); box-shadow: 0 10px 26px -14px rgba(0,0,0,.7); }
}
.tcard:active { transform: scale(.995); }
.tcard .chev {
  position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
  color: var(--dim); font-size: 1.5rem; line-height: 1;
}

/* Turnierkarte mit Anmeldeknopf: der Knopf sitzt unten an der Karte und
   bildet mit ihr optisch einen Block. Die Karte verliert dafür ihren unteren
   Abstand und ihre unteren Ecken. */
.tcard-wrap { margin-bottom: 12px; }
.tcard-wrap.has-reg .tcard {
  margin-bottom: 0;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
  border-bottom-color: transparent;
}
.reg-link {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 16px;
  font-weight: 700; font-size: .92rem; letter-spacing: .02em;
  color: #10233c; background: linear-gradient(180deg, #ffc95a, var(--gold));
  border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.reg-link::after { content: "›"; font-size: 1.2rem; line-height: 1; }
.reg-link:hover { filter: brightness(1.06); }

.meta { display: flex; flex-wrap: wrap; gap: 6px 16px; color: var(--muted); font-size: .87rem; }
/* Belegungszeile auf der Turnierkarte — etwas kleiner als die Turnierdaten
   darueber, damit sie die Karte nicht dominiert. */
.meta.cap { margin-top: 6px; font-size: .82rem; }
.cap-free { color: var(--win); font-weight: 600; }
.cap-wait { color: var(--gold); font-weight: 600; }
.cap-full { color: var(--err); font-weight: 600; }
/* Laufendes Turnier: gerade gespielte Runde/Phase statt Belegung. */
.live-phase { color: var(--win); font-weight: 700; }
.live-phase svg { opacity: 1; }
.mi { display: inline-flex; align-items: center; gap: 6px; }
.mi svg { flex: none; opacity: .75; }
/* „Nur fuer Vereinsmitglieder" — als abgesetzter Hinweis, damit klar ist, dass
   hier keine oeffentliche Anmeldung moeglich ist. */
.mi.members { color: var(--gold); font-weight: 600; }
.mi.members svg { opacity: 1; }
.mi.license { color: var(--accent); font-weight: 600; }
.mi.license svg { opacity: 1; }

/* Auf breiten Bildschirmen die Liste zweispaltig — auf dem Handy waere das
   unlesbar, dort bleibt es einspaltig. Die Ueberschriften spannen beide
   Spalten, align-items:start haelt kurze Karten oben. */
@media (min-width: 900px) {
  #results { display: grid; grid-template-columns: 1fr 1fr; column-gap: 16px; align-items: start; }
  #results .sec { grid-column: 1 / -1; }
}

/* ── Badges ───────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; margin-bottom: 10px;
  border-radius: 999px;
  font-size: .72rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  border: 1px solid transparent;
}
.badge.live { background: rgba(52,211,153,.13); color: var(--win); border-color: rgba(52,211,153,.42); }
.badge.open { background: rgba(245,183,57,.13); color: var(--gold); border-color: rgba(245,183,57,.42); }
.badge.soon { background: rgba(59,142,240,.13); color: #7fb2ff; border-color: rgba(59,142,240,.42); }
.badge.ready { background: rgba(45,212,191,.14); color: #5eead4; border-color: rgba(45,212,191,.42); }
.badge.done { background: rgba(143,164,189,.10); color: var(--muted); border-color: rgba(143,164,189,.3); }
.badge.live::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; animation: pulse 2.2s ease-out infinite;
}

/* ── Panels ───────────────────────────────────────────────────────────── */
.phead { margin-bottom: 22px; }
/* Live-Spielstand: Boule-Boy-Logo links im Kopf. Kurzer Wackler nur beim
   ersten Aufbau (Klasse .wobble), nicht bei jedem Poll. */
.live-phead { display: flex; align-items: flex-start; gap: 14px; }
.live-phead .phead-body { flex: 1; min-width: 0; }
/* Kopf-Aktionen (Teilen, Drucken, Folgen) rechts im Detailkopf. */
.phead-actions { flex: none; display: flex; gap: 8px; }
/* Groesser als frueher (38px): Die Knoepfe werden draussen am Platz mit
   dem Daumen getroffen, nicht am Schreibtisch mit der Maus. */
.iconbtn2 {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-width: 46px; height: 46px; padding: 0 13px;
  border-radius: 12px; cursor: pointer;
  color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--border);
  font: inherit; font-size: .95rem; font-weight: 600;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.iconbtn2 svg { width: 20px; height: 20px; }
.iconbtn2:hover { color: var(--gold); border-color: var(--gold); }
.iconbtn2.on { color: #14213a; background: var(--gold); border-color: var(--gold); }

/* Smartphone: Vereinslogo nur halb so groß, und die Turnierinfos bekommen die
   volle Breite (Logo + Aktionen in der ersten Zeile, Details darunter) — sonst
   quetscht sich Titel und Metazeile in eine viel zu schmale Spalte. */
@media (max-width: 640px) {
  .live-phead { flex-wrap: wrap; gap: 8px 10px; }
  .live-logo.big { width: 42px; height: 42px; border-radius: 8px; }
  .live-phead .phead-body { order: 3; flex: 1 1 100%; }
  .phead-actions { order: 2; margin-left: auto; }
  .iconbtn2 { min-width: 44px; height: 44px; padding: 0 10px; }
  .live-phead h1 { font-size: clamp(1.35rem, 6vw, 1.7rem); }
}

/* Dezente Kurzmeldung („Link kopiert"). */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 20px);
  z-index: 1000; max-width: 90vw;
  padding: 10px 16px; border-radius: 999px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  font-size: .9rem; font-weight: 600;
  opacity: 0; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

/* Geländekarten-Overlay (Bild in Großansicht) */
.mapmodal {
  position: fixed; inset: 0; z-index: 1100;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(6, 12, 22, .82);
}
.mapmodal-box {
  position: relative; display: flex; flex-direction: column;
  max-width: min(960px, 96vw); max-height: 92vh;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: var(--shadow); overflow: hidden;
}
.mapmodal-title {
  padding: 12px 44px 10px 16px; font-weight: 700; color: var(--text);
  border-bottom: 1px solid var(--border);
}
.mapmodal-scroll { overflow: auto; padding: 12px; }
.mapmodal-scroll img {
  display: block; max-width: 100%; height: auto; margin: 0 auto;
  border-radius: 8px;
}
.mapmodal-x {
  position: absolute; top: 8px; right: 8px; z-index: 1;
  width: 32px; height: 32px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2);
  color: var(--text); font-size: 1.3rem; line-height: 1;
}
.mapmodal-x:hover { color: var(--gold); border-color: var(--gold); }
.mapmodal-actions {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 10px 16px 14px; border-top: 1px solid var(--border);
}
/* „Bild speichern" und „Als PDF drucken" sehen gleich aus — auf dem Platz ist
   keine der beiden die naheliegendere Wahl. */
.mapmodal-print, .mapmodal-save {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2);
  color: var(--text); font: inherit; font-weight: 600;
}
.mapmodal-print:hover, .mapmodal-save:hover {
  color: var(--gold); border-color: var(--gold);
}
/* Turnstile-Platzhalter. Das Widget bringt seine eigene Groesse mit; hier nur
   Abstand und Zentrierung, damit es auf dem Handy nicht am Rand klebt. */
.captcha { margin: 14px 0 4px; display: flex; justify-content: center; }

/* Beim Drucken nie das App-Overlay/Modal mitdrucken (der iframe druckt selbst). */
@media print { .mapmodal { display: none !important; } }

/* Merkliste „zuletzt gesehen": Chips über der Turnierliste. */
.recent { margin: 0 0 18px; }
.recent-h {
  font-size: .74rem; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); margin-bottom: 8px;
}
.recent-row {
  display: flex; gap: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding-bottom: 2px;
}
.recent-row::-webkit-scrollbar { display: none; }
.chip {
  flex: none; max-width: 60vw; padding: 7px 12px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  color: var(--muted); font-size: .84rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chip:hover { color: var(--gold); border-color: var(--gold); }

/* Spieler-Suche in der Vereinsmeisterschaft. */
.psearch { margin: 0 0 14px; }
.psearch input {
  width: 100%; max-width: 340px; padding: 9px 12px;
  border-radius: var(--r-sm); background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); font: inherit; font-size: .9rem;
}
.psearch input:focus { outline: none; border-color: var(--gold); }
/* Treffer der Spieler-Suche hervorheben. */
.pmatch {
  background: rgba(245,183,57,.22); color: var(--gold) !important;
  border-radius: 5px; padding: 0 3px; font-weight: 700;
}
.live-logo {
  flex: none; width: 42px; height: 42px; border-radius: 8px;
  object-fit: contain; transform-origin: center bottom;
}
/* Vereinslogo darf doppelt so gross sein wie das Boule-Boy-Logo. */
.live-logo.big { width: 84px; height: 84px; border-radius: 12px; }
.live-logo.wobble { animation: logowackel .7s ease-in-out .1s both; }
@media (prefers-reduced-motion: reduce) { .live-logo.wobble { animation: none; } }

/* Gruppen der Vereinsmeisterschaft: zwei nebeneinander, sobald genug Platz
   ist. Auf dem Handy blieben zwei Spalten unlesbar — dort untereinander.
   align-items:start, damit eine kurze Gruppe nicht auf die Hoehe der langen
   danebenstehenden gezogen wird. */
.grid-2 { display: grid; grid-template-columns: 1fr; column-gap: 16px; align-items: start; }
@media (min-width: 640px) { .grid-2 { grid-template-columns: 1fr 1fr; } }

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: 16px;
}
.panel-head {
  display: flex; align-items: baseline; gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-soft);
  background: linear-gradient(180deg, rgba(255,255,255,.03), transparent);
}
.panel-head h2 { font-size: .8rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--gold); }
.upd { margin-left: auto; font-size: .74rem; color: var(--dim); font-variant-numeric: tabular-nums; }
.panel-body { padding: 14px 16px; }
/* Auf dem Handy bricht die Zusatzangabe rechts um („Runde 2 von 4 · Bahnen
   dieser Runde"), nicht die Ueberschrift: „WO MUSS ICH / HIN?" las sich wie
   zwei Zeilen Titel. */
@media (max-width: 640px) {
  .panel-head { gap: 10px; padding: 12px 14px; }
  .panel-head h2 { white-space: nowrap; flex: 0 0 auto; }
  .panel-head .upd { min-width: 0; text-align: right; }
  .panel-body { padding: 12px 14px; }
}
/* Einklappbare Panels: Kopf ist anklickbar, Chevron zeigt den Zustand. */
.panel.collapsible > .panel-head { cursor: pointer; user-select: none; }
.panel.collapsible > .panel-head .upd { margin-left: auto; }
.panel-chevron {
  display: inline-flex; align-items: center; color: var(--dim);
  transition: transform .18s ease; flex: 0 0 auto;
}
.panel.collapsible:not(.collapsed) > .panel-head .panel-chevron { transform: rotate(180deg); }
.panel.collapsible > .panel-head:hover .panel-chevron { color: var(--gold); }
/* Zugeklappt: Kopf ohne Trennlinie, restlicher Inhalt ausgeblendet. */
.panel.collapsible.collapsed > .panel-head { border-bottom: 0; }
.panel.collapsible.collapsed > *:not(.panel-head) { display: none; }
.panel.collapsible > .panel-head:focus-visible {
  outline: 2px solid var(--gold); outline-offset: -2px;
}

/* ── Rangliste ────────────────────────────────────────────────────────── */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 11px 10px; text-align: right; white-space: nowrap; }
/* Sechs Spalten auf 360 Pixeln: Mit zehn Pixeln Rand je Zelle stand die
   Differenz-Spalte hinter dem rechten Rand und liess sich nur durch
   seitliches Rollen erreichen. */
@media (max-width: 640px) {
  th, td { padding: 10px 6px; }
  th:first-child, td:first-child { padding-left: 8px; }
  th:last-child, td:last-child { padding-right: 8px; }
  td.pts { font-size: 1rem; }
}
th:nth-child(2), td:nth-child(2) { text-align: left; white-space: normal; width: 99%; }
thead th {
  position: sticky; top: 0;
  font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dim); background: var(--surface-2);
}
tbody tr { border-top: 1px solid var(--border-soft); }
tbody tr:nth-child(even) { background: rgba(255,255,255,.015); }
td.team { font-weight: 600; }
td.pts { font-weight: 800; font-size: 1.05rem; }
/* Buchholz-Spalten (Schweizer System): sekundär, gedämpft. */
td.bh { color: var(--muted); font-variant-numeric: tabular-nums; }

/* ── Siegerehrung: Siegertreppchen ─────────────────────────────────────── */
.podium {
  display: flex; align-items: flex-end; justify-content: center;
  gap: 10px; padding: 6px 0 0;
}
.podcol {
  flex: 1 1 0; min-width: 0; max-width: 150px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.podtrophy { font-size: 1.5rem; line-height: 1; }
.pod1 .podtrophy { font-size: 2.1rem; }
.podname {
  font-weight: 800; color: var(--text); margin: 4px 0 2px; overflow-wrap: anywhere;
}
.podpts { font-size: .78rem; color: var(--muted); margin-bottom: 6px; }
/* Steht die eigene Mannschaft auf dem Podest, traegt ihr Name die
   Akzentfarbe — das Gold des ersten Platzes bleibt dem ersten Platz. */
.podcol.me .podname { color: var(--accent); }
.podblock {
  width: 100%; border-radius: 8px 8px 0 0; display: grid; place-items: center;
}
.pod1 .podblock { height: 120px; background: linear-gradient(180deg, #ffdd73, #d9a441); }
.pod2 .podblock { height: 90px;  background: linear-gradient(180deg, #e6edf5, #a9b4c4); }
.pod3 .podblock { height: 70px;  background: linear-gradient(180deg, #e6a76f, #b06f3a); }
.podrank { font-size: 1.7rem; font-weight: 900; color: #06283d; }
td.pos { color: var(--win); }
td.neg { color: var(--err); }

/* Die Ueberschrift ueber den Ersatzspielerfeldern im Anmeldeformular: Sie
   setzt den Block von der Aufstellung ab, ohne einen zweiten Kasten zu
   oeffnen — es sind ja dieselben Leute, nur eine andere Rolle. */
.subs-head {
  margin: 14px 0 4px;
  font-size: .85rem;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
  color: var(--muted);
}

/* ── Den Weg zum Verein finden ──────────────────────────────────────────
   Die Startseite ohne Vereinslink war eine Sackgasse. Suchfeld, Treffer und
   der Umkreisknopf teilen sich ein Aussehen: eine Zeile je Treffer, links das
   Zeichen, rechts der Name — auf dem Handy mit dem Daumen zu treffen. */
.finde { margin: 22px 0 6px; }
.finde-h { font-size: 1rem; font-weight: 700; margin: 0 0 8px; }
.finde-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.finde-input:focus { outline: none; border-color: var(--border-hover); }
.finde-out { margin-top: 10px; }
.finde-list { display: flex; flex-direction: column; gap: 6px; }
.finde-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  text-decoration: none;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
}
.finde-item:hover { border-color: var(--border-hover); }
.finde-logo {
  width: 36px; height: 36px;
  flex: 0 0 36px;
  border-radius: 8px;
  object-fit: cover;
}
.finde-logo-leer {
  display: grid;
  place-items: center;
  background: var(--surface-2);
  color: var(--dim);
}
.finde-name { display: flex; flex-direction: column; min-width: 0; }
.finde-sub { font-size: .82rem; color: var(--muted); }
/* Die Entfernung steht vorn und in gleicher Breite — so lesen sich die
   Zeilen als Rangfolge, nicht als Aufzaehlung. */
.finde-km {
  flex: 0 0 62px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--accent);
}
.finde-near {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  padding: 9px 14px;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
}
.finde-near:hover { border-color: var(--border-hover); }

/* ── Auszaehlung laeuft: die Ansage zwischen letztem Wurf und Ehrung ───── */
.counting .panel-body, .bcounting { text-align: center; padding: 26px 16px; }
.counting-icon { font-size: 2.4rem; line-height: 1; margin-bottom: 8px; }
.counting h2, .bcounting h2 { margin: 0 0 6px; font-size: 1.3rem; }
.counting p, .bcounting p { margin: 0; color: var(--muted); }
.bcounting { padding: 40px 16px; }
.bcounting h2 { font-size: 2rem; }
.bcounting p { font-size: 1.2rem; }

/* Podest */
.rank {
  display: inline-grid; place-items: center;
  width: 24px; height: 24px; border-radius: 50%;
  font-size: .78rem; font-weight: 800; color: var(--dim);
}
tr.p1 .rank { background: var(--gold); color: #14213a; }
tr.p2 .rank { background: var(--silver); color: #14213a; }
tr.p3 .rank { background: var(--bronze); color: #fff; }
tr.p1 td.team { color: var(--gold); }

/* ── Die eigene Mannschaft ────────────────────────────────────────────────
   Wer seine Mannschaft gewaehlt hat („Meine Mannschaft waehlen"), findet sie
   in jeder Ansicht wieder: in der Rangliste, in der Paarungsliste und auf
   dem Podest. Bei dreissig Zeilen ist das sonst jedes Mal dieselbe Suche —
   meist im Gehen, meist mit einer Hand.

   Markiert wird mit einem Balken am linken Rand und einem Hauch der
   Akzentfarbe, NICHT mit einer kraeftigen Fuellung: Die Zeile soll auffallen,
   ohne die Rangfarben (Gold/Silber/Bronze) und das Aufleuchten einer
   Ergebnisaenderung zu ueberdecken. */
tbody tr.me {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}
tbody tr.me td.team { font-weight: 700; }
/* Auch in der geraden Zeile bleibt die Marke sichtbar — der Zebrastreifen
   liegt sonst darueber. */
tbody tr.me:nth-child(even) {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* ── Paarungen ────────────────────────────────────────────────────────── */
.matches { list-style: none; margin: 0; padding: 0; }
/* Ueberschrift ueber den Partien eines Teilturniers (A-/B-Turnier). Steht
   ausserhalb der Liste, damit sie im zweispaltigen Raster nicht in einer
   Spalte landet. */
.mgroup {
  padding: 10px 16px 4px; font-weight: 700; font-size: 13px;
  letter-spacing: .3px; color: var(--accent);
  border-top: 1px solid var(--border-soft);
}
.mgroup:first-of-type { border-top: 0; }
.match { padding: 12px 16px; border-top: 1px solid var(--border-soft); }
.match:first-child { border-top: 0; }
/* Die eigene Partie in der Rundenliste: derselbe Balken wie in der
   Rangliste, dazu der eigene Name in der Akzentfarbe. Sie steht zwar auch
   oben im Kasten „Meine Partie" — wer aber die ganze Runde durchsieht, will
   sie an ihrem Platz wiederfinden. */
.match.me {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}
.matchline .ml-team.me { color: var(--accent); font-weight: 800; }
/* Und dieselbe Marke in „Wo muss ich hin?" — die Liste, die man im Gehen
   liest. */
.lanerow.me {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}
.lanename.me { color: var(--accent); font-weight: 800; }
/* Ab genügend Breite zweispaltig: spart Scrollen bei vielen Partien. Die
   zweite Karte (rechts in der ersten Zeile) bekommt oben keine Trennlinie,
   die linke Spalte eine feine senkrechte Trennung. */
@media (min-width: 700px) {
  .matches { display: grid; grid-template-columns: 1fr 1fr; column-gap: 0; }
  .match:nth-child(2) { border-top: 0; }
  .match:nth-child(odd) {
    border-right: 1px solid var(--border-soft); padding-right: 24px;
  }
  .match:nth-child(even) { padding-left: 24px; }
  /* Ungerade Gesamtzahl: die letzte (allein linke) Karte ohne Trennstrich. */
  .match:nth-child(odd):last-child { border-right: 0; }
}
/* Einzeilige Paarung: Team A — Stand — Team B, Sieger hervorgehoben. */
.matchline { display: flex; align-items: center; gap: 10px; }
.matchline .ml-team {
  flex: 1; min-width: 0; overflow-wrap: anywhere; hyphens: auto;
  color: var(--muted); font-weight: 600;
}
/* Auf dem Handy teilen sich zwei Mannschaftsnamen gut 120 Pixel je Seite;
   „Meerjungfrauen" brach dann als „Meerjungfraue-n". Weniger Rand, und der
   Browser trennt nach Sprache (hyphens) statt an beliebiger Stelle. */
@media (max-width: 640px) {
  .match { padding: 10px 12px; }
  .matchline { gap: 8px; }
}
.matchline .ml-a { text-align: right; }
.matchline .ml-b { text-align: left; }
.matchline .ml-team.win { color: var(--text); font-weight: 800; }
/* Score-Pillen: Verlierer grau, Sieger grün, Pokal daneben. */
.matchline .ml-scores {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap;
}
.matchline .ml-pill {
  min-width: 30px; text-align: center; padding: 3px 9px; border-radius: 8px;
  font-weight: 800; font-variant-numeric: tabular-nums;
  background: var(--surface-2); color: var(--muted);
}
.matchline .ml-pill.win { background: var(--win); color: #062a1c; }
.matchline .ml-trophy { font-size: .95em; line-height: 1; }
.matchline .ml-open {
  flex: 0 0 auto; min-width: 30px; text-align: center;
  color: var(--muted); font-weight: 800;
}
/* Fußzeile einer Partie: Bahn und „Ergebnis melden" teilen sich eine Zeile,
   mittig — so steht der Knopf nicht mehr allein in einer eigenen Zeile. */
.matchfoot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 8px 16px; margin-top: 6px;
}
/* Bahn-Kennzeichen unter einer Partie. */
.matchlane {
  display: inline-block; font-size: .74rem; font-weight: 600;
  color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--border-soft); border-radius: 999px; padding: 2px 8px;
}
.matchlane::before { content: "▸ "; }
/* „Ergebnis melden"-Link — inline in der Fußzeile. */
.reportlink {
  font-size: .82rem; font-weight: 600;
  color: var(--accent); text-decoration: none;
}
.reportlink::before { content: "✎ "; }
.reportlink:hover { text-decoration: underline; }
/* Offene Ergebnismeldungen unter einer Partie. */
.matchreports {
  margin-top: 8px; padding: 8px 10px;
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-left: 3px solid var(--gold); border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.mrhead {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--gold); margin-bottom: 4px;
}
.matchreport {
  display: flex; align-items: baseline; gap: 8px; padding: 1px 0;
}
.mrscore { font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.mrby { font-size: .78rem; color: var(--muted); }
.mrtime {
  margin-left: auto; font-size: .74rem; color: var(--dim);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mrtime::before { content: "🕒 "; }
.mrnote { margin-top: 4px; font-size: .76rem; color: var(--muted); font-style: italic; }
/* Widerspruch: die beiden Teams haben abweichende Ergebnisse gemeldet. */
.matchreports.conflict { border-left-color: var(--err); background: rgba(220,80,60,.08); }
.mrconflict { margin-top: 4px; font-size: .78rem; font-weight: 700; color: var(--err); }
/* Punkteraster der Ergebnismeldung (wie die Eingabehilfe in der App). */
.scoregrid { margin-bottom: 16px; }
.scoregrid-label { font-weight: 700; margin-bottom: 8px; color: var(--text); }
.scorebtns {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
}
.scorebtn {
  padding: 12px 0; border: 1px solid var(--border-soft);
  border-radius: var(--r-sm); background: var(--surface-2); color: var(--text);
  font-size: 1.05rem; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.scorebtn:hover { border-color: var(--accent); }
.scorebtn.on {
  background: var(--win); color: #062a1c; border-color: var(--win);
  font-weight: 800;
}
/* Zusammenfassung nach dem Absenden einer Ergebnismeldung. */
.repsum {
  margin: 12px 0; padding: 14px 16px;
  border: 1px solid var(--border-soft); border-radius: var(--r-sm);
  background: var(--surface-2);
}
.repsum-title {
  font-weight: 700; color: var(--text); margin-bottom: 8px;
  font-size: .8rem; text-transform: uppercase; letter-spacing: .06em;
}
.repsum-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 5px 0; color: var(--muted);
}
.repsum-row span { min-width: 0; overflow-wrap: anywhere; }
.repsum-row strong {
  min-width: 34px; text-align: center; font-size: 1.15rem; color: var(--text);
}
.repsum-row.win { color: var(--text); }
.repsum-row.win strong { color: var(--win); }
.repsum-meta {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border-soft); color: var(--muted);
  font-size: .9rem;
}
.repsum-note { margin-top: 6px; color: var(--muted); font-style: italic; }
.side { display: flex; align-items: center; gap: 12px; padding: 3px 0; color: var(--muted); }
.side .nm { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.side .sc {
  min-width: 34px; text-align: center; font-weight: 800;
  padding: 2px 8px; border-radius: 8px;
  background: rgba(255,255,255,.05); color: var(--muted);
}
/* K.-o.-Paarung: Hin- und Rückspiel nebeneinander. Auf schmalen Displays
   untereinander — zwei Spalten mit Name und Punktestand wären dort unlesbar. */
.tie { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 560px) {
  .tie { grid-template-columns: 1fr 1fr; column-gap: 36px; }
}
.leg-label {
  display: block; margin-bottom: 4px;
  font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--dim);
}
.leg-open { padding: 3px 0; color: var(--dim); font-size: .9rem; }

.side.win { color: var(--text); }
.side.win .nm { font-weight: 700; }
.side.win .sc { background: rgba(52,211,153,.16); color: var(--win); }

/* Zeitraum je Phase im Panel-/Spaltentitel (aus tournament_phase_dates). Nicht
   in Versalien wie der Titel, sondern gedämpft und normal geschrieben. */
.phase-date {
  margin-left: 10px; font-size: .72rem; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--dim); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Vereinsmeisterschaft: grafischer Turnierbaum ──────────────────────── */
/* K.-o.-Phasen als Spalten (Achtelfinale links → Finale rechts); SVG-Linien
   verbinden jede Paarung mit dem Folgespiel. Auf schmalen Displays scrollt der
   Baum waagerecht. */
.bkt-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 8px; }
.bkt {
  position: relative; display: flex; gap: 40px; align-items: stretch;
  min-width: min-content; padding: 4px 2px;
}
.bkt-lines { position: absolute; top: 0; left: 0; z-index: 0; pointer-events: none; }
.bkt-lines path { fill: none; stroke: var(--border); stroke-width: 2; }
.bkt-round { display: flex; flex-direction: column; min-width: 200px; }
.bkt-round-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-bottom: 8px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border-soft);
}
.bkt-round-head > span:first-child {
  font-size: .72rem; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--gold);
}
.bkt-round-head .phase-date { margin-left: 0; }
/* space-around zentriert jedes Folgespiel zwischen seinen beiden Zubringern,
   sodass die Verbindungslinien sauber zusammenlaufen. */
.bkt-col {
  position: relative; z-index: 1; flex: 1;
  display: flex; flex-direction: column; justify-content: space-around; gap: 12px;
}
.bkt-tie {
  background: var(--bg-2); border: 1px solid var(--border-soft);
  border-radius: 10px; overflow: hidden;
}
.bkt-slot { display: flex; align-items: center; gap: 8px; padding: 7px 10px; }
.bkt-slot + .bkt-slot { border-top: 1px solid var(--border-soft); }
.bkt-nm {
  flex: 1; min-width: 0; overflow-wrap: anywhere;
  color: var(--muted); font-size: .92rem;
}
.bkt-pt { font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }
.bkt-slot.win .bkt-nm { color: var(--text); font-weight: 700; }
.bkt-slot.win .bkt-pt { color: var(--win); }
/* Turniersieger: goldener Akzent im Finale. */
.bkt-tie:has(.bkt-slot.champ) { border-color: var(--gold); }
.bkt-slot.champ { background: rgba(245,183,57,.12); }
.bkt-slot.champ .bkt-nm { color: var(--gold); font-weight: 800; }
/* Seitwärts-Scroll-Hinweis über dem Baum. */
.bkt-hint {
  margin: 0 0 8px; font-size: .82rem; color: var(--dim);
  display: flex; align-items: center; gap: 6px;
}
.bkt-hint[hidden] { display: none; }
.bkt-third { padding: 8px 0 0; max-width: 260px; }
.bkt-third .bkt-tie { margin-top: 4px; }

/* Gesamt-Rangliste der Vereinsmeisterschaft: Podestfarben für die Top 3.
   Eigene Klasse `rank-table` (NICHT `.rank` — das ist die 24×24-Badge der
   Rangnummer; als Tabellenklasse würde sie die Tabelle auf 24 px stauchen). */
table.rank-table tr.p1 td { color: var(--gold); }
table.rank-table tr.p2 td { color: #cfd8e3; }
table.rank-table tr.p3 td { color: #e0a97a; }
table.rank-table td.bname { font-weight: 700; }

/* ── Pyramide ─────────────────────────────────────────────────────────── */
/* Reihe 1 oben mit einem Platz, jede weitere eine breiter. Die Reihen sind
   zentriert, damit die Dreiecksform auch dann erkennbar bleibt, wenn eine
   Reihe wegen langer Namen umbricht. */
.pyr { display: flex; flex-direction: column; gap: 8px; }
.pyr-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.pyr-cell {
  flex: 0 1 auto; min-width: 84px; max-width: 200px;
  padding: 8px 12px;
  text-align: center; font-size: .88rem; font-weight: 600;
  color: var(--text); background: var(--bg-2);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  overflow-wrap: anywhere;
}
/* Die Spitze ist der Sinn der ganzen Pyramide — die darf man sehen. */
.pyr-row.top .pyr-cell {
  color: var(--gold); border-color: rgba(245,183,57,.55);
  background: rgba(245,183,57,.10);
}
/* Freie Plätze bleiben sichtbar: eine Lücke ist eine Aussage (dort kann
   jemand aufsteigen), kein fehlender Eintrag. */
.pyr-cell.empty {
  color: var(--dim); font-weight: 400; font-style: italic;
  background: none; border-style: dashed;
}

/* Infoknopf hinter einem Wert (z. B. Spielmodus) und der Absatz, den er
   aufklappt. Der Knopf ist bewusst klein und rund — er soll den Wert
   begleiten, nicht mit ihm konkurrieren. */
.infobtn {
  display: inline-grid; place-items: center;
  width: 21px; height: 21px; margin-left: 8px; padding: 0;
  font: inherit; font-size: .76rem; font-weight: 800; line-height: 1;
  color: var(--gold); background: rgba(245,183,57,.14);
  border: 1px solid rgba(245,183,57,.55); border-radius: 50%;
  cursor: pointer; vertical-align: middle;
  transition: border-color .16s ease, color .16s ease, background .16s ease;
}
.infobtn:hover { border-color: var(--gold); background: rgba(245,183,57,.26); }
.infobtn.on {
  color: #10233c; background: var(--gold); border-color: var(--gold);
}
.rowhelp {
  margin-top: 8px; padding: 10px 12px;
  font-size: .86rem; line-height: 1.45; color: var(--muted);
  background: var(--bg-2);
  border-left: 3px solid var(--gold); border-radius: 0 var(--r-sm) var(--r-sm) 0;
}

/* ── Beschreibungsliste ───────────────────────────────────────────────── */
.rows { margin: 0; }
.row { display: flex; justify-content: space-between; gap: 16px; padding: 11px 0; border-top: 1px solid var(--border-soft); }
.row:first-child { border-top: 0; }
.row dt { color: var(--muted); flex: none; }
.row dd { margin: 0; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
/* Kontaktzeilen des Veranstalters (Telefon/E-Mail) unter dem Vereinsnamen. */
.orgcontact { margin-top: 4px; font-size: .88rem; font-weight: 500; }
.orgcontact a { color: var(--gold); text-decoration: none; }
.orgcontact a:hover { text-decoration: underline; }

/* ── Aktionen ─────────────────────────────────────────────────────────── */
.cta {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; margin-top: 18px; padding: 15px;
  font: inherit; font-weight: 800; letter-spacing: .03em;
  color: #10233c; background: linear-gradient(180deg, #ffc95a, var(--gold));
  border: 0; border-radius: var(--r-md); cursor: pointer;
  box-shadow: 0 6px 18px -8px rgba(245,183,57,.7);
  transition: filter .16s ease, transform .16s ease;
}
.cta:hover { filter: brightness(1.06); }
.cta:active { transform: scale(.99); }
.cta:disabled { opacity: .5; box-shadow: none; cursor: default; }

.ghost {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: 10px; padding: 13px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--muted); font-weight: 600;
  transition: border-color .16s ease, color .16s ease;
}
.ghost:hover { border-color: var(--border-hover); color: var(--text); }

.back {
  display: inline-flex; align-items: center; gap: 8px;
  margin-bottom: 16px; padding: 8px 12px 8px 0;
  color: var(--muted); font-size: 1.05rem; font-weight: 600;
}
.back:hover { color: var(--text); }

/* ── Formular ─────────────────────────────────────────────────────────── */
.field { margin-bottom: 14px; }
label { display: block; margin-bottom: 6px; font-weight: 600; font-size: .88rem; color: var(--muted); }
input, textarea {
  width: 100%; padding: 13px 14px;
  font: inherit; color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--border); border-radius: var(--r-md);
  transition: border-color .16s ease, box-shadow .16s ease;
}
input::placeholder, textarea::placeholder { color: var(--dim); }
/* Read-only-Felder (Anmelder im Team-Abschnitt): sichtbar, aber klar als
   nicht editierbar erkennbar. */
input[readonly] { color: var(--muted); background: rgba(255,255,255,.03); cursor: default; }
input[readonly]:focus { border-color: var(--border); box-shadow: none; }
input:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(59,142,240,.22);
}
textarea { resize: vertical; }
/* Vor-/Nachname nebeneinander; unter 380px untereinander, sonst wird jedes
   Feld zu schmal fuer einen Namen. */
.name2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
/* Geschlechts-Auswahl als zwei Chips (nur zur Zielgruppen-Warnung). */
.gender { display: flex; gap: 8px; }
.gchip { position: relative; flex: 1; cursor: pointer; }
.gchip input { position: absolute; opacity: 0; pointer-events: none; }
.gchip span {
  display: block; text-align: center; padding: 9px 8px;
  font-weight: 600; color: var(--muted);
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: var(--r-md); transition: border-color .16s ease, color .16s ease;
}
.gchip input:checked + span {
  color: var(--text); border-color: var(--gold);
  background: rgba(245,183,57,.12);
}
.gchip input:focus-visible + span { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Bereits meldendes Team: nicht mehr wählbar. */
.gchip.off { cursor: not-allowed; }
.gchip.off span { opacity: .5; }
.chiptag { font-style: normal; font-weight: 600; font-size: .78em; color: var(--muted); }
@media (max-width: 380px) { .name2 { grid-template-columns: 1fr; } }
.req { color: var(--gold); }

/* „Anmeldung stornieren" — als Knopf, aber bewusst zurückhaltend: der
   Hauptweg auf dieser Seite ist Ändern, nicht Abbrechen. */
button.ghost {
  width: 100%; font: inherit; font-weight: 600;
  background: none; cursor: pointer;
}
button.ghost.danger { color: var(--err); }
button.ghost.danger:hover { border-color: var(--err); color: var(--err); }

/* Anmeldenummer — wird am Turniertag vorgelesen und abgetippt, also gross,
   mit Ziffernabstand und ohne Verwechslungsgefahr. */
.regcode {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 18px 16px; margin: 16px 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.regcode strong {
  font-size: 1.9rem; font-weight: 800; letter-spacing: .14em;
  font-variant-numeric: tabular-nums; color: var(--gold);
}

/* Honeypot: für Menschen unsichtbar, Bots füllen ihn aus. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ── Hinweise ─────────────────────────────────────────────────────────── */
.note {
  display: flex; gap: 12px;
  padding: 14px 16px; margin: 16px 0;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--gold); border-radius: 0 var(--r-md) var(--r-md) 0;
}
.note.error { border-left-color: var(--err); }
.note.ok { border-left-color: var(--win); }
.note.warn { border-left-color: var(--gold); }
/* Der Wachhund: die Turnier-App meldet sich nicht mehr. Kraeftiger als ein
   gewoehnlicher Hinweis, denn er sagt, dass alles darunter alt sein kann. */
.note.appoffline { background: color-mix(in srgb, var(--gold) 14%, var(--surface)); }
.note.drawing { border-left-color: var(--accent); }
.note strong { display: block; margin-bottom: 2px; }

.empty { text-align: center; padding: 40px 16px; color: var(--muted); }
.empty svg { opacity: .35; margin-bottom: 12px; }

/* ── Ladeskelett ──────────────────────────────────────────────────────── */
.sk { border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--border); margin-bottom: 12px; height: 92px; position: relative; overflow: hidden; }
.sk::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.05), transparent);
  animation: shimmer 1.3s infinite;
}
@keyframes shimmer { 100% { transform: translateX(100%); } }
.sk::after { transform: translateX(-100%); }

/* ── Fuß ──────────────────────────────────────────────────────────────── */
.foot {
  padding: 28px 16px calc(32px + env(safe-area-inset-bottom, 0px));
  text-align: center; color: var(--dim); font-size: .84rem;
  border-top: 1px solid var(--border-soft);
}
.foot a { color: var(--muted); font-weight: 600; }
/* Rechtslinks: eine Zeile darunter, durch einen Mittelpunkt getrennt. */
.foot-legal { margin-top: 8px; display: flex; gap: 16px; justify-content: center; }
.foot-legal a { position: relative; }
.foot-legal a + a::before {
  content: "·"; position: absolute; left: -10px; color: var(--dim);
}
.foot-legal a:hover { color: var(--gold); }

@media (min-width: 640px) {
  /* Auf breiten Schirmen noch eine Spur groesser — dort steht der Bildschirm
     meist weiter weg. */
  html { font-size: calc(19px * var(--fs, 1)); }
  .wrap { padding: 32px 24px 64px; }
}

/* ── Hilfe ────────────────────────────────────────────────────────────── */
.help { list-style: none; margin: 0; padding: 0; }
.help li { padding: 12px 0; border-top: 1px solid var(--border-soft); }
.help li:first-child { border-top: 0; padding-top: 0; }
.help b { display: block; margin-bottom: 2px; }
.help span { color: var(--muted); font-size: .92rem; }

/* ── Werbung ──────────────────────────────────────────────────────────── */
/* Werbung: deutlich zurueckhaltender als der Inhalt darueber. Kein Gold,
   kein Farbverlauf — die Seite gehoert dem Zuschauer. Der grosse Abstand
   nach oben setzt sie sichtbar vom Turnierinhalt ab. */
.promo {
  position: relative; overflow: hidden;
  margin-top: 56px; padding: 20px 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg-2);
}
/* Der Absender darf Farbe tragen: das Panel bleibt zurueckhaltend, aber woher
   die Werbung kommt, soll man auf einen Blick sehen. */
.promo-tag {
  display: inline-block; margin-bottom: 10px;
  padding: 3px 10px; border-radius: 999px;
  color: #10233c; background: linear-gradient(180deg, #ffc95a, var(--gold));
  border: 1px solid var(--gold);
  font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
}
.promo h3 { font-size: 1.15rem; margin-bottom: 8px; }
.promo p { margin: 0; color: var(--muted); font-size: .93rem; }
.promo ul { margin: 12px 0 0; padding-left: 18px; color: var(--muted); font-size: .9rem; }
.promo ul li { margin: 4px 0; }
/* Der Knopf in der Werbung ist bewusst kein goldener Hauptknopf — der ist
   fuer „Jetzt anmelden" reserviert. */
.promo .cta {
  margin-top: 16px;
  color: var(--text); background: var(--surface-2);
  border: 1px solid var(--border); box-shadow: none;
}
.promo .cta:hover { border-color: var(--border-hover); filter: none; background: var(--surface); }

/* Externe Links (Karte, Vereinswebseite) */
.maplink { color: var(--muted); text-decoration: none; border-bottom: 1px dotted rgba(143,164,189,.5); }
.maplink:hover { color: var(--gold); border-bottom-color: var(--gold); }
/* Geländekarte-Knopf in der Metazeile — klar als Button erkennbar. */
.mapchip {
  cursor: pointer; font: inherit; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 3px 12px;
}
.mapchip svg { opacity: .9; }
.mapchip:hover { color: var(--gold); border-color: var(--gold); }
dd .maplink { color: var(--gold); border-bottom-color: rgba(245,183,57,.5); font-weight: 600; }

/* Runden-Reiter */
.tabs {
  display: flex; gap: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: 12px 16px; border-bottom: 1px solid var(--border-soft);
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: none; padding: 7px 14px;
  font: inherit; font-size: .84rem; font-weight: 700; white-space: nowrap;
  color: var(--muted); background: var(--bg-2);
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  transition: color .16s ease, border-color .16s ease, background .16s ease;
}
.tab:hover { color: var(--text); border-color: var(--border-hover); }
.tab.on {
  color: #14213a; background: var(--gold); border-color: var(--gold);
}

/* ── Suche in der Übersicht ───────────────────────────────────────────── */
.search { margin-bottom: 18px; }
.search input {
  width: 100%; padding: 13px 14px;
  font: inherit; color: var(--text);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.search input::placeholder { color: var(--dim); }
.search input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(59,142,240,.22);
}
.search input::-webkit-search-cancel-button { filter: invert(.6); cursor: pointer; }

/* Knopf „ältere Turniere anzeigen" */
button.more {
  width: 100%; margin-top: 6px;
  font: inherit; font-weight: 600;
  background: transparent; cursor: pointer;
}


/* ── Anzeigetafel (#/tafel/<id>) ───────────────────────────────────────── */
/* Vollbild für Beamer und Fernseher: Kopfleiste und Fußzeile verschwinden,
   die Schrift skaliert mit der Fensterbreite (vw), damit dieselbe Seite auf
   einem 24-Zoll-Monitor und auf einer Leinwand lesbar bleibt. */
body.board .top,
body.board .foot,
body.board .promo { display: none; }
body.board { overflow: hidden; }
body.board .wrap {
  max-width: none; height: 100dvh; padding: 2vh 3vw;
  display: flex; flex-direction: column;
}

.bhead {
  display: flex; align-items: baseline; gap: 2vw;
  padding-bottom: 1.4vh; margin-bottom: 1.8vh;
  border-bottom: 2px solid var(--border);
}
.bhead h1 { font-size: clamp(1.4rem, 3.4vw, 3.4rem); margin: 0; }
.bmeta { color: var(--muted); font-size: clamp(.8rem, 1.3vw, 1.4rem); }
.bclock {
  margin-left: auto; color: var(--gold); font-weight: 800;
  font-size: clamp(1rem, 2vw, 2.2rem); font-variant-numeric: tabular-nums;
}

.bbody { flex: 1; min-height: 0; overflow: hidden; }
.btitle {
  font-size: clamp(.9rem, 1.6vw, 1.7rem); font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: var(--gold);
  margin: 0 0 1.2vh;
}

.btable { width: 100%; border-collapse: collapse; font-size: clamp(.9rem, 2.1vw, 2.1rem); }
.btable th {
  text-align: left; padding: .5vh 1vw;
  font-size: .5em; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dim); border-bottom: 1px solid var(--border);
}
.btable td { padding: .8vh 1vw; border-bottom: 1px solid var(--border-soft); }
.btable .bname { font-weight: 700; }
.btable tr.p1 td { color: var(--gold); }
.btable tr.p2 td { color: var(--silver); }
.btable tr.p3 td { color: var(--bronze); }

.bmatches { display: grid; gap: 1vh; }
.bmatch {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 1.5vw; padding: 1vh 1.5vw;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: clamp(.85rem, 1.9vw, 1.9rem);
}
.bside { color: var(--muted); overflow-wrap: anywhere; }
.bside.right { text-align: right; }
.bside.win { color: var(--text); font-weight: 800; }
.bscore {
  font-weight: 800; color: var(--gold);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Seitenanzeige beim Umblättern — klein, aber sie erklärt, warum sich das
   Bild gleich ändert. */
.bdots { display: flex; justify-content: center; gap: 8px; padding-top: 1.4vh; }
.bdot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border);
}
.bdot.on { background: var(--gold); }

body.board .pyr-cell { font-size: clamp(.75rem, 1.5vw, 1.5rem); min-width: 6vw; }

/* Ausstieg aus der Tafel: dezent, aber auffindbar. Auf der Leinwand faellt er
   nicht auf, am Tablet findet ihn der Finger. */
.bexit {
  position: fixed; top: 1vh; right: 1vw; z-index: 30;
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  font-size: 1.6rem; line-height: 1; color: var(--dim);
  background: rgba(10,20,34,.5); border: 1px solid var(--border);
  opacity: .25; transition: opacity .16s ease, color .16s ease;
}
.bexit:hover, .bexit:focus { opacity: 1; color: var(--text); }

/* Vorlauf-Ansicht der Tafel (vor dem Start): grosse, ruhige Mitte mit dem
   Beginn, Belegung und Anmeldeknopf. */
.bpre {
  height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2vh; text-align: center;
}
.bpre .badge { margin: 0; font-size: clamp(.8rem, 1.4vw, 1.4rem); }
.bpre-label {
  font-size: clamp(.9rem, 1.6vw, 1.6rem); letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim);
}
.bpre-when {
  font-size: clamp(1.8rem, 5vw, 5rem); font-weight: 800; line-height: 1.1;
  color: var(--gold);
}
.bpre-cap { font-size: clamp(1rem, 2.2vw, 2.2rem); color: var(--muted); }
.bpre-cta {
  width: auto; margin-top: 1vh; padding: 1.4vh 4vw;
  font-size: clamp(1rem, 2vw, 2rem);
}


/* Tastaturfokus sichtbar machen (nur bei Tab-Navigation, nicht beim Klick). */
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, .tcard:focus-visible {
  outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--r-sm);
}
.tcard:focus-visible { outline-offset: 0; border-radius: var(--r-lg); }


/* ── Auflockernde Effekte ─────────────────────────────────────────────── */
/* 1) Belegung als duenner Fuellbalken unter der Turnierkarte. Faehrt sich beim
      Erscheinen auf den Fuellstand auf. */
.capbar {
  height: 5px; margin-top: 6px; border-radius: 3px;
  background: var(--bg-2); overflow: hidden;
}
.capbar > span {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--win), #7ee0b4);
  border-radius: 3px;
  animation: capfill .6s ease-out .1s both;
}
.capbar.full > span { background: linear-gradient(90deg, var(--err), #ff9d9d); }
@keyframes capfill { from { transform: scaleX(0); transform-origin: left; } }

/* 4) Karten laufen beim ersten Aufbau gestaffelt ein. */
.tcard-wrap.stagger { animation: cardin .28s ease-out both; }
@keyframes cardin { from { opacity: 0; transform: translateY(8px); } }

/* 2) Frisch aktualisierte Rangzeile leuchtet einmal gold auf. */
tr.flash { animation: rowflash 1.4s ease-out; }
@keyframes rowflash {
  0%   { background: rgba(245,183,57,.32); }
  100% { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .capbar > span, .tcard-wrap.stagger, tr.flash { animation: none; }
  .capbar > span { width: auto; }
}

/* ── Druckansicht ──────────────────────────────────────────────────────── */
/* Für Ausdruck/PDF: weiße Fläche, dunkler Text, ohne Chrome. Am elegantesten
   über die CSS-Variablen — so werden alle var(--…)-Verweise druckfreundlich. */
@media print {
  :root {
    --bg: #fff; --bg-2: #fff; --surface: #fff; --surface-2: #fff;
    --text: #111; --muted: #333; --dim: #555; --gold: #9a6600;
    --border: #bbb; --border-soft: #ddd; --win: #060; --err: #900;
    --shadow: none;
  }
  body { background: #fff; min-height: 0; }
  .top, .foot, .promo, .langsel, #helpLink, #themeToggle, #liveDot,
  .phead-actions,
  .search, .ghost, .reg-link, .tabs, .toast, .panel-chevron,
  .print-hide { display: none !important; }
  * { box-shadow: none !important; }
  .wrap { max-width: none; padding: 0; }
  .bkt-wrap, .table-scroll { overflow: visible !important; }
  .panel, .bkt-tie, .match, tr { break-inside: avoid; }
  /* Die Ueberschrift eines Teilturniers darf nicht allein am Seitenfuss
     stehenbleiben — sie gehoert zu der Liste, die auf sie folgt. */
  .mgroup { break-inside: avoid; break-after: avoid; }
}

/* Förderer-Plakette hinter dem Vereinsnamen.
   Klein und ohne Bewegung: Sie steht in einer Datenzeile, nicht auf einer
   Bühne — sie soll auffallen, wenn man hinsieht, und sonst nicht stören. */
.sponsor {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 20px;
  background: linear-gradient(135deg, #ffd24a, #f2a900 55%, #c97f00);
  color: #4a3000;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.6px;
  vertical-align: 2px;
  white-space: nowrap;
}

/* ── Turnierserie: die Gesamtwertung einer Saison ──────────────────────────
   Ein Aushang, kein Live-Stand: Er zeigt eine Momentaufnahme samt ihrem
   Zeitpunkt. Der steht deshalb oben und nicht im Kleingedruckten. */
.asof { margin: -6px 0 14px; }

.stab {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 18px;
  font-size: 14px;
}
.stab th, .stab td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--border-soft);
  text-align: left;
}
.stab th {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
  opacity: 0.75;
}
.stab .num { text-align: right; white-space: nowrap; }
.stab th.num { text-align: right; }

/* Die ersten drei in ihrer Medaillenfarbe — dieselbe wie in der App und auf
   dem gedruckten Aushang, damit man nicht dreimal lernt, was Gold bedeutet.
   Nur ein zarter Streifen links plus eine Tönung: Die Tabelle soll lesbar
   bleiben und nicht bunt werden. */
.stab tr.medal td { font-weight: 700; }
.stab tr.medal td:first-child { border-left: 3px solid transparent; }
.stab tr.m1 td { background: rgba(212, 175, 55, 0.14); }
.stab tr.m1 td:first-child { border-left-color: #d4af37; }
.stab tr.m2 td { background: rgba(160, 160, 160, 0.14); }
.stab tr.m2 td:first-child { border-left-color: #a0a0a0; }
.stab tr.m3 td { background: rgba(176, 118, 63, 0.14); }
.stab tr.m3 td:first-child { border-left-color: #b0763f; }

/* Turniere und Ehrungen der Serie: je Zeile ein Gegenstand und seine
   Beiwerte. Umbrechend, damit auf dem Smartphone nichts abgeschnitten wird. */
.slist { list-style: none; margin: 0 0 18px; padding: 0; }
.slist li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-soft);
}
.slist .sname { font-weight: 600; }
.slist .swin { margin-left: auto; }

/* „Läuft" statt eines Siegers in der Turnierliste einer Serie: die Auskunft,
   wegen der jemand die Seite gerade öffnet. */
.slist .live-now {
  color: var(--ok, #1f7a4d);
  font-weight: 700;
  letter-spacing: 0.3px;
}

/* ── Schriftgroesse verstellen ───────────────────────────────────────────
   Der Knopf zeigt die Stufe an („A", „A+", „A++"), damit man sieht, wo man
   steht — ein Symbol allein liesse offen, ob es groesser oder kleiner wird.
   Nach der groessten Stufe geht es zurueck auf die Ausgangsgroesse. */
.fsbtn {
  width: auto; min-width: 30px; padding: 0 8px;
  border-radius: 15px;
  font-variant-numeric: tabular-nums;
}
.fsbtn .fs-plus { font-size: .72em; vertical-align: super; letter-spacing: -.04em; }
.thbtn { font-size: 1.05rem; line-height: 1; }

/* ── Vor dem Start: Wetter, Brotzeit, Umgebung ─────────────────────────── */
.osmframe {
  width: 100%; height: 300px; border: 0; border-radius: 12px;
  background: var(--surface-2);
}
.wxtable { width: 100%; border-collapse: collapse; font-size: .92rem; }
.wxtable th, .wxtable td {
  padding: 5px 8px; text-align: right; border-bottom: 1px solid var(--border);
}
.wxtable th:first-child, .wxtable td:first-child { text-align: left; }
.wxtable .wet { color: #64b5f6; font-weight: 700; }
.wxtable .storm { color: var(--gold); font-weight: 700; }
.wxwarn {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 8px 8px 0; padding: 6px 12px; border-radius: 9px;
  font-size: .9rem; font-weight: 700; color: #fff;
}
.wxwarn.rain { background: #1976d2; }
.wxwarn.storm { background: #ef6c00; }
.wxwarn.thunder { background: #d32f2f; }
.bzrow {
  display: flex; align-items: baseline; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--border);
}
.bzrow .k { flex: none; }
.bzrow .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bzrow .d { flex: none; color: var(--muted); font-size: .88rem; }
.checkin-nums {
  display: flex; flex-wrap: wrap; gap: 18px; margin: 6px 0 2px;
}
.checkin-nums .num { text-align: center; }
.checkin-nums .num b { display: block; font-size: 1.9rem; line-height: 1.1; }
.checkin-nums .num span { color: var(--muted); font-size: .85rem; }

/* ── Vor-Start-Sektionen: auf dem Handy als Reiter ─────────────────────
   Auf einem breiten Schirm stehen Check-in, Wetter, Brotzeit und Karte
   bequem untereinander. Auf dem Handy ergaebe das eine Bildschirmmeter
   lange Rolle — Reiter zeigen eines nach dem anderen. */
.pretabs { display: none; }
@media (max-width: 700px) {
  .pretabs {
    display: flex; padding: 4px 0 10px; border-bottom: 0;
    position: sticky; top: 0; z-index: 5; background: var(--bg);
  }
  .presec { display: none; }
  .presec.on { display: block; }
}

/* Der Tagesverlauf in zwei Spalten, sobald die Kachel breit genug ist.
   Vierzehn Stundenzeilen untereinander sind auf einem breiten Schirm eine
   schmale, hohe Saeule mit viel Weissraum daneben — nebeneinander passt der
   ganze Tag ohne Rollen ins Bild. */
.wxcols { display: grid; grid-template-columns: 1fr; gap: 0 22px; }
@media (min-width: 760px) {
  .wxcols { grid-template-columns: 1fr 1fr; }
}
.wxcols .wxtable { align-self: start; }

/* ── „Wo muss ich hin?" — Bahn und Paarung, sonst nichts ──────────────────
 *
 * Die Liste wird im Gehen gelesen: ein Blick auf die Bahnnummer, ein Blick
 * auf den eigenen Namen. Deshalb steht die Nummer als kräftige Marke links
 * und nicht als Fußnote unter der Paarung — und deshalb steht hier weder ein
 * Punktestand noch ein Knopf.
 */
.lanelist { list-style: none; margin: 0; padding: 0; }
.lanerow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--line);
}
.lanerow:last-child { border-bottom: 0; }
.lanetag {
  flex: 0 0 auto;
  min-width: 3.2em;
  text-align: center;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent-soft, #e8f1ec);
  color: var(--accent, #1f5f3f);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.lanepair { flex: 1 1 auto; min-width: 0; }
.lanevs { margin: 0 8px; color: var(--fg-muted); }

/* Sanft hinspringen statt harter Sprung — man sieht dabei, wohin es geht. */
html { scroll-behavior: smooth; }
/* Etwas Luft über dem Ziel, sonst klebt die Überschrift am oberen Rand. */
#wohin { scroll-margin-top: 12px; }

/* ── „Meine Partie" ───────────────────────────────────────────────────────
   Der Kasten ganz oben, für den, der selbst spielt: Bahn und Gegner mit
   einem Blick, ohne die Paarungsliste nach dem eigenen Namen abzusuchen.
   Offen leuchtet er in der Akzentfarbe (das ist die Partie, die JETZT
   zählt), gespielt bleibt er ruhig. */
.mymatch {
  margin: 14px 0;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.mymatch.done { border-left-color: var(--border); }

/* ── Sponsorenleiste ──────────────────────────────────────────────────────
   Logos nebeneinander, auf dem Handy waagerecht rollbar. Der weisse Kasten
   ist die Vorgabe der Tafel (Logos auf Transparenz sehen sonst im dunklen
   Modus schwarz aus); „dark" und „bare" sind die beiden anderen Hintergruende,
   die der Verein je Sponsor waehlt. */
.sponsors {
  margin: 14px 0;
  padding: 10px 14px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.sponsors-head {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin-bottom: 8px;
}
.sponsors-row {
  display: flex; gap: 10px; align-items: center;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding-bottom: 2px;
}
.sponsors-row::-webkit-scrollbar { display: none; }
.sp {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  min-width: 64px; height: 56px; padding: 6px 10px;
  background: #fff; color: #1b2430;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  text-decoration: none;
  /* Bezugspunkt fuer den Spruch darunter. */
  position: relative;
}
.sp.dark { background: #1b2430; color: #fff; }
.sp.bare { background: transparent; border-color: transparent; color: inherit; }
.sp img { max-height: 44px; max-width: 140px; width: auto; height: auto; display: block; }
.sp-name { font-weight: 600; font-size: .9rem; white-space: nowrap; }
a.sp:hover, a.sp:focus-visible { border-color: var(--accent); }

/* ── Der Sponsor unter der Maus ───────────────────────────────────────────
 *
 * Der Verein verkauft diese Kacheln, und sie sind klein: 56 Punkte hoch, in
 * einer Reihe mit sechs anderen. Wer mit der Maus daraufgeht, bekommt beides,
 * wofuer bezahlt wurde — das Logo gross und den Satz dazu.
 *
 * Nur auf Geraeten mit echtem Zeiger: Auf dem Telefon gibt es kein
 * „Ueberfahren"; dort waere die Vergroesserung ein Zustand, aus dem man nicht
 * mehr herauskommt, und ein Tipp soll die Seite des Sponsors oeffnen.
 *
 * Die Reihe rollt sonst waagerecht (overflow-x). Ein gewachsenes Logo waere
 * darin oben und unten abgeschnitten — deshalb steht sie hier offen und
 * umbricht stattdessen. */
@media (hover: hover) and (pointer: fine) {
  .sponsors-row { overflow: visible; flex-wrap: wrap; }
  .sp {
    transition: transform .2s cubic-bezier(.2, .8, .3, 1.2),
                box-shadow .2s ease, border-color .2s ease;
    transform-origin: center center;
  }
  /* Fast doppelt so gross: Bei 1,35 blieb ein Logo von 44 Punkten unter
   * 60 — lesbar, aber nicht das, wofuer bezahlt wurde. Jetzt wird aus der
   * Kachel eine Karte, die ueber ihren Nachbarn liegt (z-index) und mit der
   * Reihe nach oben und unten hinausragen darf (overflow: visible oben). */
  .sp:hover, .sp:focus-visible {
    transform: scale(1.9);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .5);
    z-index: 5;
  }
  /* Der Spruch: unter der Kachel, ohne die Reihe zu verschieben (absolut),
   * und er blendet sich mit auf. */
  .sp-slogan {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    transform: translate(-50%, 4px);
    z-index: 6;
    max-width: 240px;
    width: max-content;
    padding: 6px 10px;
    border-radius: 8px;
    background: #111827;
    color: #fff;
    font-size: .62rem;
    line-height: 1.35;
    font-weight: 500;
    text-align: center;
    white-space: normal;
    opacity: 0;
    pointer-events: none;
    box-shadow: 0 8px 20px rgba(0, 0, 0, .4);
    transition: opacity .2s ease, transform .2s ease;
  }
  .sp:hover .sp-slogan, .sp:focus-visible .sp-slogan {
    opacity: 1;
    transform: translate(-50%, 0);
  }
  /* Wer die Bewegung nicht will, bekommt sie nicht — der Spruch bleibt. */
  @media (prefers-reduced-motion: reduce) {
    .sp, .sp-slogan { transition: none; }
    .sp:hover, .sp:focus-visible { transform: none; }
  }
}

/* Ohne Zeiger (Telefon, Tablet) bleibt der Spruch unsichtbar: Dort ist die
 * Kachel ein Knopf zur Seite des Sponsors, mehr nicht. */
@media not all and (hover: hover) {
  .sp-slogan { display: none; }
}
.mymatch.pick {
  border-left-color: var(--border);
  padding: 8px 14px;
  text-align: center;
}
.mmhead {
  display: flex; align-items: baseline; gap: 8px;
  font-size: .78rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted);
}
.mmround { margin-left: auto; text-transform: none; letter-spacing: 0; }
.mmbody {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-top: 4px; font-size: 1.05rem;
}
.mmlane {
  padding: 1px 8px;
  background: var(--surface-2); border-radius: 999px;
  font-size: .9rem; color: var(--text);
}
.mmscore { margin-left: auto; font-weight: 700; color: var(--gold); }
.mmfoot { margin-top: 6px; }

/* ── Rundenuhr ────────────────────────────────────────────────────────────
   Die Uhr der laufenden Runde: grosse Zahl, kleiner Satz. Gruen, solange
   Zeit ist; Bernstein ab der Warnschwelle; Rot und aufwaerts zaehlend, wenn
   sie um ist; grau und still, wenn sie angehalten wurde. In der letzten
   Minute atmet der Rand — dieselbe Sprache wie die Uhr in der App. */
.rclock {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: 14px 0 0;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--win);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.rc-time {
  font-size: 1.6rem; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--win);
}
.rc-label { font-size: .9rem; color: var(--muted); }
.rclock.warn { border-left-color: var(--gold); }
.rclock.warn .rc-time { color: var(--gold); }
.rclock.up { border-left-color: var(--err); }
.rclock.up .rc-time { color: var(--err); }
.rclock.up .rc-label { color: var(--err); font-weight: 600; }
.rclock.paused { border-left-color: var(--border); }
.rclock.paused .rc-time { color: var(--muted); }
/* Die Pause der Tafel: gold wie die Ansage im Saal, nicht grau wie eine
   angehaltene Uhr — sie ist gewollt, kein Stillstand. */
.rclock.break { border-left-color: var(--gold); }
.rclock.break .rc-time { color: var(--gold); }
.rclock.break .rc-label { color: var(--text); }
.rclock.warn .rc-time { animation: rc-warn 1s ease-in-out infinite alternate; }
@keyframes rc-warn { from { opacity: 1; } to { opacity: .55; } }
@media (prefers-reduced-motion: reduce) {
  .rclock.warn .rc-time { animation: none; }
}
/* Das Plaettchen in „Meine Partie" traegt dieselben Farben. */
.mmclock { font-variant-numeric: tabular-nums; font-weight: 600; }
.mmclock.run { color: var(--win); }
.mmclock.warn { color: var(--gold); }
.mmclock.up { color: var(--err); }
.mmclock.paused { color: var(--muted); }

/* Ein Knopf, der wie ein Verweis aussieht — für Nebensachen im Fließtext. */
.linkbtn {
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; cursor: pointer;
  text-decoration: underline;
}

/* Die Mannschaftswahl: eine Liste in der Mitte des Schirms.
 *
 * Sie kam von unten herein — am unteren Rand angeschlagen, so hoch wie der
 * Schirm. Auf einem Smartphone blieb davon nur der abgedunkelte Hintergrund:
 * Der untere Rand des festen Rahmens liegt dort je nach Browser unter der
 * ein- und ausfahrenden Werkzeugleiste oder unterhalb des sichtbaren
 * Ausschnitts, sobald die Seite gezoomt ist — und mit ihm die ganze Liste.
 * Die Mitte ist auf jedem Schirm sichtbar; deshalb steht sie jetzt dort,
 * und der Rahmen misst sich am kleinsten Ausschnitt (svh), den der Browser
 * je zeigt, statt am groessten (vh). */
.sheetwrap {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 12px; background: rgba(3, 8, 16, .6);
}
@supports (height: 100svh) {
  .sheetwrap { height: 100svh; }
}
.sheet {
  width: 100%; max-width: 520px; max-height: 80%; overflow: auto;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: 14px 0 8px;
}
.sheethead {
  padding: 0 18px 10px; font-weight: 700; color: var(--text);
}
.sheetlist { list-style: none; margin: 0; padding: 0; }
.sheetlist button {
  display: block; width: 100%; text-align: left;
  padding: 12px 18px;
  background: none; border: 0; border-top: 1px solid var(--border-soft);
  color: var(--text); font: inherit; cursor: pointer;
}
.sheetlist button:hover { background: var(--surface); }

/* Das Band „Keine Verbindung" über einem Stand von vorhin. */
.offlinenote { margin-top: 10px; }
