/* Backyard Crew — PWA Stylesheet
   Dark-First, Material-3-inspiriert, große Touch-Ziele, Nacht-Rot-Modus. */

:root {
  --bg:        #0B0F14;
  --surface:   #131A22;
  --surface-2: #1B2530;
  --surface-3: #243040;
  --line:      #2A3644;
  --text:      #E6EDF3;
  --text-dim:  #9AA7B4;
  --text-mute: #6B7885;
  /* Marke: Orange führt, Cyan begleitet — dieselben zwei Farben wie im Logo.
     --on-accent ist die Schrift, die AUF der Akzentfläche liegt: Weiß erreicht auf
     Orange nur 2,9:1, dieses dunkle Braunschwarz 6,7:1. */
  --accent:    #ff6a2f;
  --accent-2:  #25d7e6;
  --accent-dim:#c2470f;
  --on-accent: #1a0a04;
  --good:      #2FBF71;
  --warn:      #F5B62F;
  /* ⚠ Fehlerfarbe bewusst ins Rosarote gezogen (war #E5484D): neben dem orangen
     Akzent — Live-Leiste, Hero-Schein — lag das alte Rot fast auf derselben Farbe.
     Rot auf Rot ist Hausverbot; #FF4560 setzt sich im Farbton klar ab. */
  --bad:       #FF4560;
  --good-bg:   rgba(47,191,113,.14);
  --warn-bg:   rgba(245,182,47,.14);
  --bad-bg:    rgba(255,69,96,.14);
  --radius:    18px;
  --radius-sm: 12px;
  --tap:       64px;
  --shadow:    0 10px 30px -8px rgba(0,0,0,.55);
  --card-shadow: 0 1px 0 rgba(255,255,255,.04) inset, 0 10px 26px -16px rgba(0,0,0,.6);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* ⚠ Stand bis zum 18.08.2026 NUR im .auth-landing-Block und galt damit ausschließlich
     auf dem Anmeldebildschirm. Die Veranstaltungs-Kennung („2026-K7F2") braucht sie im
     ganzen Haus: Ihr einziger Zweck ist das Unterscheiden, und in einer Proportionalschrift
     stehen die Zeichen zu ungleichmäßig, um zwei Kennungen mit einem Blick zu vergleichen.
     Hochgezogen statt kopiert — zwei Fassungen derselben Schriftliste laufen auseinander. */
  --sp-mono:ui-monospace,"SFMono-Regular",Consolas,monospace;
}

/* Nacht-Rot-Modus: schont die Nachtsicht im Camp */
html[data-night="true"] {
  --bg:        #120404;
  --surface:   #1E0808;
  --surface-2: #2A0C0C;
  --surface-3: #380f0f;
  --line:      #4a1414;
  --text:      #FFD9CE;
  --text-dim:  #E39A88;
  --text-mute: #B06A5C;
  --accent:    #FF7A55;
  /* ⚠ --accent-2 gehört hierher: Rückfall des Ringverlaufs, falls color-mix fehlt.
     Ohne sie fiele er auf das Cyan des Tag-Modus zurück — und ein cyanfarbenes Leuchten ist
     genau das, was dieser Modus verhindern soll. */
  --accent-2:  #FFB08A;
  --good:      #E8A05a;
  --warn:      #FF9B3d;
  --bad:       #FF5A4d;
}

/* ── Fortschrittsringe (Stärken, Level am Avatar, Level in der Kopfleiste) ────
   Gezeichnet von ringBogenSVG() in app.js. Das Essens-Tagebuch hat seine eigene
   Fassung (.ek-ring), weil dort zusätzlich ein Sport-Bogen und Text in der Mitte
   liegen — die Gestaltungsregeln sind aber dieselben.

   ⚠⚠ overflow:visible ist PFLICHT. Der Bogen füllt das SVG bis an den Rand; ohne
      diese Zeile schneidet der Rahmen das Leuchten ab, und übrig bliebe ein matter
      Ring mit einem harten Rand drumherum.
   ⚠ Die Farbe steht als `color` am <svg> (von ringBogenSVG gesetzt) und wird über
     currentColor weitergereicht. Nur so leuchtet auch ein Ring in einer Sportfarbe
     aus dem Katalog richtig — dort gibt es keine CSS-Variable, die man greifen
     könnte. */
.uq-ring { overflow: visible; }
.uq-ring-stop-a { stop-color: currentColor; }
/* Die hellere Verwandte wird ABGELEITET, nie fest gesetzt: Die Akzentfarbe ist in
   dieser App wählbar, und die Stärken-Ringe tragen je Sportart eine eigene Farbe.
   Fehlt color-mix, bleibt der Verlauf einfarbig — sichtbar bleibt der Ring in jedem
   Fall (deshalb currentColor als Rückfall, nicht Schwarz). */
.uq-ring-stop-b { stop-color: color-mix(in srgb, currentColor 55%, #ffffff); }
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .uq-ring-stop-b { stop-color: currentColor; }
}
.uq-ring-spur { stroke: var(--surface-2, #1B2530); }
.uq-ring-fuell { filter: drop-shadow(0 0 5px currentColor); }

/* Bei reduzierter Bewegung bleibt alles ruhig — hier gibt es zwar keine Animation,
   aber das Leuchten wird zurückgenommen: Es ist der Teil, der flimmern kann. */
@media (prefers-reduced-motion: reduce) {
  .uq-ring-fuell { filter: drop-shadow(0 0 3px currentColor); }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 16px;
  line-height: 1.4;
  overscroll-behavior-y: none;
  -webkit-font-smoothing: antialiased;
  letter-spacing: .1px;
}
/* Ambient-Hintergrund der Veranstaltung (hinter dem gesamten App-Inhalt) */
#ambient {
  position: fixed; inset: 0; z-index: -1; background: var(--bg);
  transition: background .45s ease;
}
button { font-family: inherit; }
h1,h2,h3,h4 { margin: 0 0 .4em; font-weight: 700; }
a { color: var(--accent); }

/* Tastaturfokus: Der Tipp-Schimmer ist oben global abgeschaltet, ohne diesen Ring
   wüsste am Rechner niemand, wo die Tastatur gerade steht. Der Abstand von 2 px legt
   den Ring AUSSERHALB des Elements — deshalb bleibt er auch auf einem orangen Knopf
   sichtbar, weil er dort auf dem dunklen Grund liegt (6,8:1 gegen --bg).
   `:where()` zählt nicht in die Spezifität: Jede Einzelregel sticht ihn weiterhin. */
:where(button, a, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Der Farbtupfer im Design-Picker trägt im Zustand „gewählt" schon ein eigenes
   outline — sonst bliebe der Fokus dort unsichtbar. */
.swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------- App-Shell ---------- */
#app { min-height: 100vh; display: flex; flex-direction: column; background: transparent; }

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px calc(12px);
  padding-top: max(12px, env(safe-area-inset-top));
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface) 82%, transparent) 0%, color-mix(in srgb, var(--surface) 60%, transparent) 100%);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px);
}
/* Auf schmalen Geräten (320 px) passte die Kopfzeile nicht: Flex-Kinder schrumpfen von
   sich aus NICHT unter ihre Inhaltsbreite (min-width:auto), dadurch schob der ☰-Knopf
   die ganze Seite quer. Die Marke darf weichen, die Knöpfe bleiben ganz. */
.topbar .brand { display: flex; align-items: center; gap: 9px; font-weight: 800; letter-spacing: .3px; font-size: 17px; min-width: 0; }
.topbar .brand .brand-mark { flex: 0 0 auto; display: block; filter: drop-shadow(0 2px 6px rgba(0,0,0,.4)); }
.topbar .brand .brand-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar .brand .brand-txt small { color: var(--accent); font-weight: 700; }
.topbar .spacer { flex: 1 1 0; min-width: 0; }
.topbar .role-pill {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  padding: 6px 12px; border-radius: 999px; background: var(--surface-3); color: var(--text-dim);
  flex: 0 0 auto; white-space: nowrap;
}
/* Auf Handys bleibt nur das Rollen-Symbol — ein abgeschnittenes „📋 Veranstalt…" sieht
   kaputt aus, das Symbol allein ist eindeutig. 430 statt 380: auch auf 390–430-px-Geräten
   (iPhone 15/16) drückte die volle Pille den Schriftzug zu „urqivo s…" (Foto Florian 26.07.). */
@media (max-width: 430px) {
  .topbar .role-pill .role-txt { display: none; }
  .topbar .role-pill { padding: 6px 10px; }
}
@media (max-width: 380px) {
  /* „urqivo SPORTS" muss KOMPLETT lesbar bleiben (war „urqivo SP…"). Logo-Größe bleibt;
     der Schriftzug wird kleiner und zweizeilig gestapelt — passt so in ~60 px Breite. */
  .topbar .brand { font-size: 14px; letter-spacing: .2px; }
  .topbar .brand .brand-txt { white-space: normal; overflow: visible; display: flex; flex-direction: column; line-height: 1.05; }
  .topbar .brand .brand-txt small { font-size: 11px; letter-spacing: .6px; }
}
.iconbtn {
  width: 44px; height: 44px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text); font-size: 20px; cursor: pointer;
  display: grid; place-items: center; flex: 0 0 auto;
}
.iconbtn:active { transform: scale(.94); }

.content { flex: 1; padding: 16px 16px 120px; max-width: 900px; width: 100%; margin: 0 auto; }

/* ---------- Bottom-Navigation ---------- */
.bottomnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; justify-content: space-around; align-items: stretch;
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface) 72%, transparent), color-mix(in srgb, var(--surface) 92%, transparent));
  border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -8px 30px rgba(0,0,0,.4);
  backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px);
}
.bottomnav button.active .ico { transform: translateY(-1px); filter: drop-shadow(0 3px 8px color-mix(in srgb, var(--accent) 55%, transparent)); }
.bottomnav button {
  flex: 1; border: 0; background: transparent; color: var(--text-mute);
  padding: 10px 4px; min-height: var(--tap); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  font-size: 11px; font-weight: 600;
}
.bottomnav button .ico { font-size: 22px; line-height: 1; }
.bottomnav button.active { color: var(--accent); }
.bottomnav button.fab {
  flex: 0 0 auto; margin-top: -18px;
}
.bottomnav button.fab .ico {
  width: 60px; height: 60px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent); display: grid; place-items: center;
  font-size: 30px; box-shadow: var(--shadow);
}

/* ---------- Cards ---------- */
.card {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--surface-2) 32%, transparent) 0%, transparent 42%),
    var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; margin-bottom: 14px;
  box-shadow: var(--card-shadow);
}
.card.tight { padding: 14px; }
.card h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .8px; color: var(--text-mute); }

.section-title { font-size: 13px; text-transform: uppercase; letter-spacing: .8px; color: var(--text-mute); margin: 18px 4px 8px; }

/* ---------- Hero-Countdown ---------- */
.hero {
  text-align: center; padding: 28px 18px;
  background:
    radial-gradient(120% 90% at 50% -10%, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 55%),
    radial-gradient(120% 120% at 50% 0%, var(--surface-2) 0%, var(--surface) 72%);
  /* 2px-Rahmen im Box-Modell: liegt immer außerhalb des Textbereichs, nie darüber.
     Feste Breite über alle Zustände → kein Springen beim Pulsieren. */
  border: 2px solid var(--line); border-radius: var(--radius); margin-bottom: 14px;
  position: relative; overflow: hidden;
  box-shadow: var(--card-shadow);
}
.hero.state-good  { border-color: var(--good); }
.hero.state-warn  { border-color: var(--warn); }
/* Nur die Rahmen-FARBE pulsiert (keine Größenänderung, kein Überdecken von Text). */
.hero.state-bad   { border-color: var(--bad); animation: heroPulse 1.4s ease-in-out infinite; }
@keyframes heroPulse {
  0%, 100% { border-color: var(--bad); }
  50%      { border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
}
/* Veranstaltungsname + Ort über dem Countdown (Vorstart-Screen) */
.hero .ev-name { font-size: 22px; font-weight: 800; letter-spacing: .3px; line-height: 1.2; }
.hero .ev-meta { color: var(--text-dim); font-size: 14px; margin: 2px 0 12px; }

/* Veranstaltungs-Logo (Vorstart-Hero + Einrichten-Blatt) und Sponsoren-Zeile */
.ev-logo { max-height: 64px; max-width: 180px; border-radius: 10px; display: block; margin: 0 auto 8px; }
.ev-logo.sm { max-height: 40px; max-width: 120px; margin: 0; display: inline-block; vertical-align: middle; }
.ev-logo.xs { max-height: 24px; max-width: 72px; margin: 0 6px 0 0; display: inline-block; vertical-align: middle; }
.sponsor-row { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center; }
.sponsor-row img { max-height: 28px; max-width: 96px; border-radius: 6px; }
.sponsor-row .sp-name { color: var(--text-dim); font-size: 13px; font-weight: 600; }
.sponsor-row a { display: inline-flex; align-items: center; text-decoration: none; }
.sponsor-row a .sp-name { text-decoration: underline dotted; text-underline-offset: 3px; }

/* Sponsoren-Kästen am Seitenende: Name oben, Logo darunter, ganzer Kasten klickbar */
.sponsor-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-top: 8px; }
.sponsor-box {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 10px; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 14px; color: var(--text); text-decoration: none; text-align: center; min-height: 76px;
}
a.sponsor-box:active, a.sponsor-box:hover { border-color: var(--accent); }
.sponsor-box .sp-box-name { font-weight: 700; font-size: 14px; }
.sponsor-box img { max-height: 48px; max-width: 100%; border-radius: 8px; }

/* Tarife: durchgestrichener Ausblicks-Preis neben dem Startphase-Preis */
s.price-old { color: var(--text-mute); margin-right: 6px; font-weight: 600; }

/* Social-Beiträge (Community): anklickbare Karte → Original-Post */
.post-wrap { position: relative; margin-bottom: 10px; }
.post-card {
  display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--text);
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface-2) 32%, transparent), transparent 42%), var(--surface);
  border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; box-shadow: var(--card-shadow);
}
.post-card:active { border-color: var(--accent); }
.post-card .pc-ico { font-size: 26px; flex: 0 0 auto; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; background: var(--surface-2); }
.post-card .pc-body { flex: 1; min-width: 0; }
.post-card .pc-cap { display: block; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.post-card .pc-meta { color: var(--text-mute); }
.post-card .pc-go { flex: 0 0 auto; color: var(--accent); font-weight: 700; font-size: 13px; }
.post-del { position: absolute; top: 8px; right: 8px; padding: 2px 9px; font-size: 12px; z-index: 2; }
.post-wrap:has(.post-del) .post-card { padding-right: 40px; }
.post-card .pc-tag { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-weight: 700; font-size: 11px; background: var(--surface-3); color: var(--text-dim); }
.post-card .pc-tag.ok { background: var(--good-bg); color: var(--good); }

/* Anklickbarer Name → Profil */
.name-link { background: none; border: 0; padding: 0; margin: 0; font: inherit; font-weight: 800; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
/* Avatar (Profilkarte + Editor) */
.avatar { border-radius: 50%; object-fit: cover; display: inline-grid; place-items: center; vertical-align: middle; flex: 0 0 auto; }
/* Initialen: Der Verlauf bleibt bewusst im dunklen Teil der Akzentfamilie — auf dem
   hellen Orange käme Weiß nur auf 2,9:1, so trägt es über den ganzen Verlauf ≥5:1. */
.avatar.ph { background: linear-gradient(135deg, var(--accent-dim), color-mix(in srgb, var(--accent-dim) 55%, #000)); color: #fff; font-weight: 800; }
/* Profilbild groß ansehen — nur die Bilder, die für sich stehen (Profilkarte, Editor),
   tragen `.avatar-zoom`. Unter dem Zeiger hebt es sich an wie jede andere Fläche der App. */
.avatar-zoom { cursor: zoom-in; transition: transform .22s, box-shadow .22s, outline-color .22s; outline: 2px solid transparent; outline-offset: 2px; }
.avatar-zoom:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(0,0,0,.38); outline-color: var(--accent); }
/* ⚠ Ebene 70: über Blatt (50) und Schublade (61), aber UNTER dem Toast (80) — eine Meldung,
   die hinter dem Bild verschwände, käme nicht wieder zum Vorschein. */
.uq-bildgross {
  position: fixed; inset: 0; z-index: 70; padding: 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: rgba(0,0,0,.84); animation: fade .18s; cursor: zoom-out;
}
/* ⚠ `contain`, nicht `cover`: Der Kreis in der Karte schneidet zu, groß soll das GANZE
   Bild stehen. Die Breite ist bewusst gedeckelt — die Quelle ist auf 200 px lange Kante
   verkleinert gespeichert, weiter aufgezogen wird sie nur unscharf. */
.uq-bildgross img {
  max-width: min(84vw, 300px); max-height: 72vh; width: auto; height: auto;
  border-radius: 18px; object-fit: contain;
  border: 3px solid rgba(255,255,255,.14); box-shadow: 0 18px 50px rgba(0,0,0,.55);
}
.uq-bildgross-name { color: #fff; font-weight: 800; font-size: 17px; text-align: center; }
.uq-bildgross-zu {
  position: absolute; top: max(14px, env(safe-area-inset-top)); right: 14px;
  width: 40px; height: 40px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(255,255,255,.16); color: #fff; font-size: 17px; line-height: 1;
}
@media (prefers-reduced-motion: reduce) {
  .avatar-zoom, .avatar-zoom:hover { transition: none; transform: none; }
  .uq-bildgross { animation: none; }
}
/* Kanal-Chips in der Profilkarte */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip-link { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; padding: 8px 14px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); color: var(--text); font-weight: 600; font-size: 14px; }
.chip-link:active { border-color: var(--accent); }

/* Design-Picker im Einrichten-Blatt: Akzentfarbe + Hintergrund */
.swatch-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 6px; }
.swatch { width: 34px; height: 34px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0; box-shadow: 0 2px 8px rgba(0,0,0,.4); }
.swatch.on { border-color: var(--text); outline: 2px solid var(--bg); }
.swatch.custom { display: grid; place-items: center; background: var(--surface-3); color: var(--text); font-size: 15px; }
.bg-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
.bg-choice { border: 1px solid var(--line); border-radius: 12px; padding: 0; cursor: pointer; overflow: hidden; background: var(--surface-2); color: var(--text); }
.bg-choice.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.bg-choice .prev { height: 42px; display: block; }
.bg-choice .lbl { display: block; font-size: 12px; font-weight: 600; padding: 5px 0; }

/* Höhenprofil der importierten Strecke (Karte, Vorstart, Etappen) */
.elev-svg { width: 100%; height: 120px; display: block; border-radius: 8px; }

/* ✕ im Popup: bleibt beim Scrollen oben rechts sichtbar (sticky) */
.sheet .sheet-x {
  position: sticky; top: 0; float: right; margin: -4px -4px 0 8px;
  width: 36px; height: 36px; z-index: 2;
  border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text); font-size: 22px; line-height: 1; cursor: pointer;
}
.hero .label { font-size: 13px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-dim); }
.hero .big {
  font-size: clamp(56px, 20vw, 104px); font-weight: 800; line-height: 1; letter-spacing: 2px;
  font-variant-numeric: tabular-nums; margin: 8px 0 6px;
  white-space: nowrap;
}
/* Zeitangaben werden mit jeder Stelle breiter: „51:00" (5 Zeichen) passt bequem,
   „1:00:00" (7) und „00:20:39" (8) schoben sich über den Rand des Kastens. Die
   Schriftgröße richtet sich deshalb nach der Zeichenzahl — die Klasse setzt bigCls()
   in app.js dort, wo der Text entsteht. */
.hero .big.len7 { font-size: clamp(40px, 15vw, 80px); letter-spacing: 1px; }
.hero .big.len8 { font-size: clamp(34px, 13vw, 68px); letter-spacing: 0; }
.hero.state-good .big { color: var(--good); }
.hero.state-warn .big { color: var(--warn); }
.hero.state-bad  .big { color: var(--bad); }
.hero .sub { color: var(--text-dim); font-size: 15px; }
.hero .phase {
  display: inline-block; margin-bottom: 8px; padding: 5px 14px; border-radius: 999px;
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 1px;
}
.phase-run  { background: var(--good-bg); color: var(--good); }
.phase-rest { background: var(--warn-bg); color: var(--warn); }
.phase-corral { background: var(--bad-bg); color: var(--bad); }

/* Fortschrittsbalken */
.bar { height: 10px; border-radius: 999px; background: var(--surface-3); overflow: hidden; margin-top: 14px; }
.bar > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; transition: width .5s; }
.bar.good > span { background: var(--good); }
.bar.warn > span { background: var(--warn); }
.bar.bad  > span { background: var(--bad); }

/* ---------- Stat-Grid ---------- */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.stats.two { grid-template-columns: repeat(2, 1fr); }
.stats.four { grid-template-columns: repeat(4, 1fr); }
.stat {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 10px; text-align: center;
}
.stat .v { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; }
.stat .k { font-size: 11px; color: var(--text-mute); text-transform: uppercase; letter-spacing: .5px; margin-top: 2px; }
.stat .ico { font-size: 15px; }
.stat.good .v { color: var(--good); }
.stat.warn .v { color: var(--warn); }
.stat.bad  .v { color: var(--bad); }

/* ---------- Buttons ----------
   Eine Skala für ALLE Knöpfe (Florian, 18.08.: „teilweise sind Felder sehr groß,
   einheitlich anpassen — mobil an Instagram orientieren"). 44 px ist die Höhe der
   .iconbtn und zugleich die volle Touch-Empfehlung — mehr braucht kein Knopf,
   auch auf dem Desktop nicht. Die alten 72 px stammten aus der Zeitnahme-Ära. */
.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 44px; border: 0; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--on-accent); font-size: 16px; font-weight: 700;
  cursor: pointer; letter-spacing: .3px; box-shadow: var(--shadow); padding: 10px 16px;
  /* ⚠ Ein Knopf, dessen letzte Zeile aus einem einzigen Wort besteht, sieht kaputt aus:
     „Habe noch keins — Trainer schlägt / vor" (Florian, 26.08.2026, Bildschirmfoto).
     `balance` verteilt die Wörter gleichmäßig auf die Zeilen; Browser ohne die
     Eigenschaft brechen weiter wie bisher — es geht nichts verloren. */
  text-wrap: balance;
}
.btn:active { transform: scale(.985); }
.btn.secondary { background: var(--surface-3); color: var(--text); box-shadow: none; border: 1px solid var(--line); }
.btn.good { background: var(--good); }
.btn.warn { background: var(--warn); color: #1a1200; }
.btn.bad  { background: var(--bad); }
.btn.sm { min-height: 36px; font-size: 14px; padding: 7px 13px; }
.btn.ghost { background: transparent; border: 1px solid var(--line); color: var(--text); box-shadow: none; }
/* Knopfreihen brechen um, statt die Seite quer zu schieben: drei Knöpfe nebeneinander
   passen auf 320 px nicht. Die Mindestbreite entscheidet, wann umbrochen wird — der
   umgebrochene Knopf nimmt dann die volle Zeile ein. */
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }
.btn-row .btn { flex: 1 1 0; min-width: 130px; }

/* ---------- Checklist ---------- */
.check {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 14px; margin-bottom: 10px; cursor: pointer; text-align: left; color: var(--text);
  font-size: 15px; font-weight: 600;
}
.check .box {
  width: 24px; height: 24px; flex: 0 0 auto; border-radius: 7px; border: 2px solid var(--text-mute);
  display: grid; place-items: center; font-size: 16px; color: transparent;
}
.check.done { background: var(--good-bg); border-color: var(--good); }
.check.done .box { background: var(--good); border-color: var(--good); color: #fff; }
.check.done .lbl { text-decoration: line-through; color: var(--text-dim); }
/* Ausgewählter Läufer („mein Star") in der Startliste. BEWUSST NICHT .check.done:
   dort ist der Text durchgestrichen — das liest sich wie „erledigt/ausgeschieden"
   und wäre für den Favoriten genau die falsche Botschaft. */
.check.stern { background: color-mix(in srgb, var(--accent) 14%, transparent); border-color: var(--accent); }
.check.stern .lbl { color: var(--text); font-weight: 800; }
.check .who { margin-left: auto; font-size: 12px; color: var(--text-mute); font-weight: 600; }
.check .src { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: var(--surface-3); color: var(--text-dim); margin-left: 8px; }

/* prep list */
.prep { list-style: none; padding: 0; margin: 0; }
.prep li { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px dashed var(--line); font-size: 18px; font-weight: 600; }
.prep li:last-child { border-bottom: 0; }
.prep li .dot { color: var(--warn); font-size: 20px; }

/* ---------- Sliders (Post-Yard-Check) ---------- */
.rating { margin-bottom: 16px; }
.rating .rlabel { display: flex; justify-content: space-between; font-weight: 700; margin-bottom: 8px; font-size: 16px; }
.rating .rlabel .rv { color: var(--accent); font-variant-numeric: tabular-nums; }
.scale { display: flex; gap: 5px; }
.scale button {
  flex: 1; min-height: 44px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text-mute); font-weight: 800; font-size: 15px; cursor: pointer;
}
.scale button.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.scale.inverse button.on { background: var(--warn); color: #1a1200; border-color: var(--warn); }

/* ---------- Tables / lists ---------- */
.table { width: 100%; border-collapse: collapse; font-size: 15px; }
.table th, .table td { text-align: left; padding: 12px 10px; border-bottom: 1px solid var(--line); }
.table th { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-mute); }
.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table tr:active { background: var(--surface-2); }
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.badge.good { background: var(--good-bg); color: var(--good); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.bad  { background: var(--bad-bg); color: var(--bad); }
.badge.mute { background: var(--surface-3); color: var(--text-dim); }

/* ticker */
.ticker { list-style: none; padding: 0; margin: 0; }
.ticker li { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.ticker li .t { color: var(--text-mute); font-variant-numeric: tabular-nums; flex: 0 0 52px; font-weight: 700; }

/* Rundenverlauf-Accordion (Zuschauer) */
.ticker li.yd { flex-direction: column; align-items: stretch; gap: 0; padding: 0; }
.yd-head { display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 0; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.yd-head:disabled { cursor: default; }
.yd-head .yd-sum { flex: 1; min-width: 0; }
.yd-head .yd-chev { flex: 0 0 auto; color: var(--text-mute); font-size: 13px; }
.yd-body { display: flex; flex-direction: column; gap: 6px; padding: 2px 0 12px 64px; }
.yd-row { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
.yd-row > span { color: var(--text-mute); flex: 0 0 auto; }
.yd-row > b { text-align: right; font-weight: 600; }

/* Starterfeld-Karte + Ausscheide-Alarm (gelber Glocken-Puls) */
.feld-card .feld-raus { margin-top: 6px; font-size: 14px; }
.feld-card .raus { color: #F5B62F; font-variant-numeric: tabular-nums; }
@keyframes feld-alarm {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 182, 47, 0); border-color: var(--line); }
  50% { box-shadow: 0 0 0 5px rgba(245, 182, 47, .55); border-color: #F5B62F; }
}
.feld-card.alarm { border-color: #F5B62F; animation: feld-alarm .7s ease-in-out 0s 8; }

/* ---------- Map placeholder ---------- */
.map {
  position: relative; height: 320px; border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line);
  background:
    radial-gradient(circle at 30% 40%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 40%),
    repeating-linear-gradient(0deg, #0e141b 0 39px, #16202b 39px 40px),
    repeating-linear-gradient(90deg, #0e141b 0 39px, #16202b 39px 40px);
}
.map svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.map .maptag {
  position: absolute; bottom: 12px; left: 12px; right: 12px;
  background: rgba(11,15,20,.85); border: 1px solid var(--line); border-radius: 12px;
  padding: 10px 14px; font-size: 14px; display: flex; justify-content: space-between; gap: 10px;
}

/* ---------- Coach messages ---------- */
.coach { border-left: 4px solid var(--accent); }
.coach.info { border-color: var(--accent); }
.coach.warn { border-color: var(--warn); }
.coach.critical { border-color: var(--bad); }
.coach .ctitle { display: flex; align-items: center; gap: 8px; font-weight: 800; margin-bottom: 4px; }

/* ---------- Modal / Popup (zentriert; schließt NUR über ✕ oder die Aktion) ---------- */
.sheet-backdrop {
  position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,.6);
  display: flex; align-items: center; justify-content: center;
  padding: 18px; animation: fade .2s;
}
@keyframes fade { from { opacity: 0; } }
.sheet {
  width: 100%; max-width: 560px; max-height: 86vh; overflow-y: auto;
  background: var(--surface); border-radius: 22px; border: 1px solid var(--line);
  padding: 20px 18px;
  animation: pop .22s cubic-bezier(.2,.8,.2,1);
}
@keyframes pop { from { transform: scale(.96) translateY(12px); opacity: .5; } }
/* Grip war die Wisch-Optik des alten Bottom-Sheets — beim zentrierten Popup ohne Funktion */
.sheet .grip { display: none; }
/* Überschriften im Popup brechen ebenfalls ausgewogen — sie fließen um das
   Schließkreuz herum und rissen sonst nach dem zweiten Wort um. */
.sheet h2 { font-size: 22px; text-wrap: balance; }
.sheet .muted { color: var(--text-dim); }

/* misc */
.row { display: flex; gap: 10px; align-items: center; }
.row.between { justify-content: space-between; }
.muted { color: var(--text-dim); }
.mono { font-variant-numeric: tabular-nums; }
/* Die Kennung einer Veranstaltung („2026-K7F2"): eine Aufschrift, kein Beitrittscode.
   ⚠ Deshalb bewusst KLEIN und in der gedämpften Farbe — sie steht zwar vorn in der
   Metazeile (was hinten steht, sieht niemand), darf aber nie mit dem Läufer- oder
   Zuschauer-Code verwechselt werden, der groß und gesperrt in seiner eigenen Kachel sitzt.
   ⚠ `class="mono"` ist in diesem Projekt KEINE Monospace-Schrift, sondern nur
   tabular-nums — für Ziffernkolonnen gedacht. Eine Kennung besteht aus Ziffern UND
   Buchstaben; sie braucht echte Festbreite, sonst tanzen die Zeichen. */
.kennung { font-family: var(--sp-mono); font-size: 12px; letter-spacing: .06em; color: var(--text-mute); }
.pill-row { display: flex; flex-wrap: wrap; gap: 8px; }

/* Reiter der Live-Ansicht: EINE Reihe (Florian, 18.08.2026: „in eine reihe").
   Fünf Reiter mit Icon und Wort passen auf einem Handy nicht nebeneinander — statt sie
   umbrechen zu lassen (zwei Zeilen, die wie zwei verschiedene Leisten aussehen), läuft
   die Reihe seitlich. Die Bildlaufleiste bleibt unsichtbar; dass es weitergeht, zeigt
   der angeschnittene letzte Reiter am Rand.
   ⚠ overflow-y: hidden gehört dazu: Ein reines overflow-x: auto macht die Achse
   senkrecht ebenfalls scrollbar und schneidet Fokusringe ab. */
.live-segmente {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scrollbar-width: none;              /* Firefox */
  -ms-overflow-style: none;           /* alte Edge */
  padding-bottom: 2px;
  -webkit-overflow-scrolling: touch;
}
.live-segmente::-webkit-scrollbar { display: none; }
.live-segmente .pill {
  flex: 0 0 auto;                     /* nicht stauchen — sonst bricht der Text um */
  scroll-snap-align: start;
  white-space: nowrap;
}
/* Auf dem Handy enger gesetzt, damit möglichst viele Reiter ohne Wischen dastehen. */
@media (max-width: 700px) {
  .live-segmente { gap: 6px; }
  .live-segmente .pill { padding: 8px 11px; font-size: 13px; }
}

.pill { padding: 8px 14px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); font-size: 14px; font-weight: 600; cursor: pointer; color: var(--text); }
.pill.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
/* hidden-Attribut muss auch gegen display:block/flex-Regeln (label.field, .btn-row …) gewinnen */
[hidden] { display: none !important; }
/* `input:not([type])` fängt Felder ohne type-Attribut mit ab (z. B. #em-frei im
   Reagieren-Blatt) — die wären sonst unsichtbar klein und rahmenlos.
   Schriftgröße bleibt 16px: kleiner, und iOS zoomt beim Fokus in die Seite. */
/* ⚠ Seit `user-scalable=no` draußen ist (Barrierefreiheit, richtig so), zoomt iOS beim
   Fokus in JEDES Feld, dessen Schrift kleiner als 16px ist — unterdrücken lässt sich das
   nicht mehr, nur vermeiden. Diese Auffangregel gibt deshalb ALLEN Textfeldern 16px, auch
   solchen, die unten in der Liste nicht einzeln stehen (search, tel, url, time …) und
   künftigen. Sie steht in :where() und hat damit Spezifität 0: Jede andere Regel gewinnt
   gegen sie, sie ist nur der Boden. Ausgenommen sind die Felder ohne Text — Kästchen,
   Auswahlpunkte, Schieber, Farbwähler —, bei denen die Schriftgröße die Darstellung
   verändern würde, ohne dass je jemand hineinschreibt. */
:where(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]),
  textarea, select) { font-size: 16px; }
input[type=text], input[type=password], input[type=email], input[type=number], input[type=datetime-local], input[type=date], input[type=time], input[type=search], input[type=tel], input[type=url], input:not([type]), textarea, select {
  width: 100%; padding: 11px 14px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text); font-size: 16px; font-family: inherit;
  /* ⚠ Eine feste Zeilenhöhe für ALLE Felder: Ohne sie richtet sich die Höhe nach dem,
     was das jeweilige Bedienelement mitbringt — ein Datumsfeld wurde dadurch flacher
     als das Textfeld darüber (Florian, 26.08.2026). So sind sie überall gleich hoch. */
  line-height: 1.4;
}
textarea { resize: vertical; min-height: 80px; }
/* ⚠ Datums- und Zeitfelder bringen ihr eigenes Bedienelement mit (Ziffernblöcke plus
   Kalendersymbol) und damit eine intrinsische Mindestbreite. In schmalen Karten und auf
   dem Handy gewinnt die gegen width:100% — das Feld schob sich über den rechten Rand
   hinaus (Florian, 25.08.2026). min-width:0 gibt der Breitenangabe den Vorrang zurück. */
input[type=date], input[type=datetime-local], input[type=time] {
  min-width: 0; max-width: 100%; display: block;
  /* Dieselbe Rechnung wie beim Textfeld: Zeile (1,4 em) plus Innenabstand (2 × 11 px)
     plus Rahmen (2 × 1 px). Nötig, weil `appearance: none` auf iOS die natürliche Höhe
     nimmt und das Feld sonst flacher steht als seine Nachbarn. */
  min-height: calc(1.4em + 24px);
}
/* ⚠⚠ iOS/Safari zentriert den Inhalt eines Datumsfelds und leitet daraus eine EIGENE
   Breite ab, die width:100% überstimmt — auf dem iPhone schob sich der „Wunschtermin"
   dadurch aus der Karte heraus (Florian, 25.08.2026, Bildschirmfoto von sports.urqivo.de).
   min-width allein hilft dagegen nicht: Die Breite kommt aus dem inneren Bedienelement.
   Es links auszurichten nimmt ihr die Grundlage. Chromium bleibt unberührt — das
   Kalendersymbol des Desktops bleibt erhalten, weil hier NICHT appearance:none steht. */
input[type=date]::-webkit-date-and-time-value,
input[type=datetime-local]::-webkit-date-and-time-value,
input[type=time]::-webkit-date-and-time-value {
  text-align: left; min-width: 0; width: 100%;
}
/* Zweiter Riegel nur für iOS (die Touch-Callout-Weiche trifft ausschließlich Safari auf
   iPhone/iPad): dort gibt es ohnehin kein sichtbares Kalendersymbol zu verlieren. */
@supports (-webkit-touch-callout: none) {
  input[type=date], input[type=datetime-local], input[type=time] {
    -webkit-appearance: none; appearance: none; width: 100%;
  }
}
/* Der Platzhalter für leere Datumsfelder (siehe js/datumsfeld.js). Die Hülle legt sich
   deckungsgleich über das Feld, deshalb sitzt der Text immer richtig — unabhängig von
   Feldhöhe, Schriftgröße und Abständen. Er nimmt keine Klicks an: Ein Tipp geht durch
   ihn hindurch auf das Feld und öffnet den Datumswähler wie zuvor. */
.uq-datum-huelle { position: relative; display: block; }
.uq-datum-platzhalter {
  position: absolute; inset: 0; display: none; align-items: center;
  padding: 0 15px; font-size: 16px; color: var(--text-mute);
  pointer-events: none; border-radius: 12px;
}
/* ⚠⚠ NUR Safari zeigt ihn. Chromium schreibt in ein leeres Datumsfeld von sich aus
   „tt.mm.jjjj" — dort läge unser Text als zweite Schicht darüber und beides verschmierte
   ineinander. `-webkit-hyphens` gibt es nur in Safari (Chromium kann `hyphens` ohne
   Präfix), die Weiche trennt also genau richtig; nachgemessen am 25.08.2026: In Chromium
   ist `CSS.supports("(-webkit-hyphens: none)")` false. */
@supports (-webkit-hyphens: none) {
  .uq-datum-huelle:not(.hat-wert):not(:focus-within) .uq-datum-platzhalter { display: flex; }
}

label.field { display: block; margin-bottom: 12px; }
label.field .flabel { font-size: 13px; color: var(--text-mute); margin-bottom: 6px; display: block; font-weight: 600; }
/* Passwortfeld exakt wie das E-Mail-Feld: native Reveal-/Clear-Icons (Edge/Chromium) ausblenden */
input[type="password"]::-ms-reveal, input[type="password"]::-ms-clear { display: none; }
/* „Passwort anzeigen" — ein eigenes Auge IM Feld. Das native von Edge/Chromium bleibt
   abgeschaltet (Regel darüber): Es taucht nur in manchen Browsern und nur beim Typ
   „password" auf — zwei Augen nebeneinander sähen aus wie ein Fehler. Der Text bekommt
   rechts Platz, damit ein langes Passwort nicht unter dem Knopf verschwindet. */
.pass-wrap { position: relative; display: block; }
.pass-wrap input { padding-right: 50px; }
.pass-zeigen {
  position: absolute; top: 50%; right: 7px; transform: translateY(-50%);
  width: 36px; height: 36px; padding: 0; border: 0; border-radius: 10px;
  background: transparent; color: var(--text-dim);
  font-size: 17px; line-height: 1; cursor: pointer;
}
.pass-zeigen:hover { background: var(--surface-3); }
.pass-zeigen:active { transform: translateY(-50%) scale(.92); }
.data-age { font-size: 12px; color: var(--text-mute); }
.empty { text-align: center; color: var(--text-mute); padding: 40px 20px; }

/* Rollen-Umschalter (Drawer) */
.drawer-backdrop { position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,.6); animation: fade .2s; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(320px, 86vw); background: var(--surface); border-left: 1px solid var(--line); z-index: 61; padding: 20px; padding-top: max(20px, env(safe-area-inset-top)); animation: slidein .25s; overflow-y: auto; }
@keyframes slidein { from { transform: translateX(40px); opacity: .5; } }
.drawer h3 { margin-top: 20px; }
.role-choice { display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 14px; margin-bottom: 10px; border-radius: 14px; border: 1px solid var(--line); background: var(--surface-2); color: var(--text); font-size: 15px; font-weight: 700; cursor: pointer; text-align: left; }
.role-choice.on { border-color: var(--accent); background: var(--surface-3); }
.role-choice .ico { font-size: 24px; }
.role-choice small { display: block; font-weight: 500; color: var(--text-mute); font-size: 13px; }

.toast {
  position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%);
  background: var(--surface-3); color: var(--text); border: 1px solid var(--line);
  padding: 14px 20px; border-radius: 14px; z-index: 80; box-shadow: var(--shadow);
  font-weight: 600; max-width: 90vw; text-align: center; animation: slideup .25s;
}

@media (min-width: 720px) {
  .stats.grid-lg { grid-template-columns: repeat(4, 1fr); }
}

/* ---------- Konten & Crews: links Liste, rechts Aktionen ---------- */
.split { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 760px) {
  .split { grid-template-columns: minmax(300px, 380px) 1fr; align-items: start; }
}

/* ---------- Anmeldung / Demo-Einstieg ---------- */
.auth {
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 32px 20px calc(32px + env(safe-area-inset-bottom));
  padding-top: max(32px, env(safe-area-inset-top));
  max-width: 460px; margin: 0 auto; gap: 22px;
  background:
    radial-gradient(90% 60% at 50% 0%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 60%),
    var(--bg);
}
.auth.wide { max-width: 560px; }
.auth-brand { text-align: center; }
.auth-logo { display: grid; place-items: center; margin-bottom: 12px; }
.auth-logo svg { filter: drop-shadow(0 4px 12px rgba(0,0,0,.4)); }
.auth-title { font-size: 26px; font-weight: 800; letter-spacing: 3px; }
.auth-title b { color: var(--accent); }
.auth-sub { color: var(--text-dim); font-size: 15px; letter-spacing: 2px; text-transform: uppercase; margin-top: 2px; }
.auth-card { width: 100%; margin: 0; }
.auth-card h2 { font-size: 22px; }
.auth-foot { color: var(--text-mute); font-size: 12px; text-align: center; margin: 0; }

/* ==== Reiches Sports-Login: HF-Kreis-Emblem + Läufer + Höhenprofil + EKG (portiert aus index.html) ==== */
.auth-landing {
  --sp-ground:#0a1519; --sp-ground2:#040d10; --sp-surface:#0f2831; --sp-surface2:#143842;
  --sp-line2:rgba(255,255,255,.18);
  /* Orange und Cyan kommen aus der Marke (--accent / --accent-2) und werden hier nicht
     ein zweites Mal gepflegt; nur die Aufhellungen bleiben eigene Werte. */
  --sp-orange:var(--accent); --sp-orange-2:#ff8a42; --sp-cyan:var(--accent-2); --sp-cyan-2:#1fc3d6; --sp-vital:#22e6a5;
  --sp-white:#f2f8f7; --sp-muted:#84a6a9; --sp-muted2:#557276;
  /* --sp-mono steht seit dem 18.08.2026 in :root — die Kennung braucht sie überall.
     Hier bewusst NICHT wiederholt: Eine zweite Fassung derselben Schriftliste ist genau
     die Stelle, an der später eine von beiden geändert wird und die andere nicht. */
  position:relative; max-width:none; width:100%; margin:0; padding:40px 24px; gap:0; justify-content:center;
  color:var(--sp-white); overflow:hidden;
  background:
    radial-gradient(80% 55% at 50% 34%,rgba(255,90,31,.20),transparent 60%),
    radial-gradient(70% 60% at 82% 88%,rgba(37,215,230,.14),transparent 62%),
    radial-gradient(120% 100% at 50% 30%,#0e2932 0%,var(--sp-ground) 45%,var(--sp-ground2) 100%);
}
.auth-landing #bg { position:fixed; inset:0; width:100%; height:100%; z-index:0; pointer-events:none; }
.auth-landing #bg .ecg { fill:none; stroke:rgba(34,230,165,.20); stroke-width:1.5; }
.auth-landing #bg .ecg-pulse { fill:none; stroke:var(--sp-vital); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; --L:4200; stroke-dasharray:150 var(--L); stroke-dashoffset:150; opacity:.85; filter:drop-shadow(0 0 6px rgba(34,230,165,.55)); animation:spEcgPulse 6.5s linear .8s infinite; }
.auth-landing #bg .route { fill:none; stroke:rgba(255,255,255,.10); stroke-width:2; stroke-dasharray:2 9; stroke-linecap:round; }
.auth-landing #bg .rpt { filter:drop-shadow(0 0 6px currentColor); }
.auth-landing #bg .rpt.o { color:var(--sp-orange); fill:var(--sp-orange); }
.auth-landing #bg .rpt.c { color:var(--sp-cyan); fill:var(--sp-cyan); }
.auth-landing #bg .rpt.v { color:var(--sp-vital); fill:var(--sp-vital); }
.auth-landing .sp-metrics { position:fixed; inset:0; z-index:0; pointer-events:none; font-family:var(--sp-mono); }
.auth-landing .sp-metrics .m { position:absolute; font-size:12px; font-weight:600; letter-spacing:.06em; color:var(--sp-muted); opacity:.5; font-variant-numeric:tabular-nums; white-space:nowrap; display:flex; align-items:baseline; gap:6px; }
.auth-landing .sp-metrics .m b { font-size:19px; font-weight:800; color:var(--sp-white); opacity:.7; }
.auth-landing .sp-metrics .m .u { font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--sp-muted2); }
.auth-landing .sp-metrics .m.bpm b { color:var(--sp-vital); opacity:.85; }
.auth-landing .sp-metrics .m .hb { color:var(--sp-vital); animation:spBeat 1s ease-in-out infinite; display:inline-block; }
.auth-landing .sp-metrics .m1 { top:16%; left:8%; } .auth-landing .sp-metrics .m2 { top:30%; right:9%; } .auth-landing .sp-metrics .m3 { bottom:26%; left:10%; }
.auth-landing .sp-metrics .m4 { bottom:18%; right:11%; } .auth-landing .sp-metrics .m5 { top:13%; right:24%; }
.auth-landing .login-stage-wrap { position:relative; z-index:1; display:flex; flex-direction:column; align-items:center; width:min(520px,100%); }
.auth-landing .sp-emblem { position:relative; width:min(340px,86vw); aspect-ratio:1; margin-bottom:8px; animation:spZoom 1s cubic-bezier(.2,.8,.2,1.2) .05s both; }
.auth-landing .sp-emblem-svg { position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.auth-landing .sp-emblem-svg .halo-anim { transform-box:fill-box; transform-origin:center; animation:spPulse 3.2s ease-in-out infinite; }
.auth-landing .sp-emblem-svg .route-band { fill:none; stroke:rgba(255,255,255,.05); stroke-width:24; }
.auth-landing .sp-emblem-svg .route-line { fill:none; stroke:rgba(255,138,66,.42); stroke-width:2; stroke-dasharray:2 11; stroke-linecap:round; }
.auth-landing .sp-emblem-svg .route-edge { fill:none; stroke:rgba(255,255,255,.09); stroke-width:1; }
.auth-landing .sp-emblem-svg .startm line { stroke:var(--sp-orange); stroke-width:3; stroke-linecap:round; }
.auth-landing .sp-emblem-svg .startm text { font-family:var(--sp-mono); font-size:9px; fill:var(--sp-orange-2); letter-spacing:.14em; }
.auth-landing .sp-emblem-svg .dot { filter:drop-shadow(0 0 7px currentColor); }
.auth-landing .sp-emblem-svg .dot.o { fill:var(--sp-orange); color:var(--sp-orange); }
.auth-landing .sp-emblem-svg .dot.c { fill:var(--sp-cyan); color:var(--sp-cyan); }
.auth-landing .sp-emblem-svg .dot.v { fill:var(--sp-vital); color:var(--sp-vital); }
.auth-landing .sp-emblem-svg .nm { font-family:var(--sp-mono); font-size:11px; font-weight:700; fill:#eaf6f5; letter-spacing:.02em; paint-order:stroke; stroke:rgba(4,13,16,.85); stroke-width:3px; }
.auth-landing .sp-logo { position:absolute; top:50%; left:50%; width:33%; transform:translate(-50%,-50%); filter:drop-shadow(0 8px 30px rgba(11,26,32,.85)); }
.auth-landing .sp-logo .bl { fill:none; stroke-width:7; stroke-linecap:round; stroke-linejoin:round; }
.auth-landing .sp-logo .bl.top { stroke:var(--sp-orange); } .auth-landing .sp-logo .bl.left { stroke:var(--sp-orange-2); }
.auth-landing .sp-logo .bl.right { stroke:var(--sp-cyan); } .auth-landing .sp-logo .bl.bottom { stroke:var(--sp-cyan-2); }
.auth-landing .sp-logo .fl { fill:none; stroke-width:7; stroke-linecap:round; stroke-linejoin:round; stroke-dasharray:18 92; animation:spLogoFlow 2.4s linear infinite; }
.auth-landing .sp-logo .fl.blue { stroke:#ffc39a; } .auth-landing .sp-logo .fl.teal { stroke:#9ff9ee; } .auth-landing .sp-logo .fl.delay { animation-delay:.35s; }
.auth-landing .sp-logo .nd { fill:var(--sp-orange); } .auth-landing .sp-logo .nd.dark { fill:#e04a12; } .auth-landing .sp-logo .nd.teal { fill:var(--sp-cyan); } .auth-landing .sp-logo .nd.light { fill:#5fe3ee; } .auth-landing .sp-logo .nd.bn { fill:var(--sp-orange-2); }
.auth-landing .sp-logo .core { fill:var(--sp-orange); }
.auth-landing .sp-word { display:flex; align-items:baseline; gap:.28em; line-height:1; margin-top:2px; font-weight:900; letter-spacing:-.02em; font-size:clamp(42px,9vw,70px); opacity:0; animation:spRise .7s ease .35s both; }
.auth-landing .sp-word .u { color:#fff; text-shadow:0 10px 34px rgba(6,20,24,.7); }
.auth-landing .sp-word .s { font-style:italic; text-transform:uppercase; background:linear-gradient(100deg,var(--sp-orange),var(--sp-orange-2)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; filter:drop-shadow(0 8px 22px rgba(255,90,31,.42)); }
.auth-landing .sp-tag { margin-top:16px; font-size:12.5px; font-weight:700; letter-spacing:.34em; text-transform:uppercase; color:var(--sp-muted); opacity:0; animation:spRise .7s ease .55s both; }
.auth-landing .sp-rule { margin-top:22px; width:70px; height:3px; border-radius:3px; background:linear-gradient(90deg,transparent,var(--sp-orange),var(--sp-cyan),transparent); opacity:0; animation:spRise .7s ease .7s both; }
.auth-landing .sp-elev { width:min(340px,86vw); margin-top:24px; opacity:0; animation:spRise .7s ease .85s both; }
.auth-landing .sp-elev-head { display:flex; justify-content:space-between; align-items:baseline; font-family:var(--sp-mono); font-size:10px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:var(--sp-muted2); margin-bottom:6px; }
.auth-landing .sp-elev-head .d { letter-spacing:.08em; color:var(--sp-muted); }
.auth-landing .sp-elev-svg { display:block; width:100%; height:auto; overflow:visible; }
.auth-landing .sp-elev-svg .line { fill:none; stroke:rgba(37,215,230,.55); stroke-width:1.6; stroke-linejoin:round; stroke-linecap:round; }
.auth-landing .sp-elev-svg .base { stroke:rgba(255,255,255,.12); stroke-width:1; stroke-dasharray:1 5; stroke-linecap:round; }
.auth-landing .sp-elev-svg .peak { fill:var(--sp-orange); filter:drop-shadow(0 0 5px rgba(255,90,31,.6)); }
.auth-landing .sp-elev-svg .peak-lbl { font-family:var(--sp-mono); font-size:8.5px; font-weight:700; fill:var(--sp-orange-2); letter-spacing:.06em; }
.auth-landing .sp-elev-stats { display:flex; justify-content:center; gap:18px; margin-top:9px; font-family:var(--sp-mono); font-size:11px; font-weight:600; color:var(--sp-muted); font-variant-numeric:tabular-nums; white-space:nowrap; }
.auth-landing .sp-elev-stats b { color:var(--sp-white); opacity:.85; font-weight:800; }
.auth-landing .sp-elev-stats .up .a { color:var(--sp-orange-2); }
.auth-landing .sp-elev-stats .down .a { color:var(--sp-cyan); }
.auth-landing .sp-elev-stats .u { font-size:9px; letter-spacing:.1em; text-transform:uppercase; color:var(--sp-muted2); }
@media (max-height:700px) { .auth-landing .sp-emblem { width:min(280px,86vw); } .auth-landing .sp-elev { margin-top:14px; } }
/* „Anmelden" oben rechts (orange, wie im Sports-Login) */
.auth-landing .auth-topright { position:fixed; top:20px; right:20px; left:auto; z-index:5; }
.auth-landing .auth-topbtn {
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font-size:13px; font-weight:800; letter-spacing:.02em; padding:10px 16px; border-radius:12px;
  border:1px solid transparent; color:var(--on-accent);
  background:linear-gradient(120deg,var(--sp-orange),var(--sp-orange-2));
  box-shadow:0 12px 30px rgba(255,90,31,.34); transition:.16s;
}
.auth-landing .auth-topbtn:hover { transform:translateY(-1px); box-shadow:0 18px 40px rgba(255,90,31,.46); }
.auth-landing .auth-topbtn:active { transform:scale(.97); }
.auth-landing .auth-topbtn .ic { font-size:15px; line-height:1; }
@keyframes spLogoFlow { to { stroke-dashoffset:-110; } }
@keyframes spPulse { 0%,100% { transform:scale(.94); opacity:.6; } 50% { transform:scale(1.07); opacity:.9; } }
@keyframes spBeat { 0%,100% { transform:scale(1); } 14% { transform:scale(1.35); } 28% { transform:scale(1); } 42% { transform:scale(1.18); } }
@keyframes spZoom { from { transform:scale(.6); opacity:0; } to { transform:scale(1); opacity:1; } }
@keyframes spRise { from { transform:translateY(16px); opacity:0; } to { transform:translateY(0); opacity:1; } }
@keyframes spEcgPulse { 0% { stroke-dashoffset:150; } 42% { stroke-dashoffset:calc(-1 * var(--L)); } 100% { stroke-dashoffset:calc(-1 * var(--L)); } }
@media (max-width:520px) { .auth-landing .sp-word { font-size:clamp(34px,11vw,44px); } .auth-landing .auth-topright { top:14px; right:14px; } }
@media (prefers-reduced-motion:reduce) {
  .auth-landing .sp-emblem-svg .halo-anim, .auth-landing .sp-metrics .hb, .auth-landing .sp-logo .fl, .auth-landing #bg .ecg-pulse { animation:none; }
  .auth-landing #bg .ecg-pulse { opacity:0; }
  .auth-landing .sp-word, .auth-landing .sp-tag, .auth-landing .sp-rule, .auth-landing .sp-elev, .auth-landing .sp-emblem { animation:none; opacity:1; transform:none; }
}

/* Login als Overlay-Fenster über dem Landing */
.login-modal {
  position: fixed; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; padding-top: max(20px, env(safe-area-inset-top));
  background: rgba(3, 10, 12, .74); backdrop-filter: blur(6px); animation: fade .2s;
}
.login-card {
  position: relative; width: min(420px, 100%);
  background: linear-gradient(180deg, var(--surface-2), var(--surface)); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 24px 22px 20px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .6); animation: authCardIn .28s ease;
  color: var(--text);
}
@keyframes authCardIn { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
.login-card h2 { font-size: 22px; color: var(--text); }
.login-x {
  position: absolute; top: 12px; right: 12px; width: 32px; height: 32px;
  border: 0; border-radius: 50%; background: var(--surface-3); color: var(--text-dim);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.login-x:active { transform: scale(.92); }

/* ---------- Zuschauer-Plus: Glocke, Danger Zone, Meilensteine ---------- */
/* 🔔 Synchrone Glocke: Vollbild-Moment zu jeder vollen Stunde (alle Fans gleichzeitig) */
.bell-flash {
  position: fixed; inset: 0; z-index: 300; pointer-events: none;
  display: grid; place-items: center; text-align: center;
  background: radial-gradient(90% 70% at 50% 40%, color-mix(in srgb, var(--accent) 30%, transparent) 0%, rgba(4, 8, 12, .88) 70%);
  animation: bellIn .25s ease, bellOut .8s ease 5.2s forwards;
}
.bell-flash .bf-inner { animation: bellPop .5s cubic-bezier(.2, 1.6, .4, 1); }
.bell-flash .bf-bell { font-size: 84px; line-height: 1; animation: bellSwing 1s ease 2; transform-origin: 50% 0; }
.bell-flash .bf-title { font-size: 40px; font-weight: 900; letter-spacing: 6px; margin-top: 8px; text-shadow: 0 4px 30px rgba(0,0,0,.6); }
.bell-flash .bf-sub { font-size: 18px; color: var(--text-dim); margin-top: 6px; }
.bell-flash .bf-sub b { color: var(--good); }
@keyframes bellIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes bellOut { to { opacity: 0; } }
@keyframes bellPop { from { transform: scale(.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes bellSwing { 0%,100% { transform: rotate(0); } 25% { transform: rotate(-16deg); } 75% { transform: rotate(16deg); } }

/* 🚨 Danger Zone: Läufer noch draußen, Glocke rückt näher */
.dz-card { animation: dzPulse 1.1s ease-in-out infinite; }
@keyframes dzPulse { 0%,100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--bad) 0%, transparent); } 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bad) 25%, transparent); } }

/* 🏅 Meilenstein-Chips */
.ms-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.ms-chip {
  padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 700;
  background: var(--surface-2); border: 1px solid var(--line);
}
.ms-chip:last-child { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface-2)); }

@media (prefers-reduced-motion: reduce) {
  .bell-flash, .bell-flash .bf-inner, .bell-flash .bf-bell { animation: none; }
  .dz-card { animation: none; }
}

/* ---------- Barcode-Scanner: Sucher statt „roter Strich" ----------
   Ecken-Klammern + abgedunkeltes Umfeld + wandernde Leuchtlinie in Akzentfarbe.
   Beim Treffer blitzt das Fenster grün auf (.scanbox.hit). */
.scanbox { position: relative; border-radius: 14px; overflow: hidden; background: #000; }
.scanbox video { display: block; width: 100%; aspect-ratio: 3/4; object-fit: cover; }
.scan-frame {
  position: absolute; left: 8%; right: 8%; top: 30%; bottom: 30%;
  border-radius: 14px; pointer-events: none;
  box-shadow: 0 0 0 200vmax rgba(4, 10, 14, .45); /* dunkelt alles AUSSERHALB des Fensters ab */
}
.scan-frame i {
  position: absolute; width: 26px; height: 26px;
  border: 3px solid var(--accent); pointer-events: none;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 55%, transparent));
  animation: scanPulse 2.2s ease-in-out infinite;
}
.scan-frame i:nth-child(1) { left: -2px; top: -2px;  border-right: 0; border-bottom: 0; border-top-left-radius: 12px; }
.scan-frame i:nth-child(2) { right: -2px; top: -2px; border-left: 0;  border-bottom: 0; border-top-right-radius: 12px; }
.scan-frame i:nth-child(3) { left: -2px; bottom: -2px; border-right: 0; border-top: 0; border-bottom-left-radius: 12px; }
.scan-frame i:nth-child(4) { right: -2px; bottom: -2px; border-left: 0; border-top: 0; border-bottom-right-radius: 12px; }
.scan-laser {
  position: absolute; left: 5%; right: 5%; top: 8%; height: 36px; margin-top: -18px;
  pointer-events: none; border-radius: 999px;
  background: linear-gradient(180deg, transparent,
    color-mix(in srgb, var(--accent) 28%, transparent) 42%, var(--accent) 50%,
    color-mix(in srgb, var(--accent) 28%, transparent) 58%, transparent);
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--accent) 75%, transparent));
  animation: scanSweep 2.3s cubic-bezier(.45, 0, .55, 1) infinite alternate;
}
@keyframes scanSweep { from { top: 8%; } to { top: 92%; } }
@keyframes scanPulse { 0%, 100% { opacity: .8; } 50% { opacity: 1; } }
.scan-hit {
  position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .12s;
  background: radial-gradient(circle at 50% 50%, rgba(51, 209, 122, .5), rgba(51, 209, 122, .12) 65%, transparent);
}
.scanbox.hit .scan-hit { opacity: 1; }
.scanbox.hit .scan-frame i { border-color: #33d17a; filter: drop-shadow(0 0 10px rgba(51, 209, 122, .8)); }
@media (prefers-reduced-motion: reduce) {
  .scan-laser { animation: none; top: 50%; }
  .scan-frame i { animation: none; }
}

/* ================= App-Shell (Neuaufbau Stufe 1) ================= */
/* Titel neben dem Zurück-Pfeil auf Unterseiten. */
.shell-titel {
  font-weight: 800; font-size: 16px; margin-left: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60vw;
}
/* Glocke oben rechts; der Punkt meldet Ungelesenes (kein dauerroter Tab). */
.shell-glocke { position: relative; }
.shell-glocke .punkt {
  position: absolute; top: 4px; right: 4px; width: 8px; height: 8px;
  background: var(--bad); border-radius: 50%; border: 1.5px solid var(--surface);
}
/* Ungelesene Mitteilung: ein Streifen an der Kante, keine Einfärbung der ganzen Karte.
   Die Liste ist zugleich das Protokoll schon gesehener Ausfälle — färbte man die neuen
   flächig ein, läse sich der Bildschirm wie eine Warnung statt wie eine Liste. */
.card.neu { border-left: 3px solid var(--accent); }

/* Live-Leiste: schwebt ÜBER der Tab-Leiste (Miniplayer-Muster).
   Feste Höhe + Safe-Area der Tab-Leiste einrechnen — sonst rutscht sie auf
   iPhones unter die Leiste (Safe-Area-Falle). */
.liveleiste {
  position: fixed; left: 0; right: 0; z-index: 29;
  /* ⚠ Die Höhe der Tab-Leiste stand hier als Schätzwert (`--tap + 20px`) — sie ergibt sich
     aber aus Schriftgröße, Innenabstand und Safe-Area und war dadurch zu groß: zwischen
     Live-Leiste und Fußleiste klaffte eine Lücke. `--navh` wird nach jedem Zeichnen an der
     echten Leiste gemessen (messeLeisten() in app.js); der alte Wert bleibt als Rückfall,
     falls die Messung einmal nicht läuft. */
  bottom: var(--navh, calc(var(--tap) + 20px + env(safe-area-inset-bottom)));
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; height: 56px; padding: 0 14px; border: 0;
  border-top: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 20%, var(--surface)),
    color-mix(in srgb, var(--surface) 94%, transparent));
  backdrop-filter: saturate(1.3) blur(12px); -webkit-backdrop-filter: saturate(1.3) blur(12px);
  color: var(--text); text-align: left; cursor: pointer;
}
.liveleiste .ll-links { display: flex; align-items: center; gap: 8px; min-width: 0; }
.liveleiste b { font-size: 13.5px; font-weight: 800; }
.liveleiste small { color: var(--text-mute); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.liveleiste .ll-zeit { font-size: 17px; font-weight: 800; color: var(--accent);
  font-variant-numeric: tabular-nums; flex: none; }
.liveleiste .ll-punkt {
  width: 9px; height: 9px; border-radius: 50%; background: var(--bad); flex: none;
  animation: llPuls 1.6s infinite;
}
@keyframes llPuls { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
/* Bei sichtbarer Live-Leiste braucht der Inhalt mehr Luft nach unten: Fußleiste (gemessen)
   + Höhe der Live-Leiste (56 px) + etwas Abstand. */
body.hat-liveleiste .content { padding-bottom: calc(var(--navh, 104px) + 56px + 24px); }
@media (prefers-reduced-motion: reduce) { .liveleiste .ll-punkt { animation: none; } }

/* ============================================================================
   NEUAUFBAU — Feinschliff (Stufe 6d, 02.08.2026)
   ----------------------------------------------------------------------------
   Florian: „durch die ganzen Emojis sieht das aus wie ein Kinderspielplatz."
   Antwort darauf, in drei Handgriffen:

   1. ZAHLEN sind der Held. Tabellenziffern (alle gleich breit), enge Laufweite,
      kräftiges Gewicht — so springt die Uhr beim Zählen nicht mehr hin und her,
      und ein Wert liest sich wie auf einem Messgerät statt wie Fließtext.
   2. BESCHRIFTUNGEN treten zurück: klein, Versalien, weit gesperrt, gedämpft.
      Sie sagen, was die Zahl bedeutet, und drängen sich nicht davor.
   3. FLÄCHEN statt Rahmen: eingebettete Karten tragen einen leisen Hintergrund
      statt einer harten Linie.

   Gilt nur für den Neuaufbau (Klassen mit uq-). Die alte Oberfläche bleibt
   unverändert — sie läuft für Sandys Lauf.
   ========================================================================= */

/* „läuft gerade" trägt dieselbe Fehlerfarbe wie der Rest des Hauses — eine Stelle. */
:root { --live: var(--bad); }

/* Zahlen: gleich breite Ziffern, damit nichts wackelt, während die Uhr läuft. */
.uq-zahl {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -.02em;
  font-weight: 700;
}

/* Beschriftung über oder unter einer Zahl. */
.uq-label {
  text-transform: uppercase;
  letter-spacing: .085em;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-mute);
  line-height: 1.5;
}

/* Zweite Zeile mit Zusatzangaben — kleiner, aber nicht in Versalien. */
.uq-meta { font-size: 11.5px; line-height: 1.55; }

/* Die große Uhr während der Aufzeichnung. */
.uq-uhr {
  font-size: clamp(46px, 15vw, 62px);
  font-weight: 750;
  letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  line-height: 1.05;
  margin: 6px 0 2px;
}

/* Wertkachel (Strecke, Pace, Puls …). */
.uq-kachel {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 12px 6px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

/* Wertzeile in einer eingebetteten Aktivitäts-/Lauf-Karte. Seit 19.08.2026 ein
   GLEICHMÄSSIGES Raster statt einer starren Flex-Zeile: Vier, fünf Werte plus
   „4:48:46" sprengten auf dem Handy die Breite, und die festen Lücken ließen die
   Spalten je nach Textlänge verschoben aussehen. auto-fit bricht sauber in eine
   zweite Reihe um; ⚠ minmax mit echter Untergrenze, nie bloßes 1fr
   (min-content-Falle, siehe grid-1fr-mincontent-boden). */
/* Strecke, Zeit, Höhe, Puls, Kalorien stehen in EINER Reihe (Florian, 28.08.2026:
   „bitte die daten immer in eine reihe schreiben also strecke, zeit usw").
   Vorher war es ein auto-fit-Raster: Auf dem Handy brach es bei vier oder fünf Werten
   in zwei Zeilen um, und die Karte las sich wie zwei halbe Tabellen.

   ⚠ Warum flex und nicht `grid-auto-flow: column`: Beide halten die Reihe, aber nur
   flex lässt die Spalten nach ihrem INHALT unterschiedlich breit werden. „1:36:00"
   braucht mehr Platz als „5", und gleich breite Spalten verschenken ihn an die kurze.
   ⚠ `min-width: 0` an den Kindern ist Pflicht — ohne das ist die Mindestbreite eines
   Flex-Kindes sein Inhalt, und die Reihe schiebt die Karte auseinander, statt zu teilen.
   ⚠ Die Zahl wächst mit der Fensterbreite (clamp), damit fünf Werte auf einem 375er
   nebeneinander PASSEN, ohne auf dem Rechner winzig zu werden. Gemessen: 375 px Breite,
   fünf Werte, kein Überlauf. */
.uq-werte {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 10px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}
.uq-werte > span {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}
.uq-werte .uq-zahl {
  font-size: clamp(12px, 3.4vw, 16px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Die Einheit kleiner als die Zahl: Die Zahl ist die Nachricht, „km" nur ihr Maß.
   Spart rund ein Fünftel der Breite — genau das, woran fünf Werte in einer Reihe
   auf dem Handy sonst scheitern. */
.uq-werte .uq-einheit {
  font-size: .68em;
  font-weight: 600;
  margin-left: 2px;
  opacity: .72;
}
/* Die Beschriftung darf umbrechen — „Ø TEMPO" auf zwei Zeilen ist besser als eine
   Reihe, die dafür auseinanderfliegt. */
.uq-werte .uq-label { overflow-wrap: anywhere; }

/* Anklickbare Karte im Strom: der eigene Lauf lässt sich von hier aus ändern.
   Bewegung nach Hausregel — 3 px nach oben, kräftigerer Schatten, blauer Hauch,
   0,22 s; bei „Bewegung reduzieren" bleibt alles ruhig. */
.uq-aktkarte.uq-anklickbar { cursor: pointer; transition: transform .22s ease, box-shadow .22s ease, outline-color .22s ease; outline: 1px solid transparent; }
.uq-aktkarte.uq-anklickbar:hover,
.uq-aktkarte.uq-anklickbar:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 22%, transparent);
  outline-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .uq-aktkarte.uq-anklickbar { transition: none; }
  .uq-aktkarte.uq-anklickbar:hover,
  .uq-aktkarte.uq-anklickbar:focus-visible { transform: none; }
}

/* Eingebettete Karte (geteilte Aktivität, Veranstaltung, Live-Hinweis). */
.uq-aktkarte {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--surface-2);
  border: 0;
  border-radius: var(--radius-sm);
  padding: 14px;
  margin: 0 0 10px;
  color: inherit;
  font: inherit;
}

/* Fortschritt zur nächsten Stufe. */
.uq-balken {
  height: 5px;
  border-radius: 3px;
  background: var(--surface-2);
  margin-top: 12px;
  overflow: hidden;
}
.uq-balken > div { height: 100%; background: var(--accent); border-radius: 3px; }

/* Auszeichnung. */
.uq-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  letter-spacing: .01em;
  padding: 4px 9px;
}

/* Pille und Knopf mit vorangestelltem Icon — gleicher Abstand überall. */
.uq-pill-ico, .uq-btn-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

/* Kopf der Aufzeichnen-Seite: die gewählte Sportart, groß und ruhig. */
.uq-sportkopf {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 22px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  margin-bottom: 14px;
}

/* Gruppenüberschrift im Sportarten-Katalog. */
.uq-gruppe {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 8px;
}

/* Titel eines Blattes mit Icon davor. */
.uq-sheet-titel { display: flex; align-items: center; gap: 9px; }

/* Überschrift oder Zeilenanfang mit Icon davor. Bewusst inline-flex, damit die
   Zeile daneben weiterlaufen kann (<b> mit Namen, danach <br> und Kleingedrucktes). */
.uq-kopf-ico { display: inline-flex; align-items: center; gap: 8px; }

/* Icon in einer Listenzeile (Einstellungen, Erstellen-Menü). Es ordnet die Zeile
   ein und drängt sich nicht vor den Text — deshalb gedämpft statt farbig. */
.role-choice .ico { display: inline-flex; align-items: center; justify-content: center; color: var(--text-mute); }
.role-choice .ico svg { flex: 0 0 auto; }

/* Statuspunkt „läuft gerade". Ersetzt das rote Emoji: eine Farbe aus der Palette,
   auf jedem Gerät gleich groß. Der Puls verrät, dass gerade wirklich etwas läuft. */
.uq-punkt {
  width: 9px; height: 9px; flex: 0 0 9px;
  border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 60%, transparent);
  animation: uqPuls 1.8s ease-out infinite;
}
@keyframes uqPuls {
  70%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--live) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .uq-punkt { animation: none; } }

/* Meldung: Farbe statt ❌/✓ im Text — siehe toast() in app.js. */
.toast-fehler { border-color: color-mix(in srgb, var(--bad) 60%, var(--line)); }
.toast-gut    { border-color: color-mix(in srgb, var(--good) 60%, var(--line)); }

/* Icons sollen nie an der Grundlinie kleben. */
.uq-pill-ico svg, .uq-btn-ico svg, .uq-badge svg, .uq-gruppe svg,
.uq-sheet-titel svg, .uq-kopf-ico svg { flex: 0 0 auto; }
/* Stufe und Level (02.08.2026, siehe stufen.mjs): „Stufe II · Level 42".
   Keine Rangnamen — ein Backyard-Titel würde bei Yoga nichts bedeuten, und eine
   römische Ziffer muss niemand übersetzen. Die große Zahl ist immer das Level.

   Die Karte steht NUR im eigenen Bereich („Ich"). Im Feed trägt niemand mehr eine
   Zahl neben dem Namen — ein Rang über jedem fremden Beitrag macht aus einem Feed
   eine Rangliste. */
.uq-lvl { padding: 20px 16px 16px; }

/* ⚠ KEINE Form um die Zahl — weder Ring noch Vieleck (Florian, 02.08.). Die Fähigkeiten
   sind ein Sechseck-Radar in derselben Akzentfarbe; ein zweites Vieleck daneben liest sich
   als dasselbe Ding in zwei Ausführungen. Genau diese beiden müssen aber auseinanderbleiben:
   Das Level steigt aus XP und fällt nie, das Fähigkeitsprofil ist eine Momentaufnahme und
   kann sinken. Fähigkeiten sind mehrdimensional — dafür braucht es eine Fläche mit Achsen.
   Ein Level ist eine einzige wachsende Zahl, und die trägt sich selbst. */
.uq-lvl-kopf { display: flex; align-items: flex-start; gap: 16px; }
.uq-lvl-marke { display: flex; flex-direction: column; align-items: flex-start; flex: 0 0 auto; }
.uq-lvl-marke .uq-label { line-height: 1.2; }
.uq-lvl-zahl {
  font-size: 68px;
  line-height: .86;
  font-weight: 800;
  letter-spacing: -.055em;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: var(--text);
  margin-top: 2px;
}
/* Rechte Spalte: die Stufe als Tatsache, darunter der Satz, der den Zähler erklärt. */
.uq-lvl-neben { flex: 1; min-width: 0; padding-top: 4px; }
.uq-lvl-stufe {
  display: inline-block;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
}
.uq-lvl-neben p { margin: 4px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--text-dim); }
.uq-lvl-ziel {
  margin: 2px 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
}
.uq-lvl-ziel b { color: var(--text); font-weight: 750; font-variant-numeric: tabular-nums; }

/* XP-Zeile: Beschriftung links, Zahlen rechts, darunter der Balken. Der lineare Balken
   ist die richtige Form für das Level: Er hat einen Anfang und ein Ende und läuft in eine
   Richtung — anders als das Radar, das eine Fläche aufspannt. */
.uq-xp { margin-top: 14px; }
.uq-xp-kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 11.5px;
  color: var(--text-dim);
}
.uq-xp-kopf b { color: var(--text); font-weight: 750; }
.uq-xp-balken {
  height: 9px;
  margin-top: 7px;
  border-radius: 999px;
  overflow: hidden;
  background: color-mix(in srgb, var(--bg) 70%, var(--surface-2));
  border: 1px solid var(--line);
}
.uq-xp-balken > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 72%, #fff), var(--accent));
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 45%, transparent);
  transition: width .35s ease;
}
.uq-xp-note { margin: 6px 0 0; font-size: 11.5px; color: var(--text-mute); text-align: right; }

/* Auf sehr schmalen Geräten rutscht der Erklärsatz unter die Zahl. */
@media (max-width: 339px) {
  .uq-lvl-kopf { flex-direction: column; gap: 6px; }
  .uq-lvl-neben { padding-top: 0; }
}

/* Drei Fakten in einer Reihe, durch Haarlinien getrennt statt durch Kästen. */
.uq-lvl-fakten {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 16px;
  border-top: 1px solid var(--surface-2);
  padding-top: 14px;
}
.uq-lvl-fakten > div { text-align: center; padding: 0 4px; }
.uq-lvl-fakten > div + div { border-left: 1px solid var(--surface-2); }
.uq-lvl-fakten b { display: block; font-size: 17px; font-weight: 750; letter-spacing: -.02em; }
.uq-lvl-fakten small {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text-dim);
}

/* ---------------------------------------------------------------------------
   Level je Sportart (02.08.2026) — woraus das Gesamtlevel besteht.
   Florian: „wäre aber toll wenn man jede einzelne sportart leveln kann."

   Gleiche Kurve wie gesamt, deshalb dieselbe Sprache: Level als Zahl, ein dünner
   Balken für den Weg zum nächsten. Bewusst KEINE eigene Form je Sportart — es gilt
   dieselbe Regel wie oben: Ein Level ist eine Zahl, kein Vieleck.
   --------------------------------------------------------------------------- */
.uq-sportlvl { margin-top: 16px; border-top: 1px solid var(--surface-2); padding-top: 12px; }
.uq-sportlvl-zeile {
  display: grid;
  grid-template-columns: 30px 1fr auto;
  grid-template-areas: "ico name lvl" "ico bahn rest";
  align-items: center;
  column-gap: 10px;
  row-gap: 5px;
  padding: 9px 0;
}
.uq-sportlvl-zeile + .uq-sportlvl-zeile { border-top: 1px solid var(--surface-2); }
.uq-sportlvl-ico { grid-area: ico; color: var(--text-dim); display: flex; }
.uq-sportlvl-name {
  grid-area: name;
  font-size: 13.5px;
  font-weight: 650;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.uq-sportlvl-lvl {
  grid-area: lvl;
  font-size: 12.5px;
  font-weight: 750;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.uq-sportlvl-lvl b { color: var(--text); }
.uq-sportlvl-bahn {
  grid-area: bahn;
  height: 4px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.uq-sportlvl-bahn > i { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
.uq-sportlvl-rest {
  grid-area: rest;
  font-size: 10.5px;
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Was zu keiner Disziplin gehört (Ausrichten) — steht als Fußnote, nicht als Zeile:
   Es hat kein Level, nur XP, und darf nicht wie eine Sportart aussehen. */
.uq-sportlvl-rest-note { margin: 10px 0 0; font-size: 11px; color: var(--text-mute); }

/* Aufstieg. Selten genug, um einen eigenen Bildschirm zu verdienen — die neue Zahl
   trägt ihn allein, deshalb hier ausnahmsweise sehr groß. */
.uq-auf { text-align: center; padding: 14px 4px 4px; }
.uq-auf-label {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}
.uq-auf-stufe {
  margin-top: 10px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.uq-auf-zahl {
  font-size: clamp(84px, 30vw, 118px);
  line-height: .92;
  font-weight: 800;
  letter-spacing: -.06em;
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
  color: var(--text);
}
.uq-auf-unter {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-top: 2px;
}
.uq-auf-text { margin: 16px auto 0; max-width: 30ch; font-size: 13px; line-height: 1.5; color: var(--text-dim); }

/* XP-Verlauf im eigenen Bereich — macht sichtbar, dass sich etwas bewegt. */
.uq-xplog { margin-top: 16px; border-top: 1px solid var(--surface-2); padding-top: 12px; }
.uq-xplog-zeile {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
  font-size: 12.5px;
}
.uq-xplog-zeile + .uq-xplog-zeile { border-top: 1px solid var(--surface-2); }
.uq-xplog-xp {
  flex: 0 0 auto;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  min-width: 52px;
}
.uq-xplog-grund { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uq-xplog-wann { flex: 0 0 auto; font-size: 11px; color: var(--text-mute); }

/* Level am Avatar in der Kopfleiste — auf jedem Tab sichtbar, ohne dass neben fremden
   Namen eine Zahl steht. Der Ring zeigt den Fortschritt, die Zahl das Level. */
.uq-kopf-lvl { position: relative; display: flex; align-items: center; justify-content: center; }
.uq-kopf-lvl svg { display: block; }
.uq-kopf-lvl b {
  position: absolute;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* Das eigene Bild oben rechts (27.08.2026) — an der Stelle, an der bis dahin der
   Nacht-Knopf saß. Der Level-Ring liegt darum, nicht darüber.
   ⚠ Das Bild braucht `overflow:hidden` an der INNEREN Hülle: avatarHTML liefert je
     nach Stand ein <img> oder eine Initialen-Fläche, und nur eine gemeinsame Hülle
     macht aus beidem denselben Kreis. */
.uq-kopf-ich { position: relative; display: block; }
.uq-kopf-ich svg { display: block; position: absolute; inset: 0; }
.uq-kopf-ich-bild {
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2, rgba(255,255,255,.06));
}
.uq-kopf-ich-bild .avatar {
  width: 100% !important;
  height: 100% !important;
  margin: 0;
  border-radius: 50%;
  object-fit: cover;
}
/* Der Knopf trägt sonst die Innenabstände der Icon-Knöpfe — dann säße das Bild in
   einem viel zu großen Feld und rutschte an den Rand. */
.iconbtn.kopf-ich { padding: 0; width: 34px; height: 34px; }

/* Vergleich mit den Gefolgten — nur im eigenen Bereich, nur für einen selbst. */
.uq-vgl { margin-top: 12px; }
.uq-vgl-zeile {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  grid-template-areas: "platz name lvl" "platz bahn xp";
  align-items: center;
  column-gap: 9px;
  row-gap: 5px;
  padding: 10px 0;
}
.uq-vgl-zeile + .uq-vgl-zeile { border-top: 1px solid var(--surface-2); }
.uq-vgl-platz {
  grid-area: platz;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
/* Lange Namen kürzen statt umbrechen — sonst wird die eine Zeile in der Liste doppelt
   so hoch wie alle anderen und der Vergleich verliert seine Ruhe. */
.uq-vgl-name {
  grid-area: name;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 700;
  font-size: 14px;
}
/* „du" statt einer zweiten Farbe: Die eigene Zeile soll auffindbar sein, ohne dass
   die Liste in zwei Sorten Mensch zerfällt. */
.uq-vgl-name i {
  font-style: normal;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.uq-vgl-zeile .uq-stufe-chip { grid-area: lvl; }
.uq-vgl-bahn {
  grid-area: bahn;
  height: 5px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}
.uq-vgl-bahn i { display: block; height: 100%; border-radius: 3px; background: var(--text-dim); opacity: .55; }
.uq-vgl-zeile.ist-ich .uq-vgl-bahn i { background: var(--accent); opacity: 1; }
.uq-vgl-zeile.ist-ich .uq-vgl-platz { color: var(--accent); }
.uq-vgl-xp { grid-area: xp; font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* Stufe und Level neben einem Namen — nur noch im Vergleich. */
.uq-stufe-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 7px;
  border-radius: 7px;
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
/* Römisch neben arabisch: Der Farbwechsel trennt die beiden Zahlen ohne Trennzeichen,
   das auf 11px ohnehin niemand sähe. */
.uq-stufe-chip i {
  font-style: normal;
  font-weight: 800;
  color: var(--accent);
  letter-spacing: .02em;
}
.uq-stufe-chip i::after {
  content: "·";
  margin-left: 3px;
  color: var(--text-dim);
  opacity: .6;
}
/* ================= Splitscreen-Erfassung =================
   Ein Tablet am Rundenende, ein Feld je Starter. Alles hier ist auf einen Griff im
   Gedränge ausgelegt: große Flächen, harte Zustandsfarben, keine Verzierung.
   Alle Farben laufen über die Variablen — damit trägt der Nacht-Rot-Modus mit, und
   ein Backyard läuft nun einmal durch die Nacht. */
.split-kopf {
  position: sticky; top: 0; z-index: 3;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 14px; margin-bottom: 10px;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.split-kopf .sk-mitte { text-align: center; flex: 1; }
.split-kopf .sk-rest {
  font-size: clamp(30px, 7vw, 52px); font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.split-kopf .sk-k { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .08em; }
.split-kopf .sk-v { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Die Zeilen- und Spaltenzahl setzt die Oberfläche als Variable — ein Feld, zwei
   nebeneinander, vier im Quadrat, danach 3×2, 3×3 und so fort. */
.split-raster {
  display: grid; gap: 10px;
  grid-template-columns: repeat(var(--split-spalten, 2), minmax(0, 1fr));
  grid-template-rows: repeat(var(--split-zeilen, 1), minmax(84px, 1fr));
  height: calc(100vh - 250px);
  height: calc(100dvh - 250px);
  min-height: 280px;
}
.split-feld {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 8px; width: 100%; height: 100%;
  border: 2px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2); color: var(--text);
  font-family: inherit; cursor: pointer; text-align: center;
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease, background .22s ease;
}
/* Die Startnummer sitzt als kleine Marke in der Ecke, seit der NAME das Feld trägt.
   Sie bleibt sichtbar, weil sie die eindeutige Kennung ist, wenn zwei gleich heißen. */
.split-feld .sf-bib {
  position: absolute; top: 8px; left: 10px;
  font-size: clamp(13px, 1.4vw, 19px); font-weight: 800; line-height: 1;
  color: var(--text-mute); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
/* Profilbild — oder die Initialen, wenn keines hinterlegt ist. Beides derselbe Kreis,
   damit die Felder in einer Reihe stehen, egal wer ein Bild hat.
   ⚠ Größe aus der ZEILENZAHL, nicht aus der Fensterbreite: Das Raster teilt eine feste
   Höhe unter allen Zeilen auf. Ein an vw gebundener Name wächst bei zwölf Startern
   genauso wie bei zweien — und wird dann unten abgeschnitten, weil das Feld nur noch
   ein Sechstel so hoch ist. */
.split-feld .sf-bild {
  width: clamp(26px, calc(13vh / var(--split-zeilen, 1)), 84px);
  height: clamp(26px, calc(13vh / var(--split-zeilen, 1)), 84px);
  border-radius: 50%; object-fit: cover; flex: none;
  border: 2px solid var(--line); background: var(--surface-3);
  display: grid; place-items: center;
  font-size: clamp(11px, calc(5vh / var(--split-zeilen, 1)), 30px);
  font-weight: 800; color: var(--text-dim); letter-spacing: .01em;
}
.split-feld .sf-name {
  font-size: clamp(15px, calc(8vh / var(--split-zeilen, 1)), 46px);
  font-weight: 800; color: var(--text);
  line-height: 1.1; letter-spacing: -.015em;
  /* Zwei Sicherungen gegen „unten abgehackt": Der Text bleibt einzeilig (kürzt sich
     waagerecht mit …), und er darf schrumpfen statt das Feld zu sprengen. */
  min-width: 0; max-width: 100%; flex-shrink: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.split-feld .sf-zustand { font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Anheben unter der Maus — dieselbe Bewegung wie überall im Haus: 3 px hoch,
   kräftigerer Schatten, ein Hauch Akzent am Rand. */
.split-feld:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--accent-dim); }
.split-feld:active { transform: translateY(0) scale(.985); }
.split-feld.im-ziel { background: var(--good-bg); border-color: var(--good); }
.split-feld.im-ziel .sf-zustand { color: var(--good); }
.split-feld.raus { background: transparent; opacity: .45; cursor: default; }
.split-feld.raus:hover { transform: none; box-shadow: none; border-color: var(--line); }
.split-feld.raus .sf-zustand { color: var(--bad); }
/* Quittung beim Melden: Das Feld schlägt kurz an, ein grüner Schein blüht auf und ein
   Ring läuft zum Rand. Auf einem Tablet am Rundenende ist das die einzige Bestätigung,
   die man aus dem Augenwinkel mitbekommt — der Blick ist bei den Läufern. */
.split-feld.gemeldet { animation: sfPop .42s ease; border-color: var(--good); }
.split-feld.gemeldet::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--good) 55%, transparent), transparent 70%);
  animation: sfSchein .5s ease-out forwards;
}
.split-feld.gemeldet::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  border: 3px solid var(--good);
  animation: sfRing .6s ease-out forwards;
}
@keyframes sfPop    { 0% { transform: scale(1); } 30% { transform: scale(1.05); } 100% { transform: scale(1); } }
@keyframes sfSchein { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sfRing   { 0% { opacity: .9; transform: scale(.55); } 100% { opacity: 0; transform: scale(1); } }
/* Der Rückgängig-Streifen steht dort, wo die Hand ohnehin ist: unten, über der
   Reiterleiste, und breit genug, dass man ihn im Gedränge trifft. */
.split-streifen {
  position: sticky; bottom: 8px; z-index: 4; margin-top: 10px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-radius: var(--radius);
  background: var(--surface-3); border: 1px solid var(--accent-dim);
  box-shadow: var(--shadow);
}
.split-streifen b { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) {
  .split-feld { transition: none; }
  .split-feld:hover, .split-feld:active { transform: none; }
  /* Die Quittung bleibt, sie wird nur ruhig: grüner Rand statt Anschlag und Ring.
     Ganz wegnehmen darf man sie nicht — sie ist die Rückmeldung, nicht Zierde. */
  .split-feld.gemeldet { animation: none; }
  .split-feld.gemeldet::before, .split-feld.gemeldet::after { animation: none; opacity: 0; }
}
/* Auf dem Handy tragen mehr als zwei Spalten keine treffsichere Fläche mehr. Dann
   lieber scrollen als Felder, die niemand trifft. */
@media (max-width: 520px) {
  .split-raster {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: none; grid-auto-rows: minmax(96px, auto);
    height: auto;
  }
  /* Auf dem Handy wächst die Liste nach unten statt sich die Höhe zu teilen — hier darf
     die Schrift NICHT an der Zeilenzahl hängen, sonst schrumpft sie ins Nichts, obwohl
     jede Zeile ihre vollen 96 px behält. */
  .split-feld .sf-bild { width: 40px; height: 40px; font-size: 15px; }
  .split-feld .sf-name { font-size: 20px; }
}

/* ================= Anheben unter der Maus (Hausregel) =================
   Was aussieht wie eine Karte, muss sich unter dem Zeiger auch rühren — dieselbe
   Bewegung wie beim Splitscreen-Feld weiter oben: 3 px nach oben, kräftigerer
   Schatten, ein Hauch Akzent am Rand, Übergang 0,22 s.

   Zwei Bedingungen sind Pflicht:
   • nur mit echtem Zeigegerät (hover:hover) — auf dem Touchscreen bliebe der
     angehobene Zustand nach dem Tippen kleben;
   • gar nichts davon bei „Bewegung reduzieren" (no-preference in der Abfrage).

   Es geht ausschließlich um Hover. Ohne JavaScript ist hier nichts unsichtbar —
   alle Karten stehen von Anfang an voll sichtbar da.
   ========================================================================= */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .card, .post-card, .uq-aktkarte, .uq-kachel, .stat,
  .sponsor-box, .chip-link, .role-choice {
    transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease;
  }
  .card:hover, .post-card:hover, .uq-aktkarte:hover, .uq-kachel:hover, .stat:hover,
  .sponsor-box:hover, .chip-link:hover, .role-choice:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow);
    border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
  }
  /* Randlose Kacheln tragen den Hauch als Ring — sonst wäre er nicht zu sehen. */
  .uq-aktkarte:hover, .uq-kachel:hover {
    box-shadow: var(--shadow), 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent);
  }
  /* Was schon eine eigene Choreografie hat, bleibt in Ruhe: die Anmeldekarte fährt
     beim Öffnen ein, Danger-Zone und Ausscheide-Alarm pulsieren ohnehin. */
  .auth-card:hover, .dz-card:hover, .feld-card.alarm:hover {
    transform: none; box-shadow: var(--card-shadow); border-color: var(--line);
  }
  /* Keine zwei Bewegungen übereinander: Liegt der Zeiger auf einer Kachel IN der
     Karte, hebt sich nur die Kachel — die Karte darunter hält still. */
  .card:hover:has(.stat:hover, .uq-kachel:hover, .uq-aktkarte:hover,
                  .post-card:hover, .sponsor-box:hover, .chip-link:hover) {
    transform: none; box-shadow: var(--card-shadow); border-color: var(--line);
  }
}

/* ================= Gesperrte Bedienelemente (ein Zustand für alles) =================
   Bis hierher kannte die Datei keinen Sperrzustand — app.js blendete gesperrte Knöpfe
   per Inline-Stil ab, an mehreren Stellen mit jeweils eigenen Werten. Ab hier gilt ein
   gemeinsamer Zustand, der sowohl auf das echte `disabled`-Attribut als auch auf
   `aria-disabled="true"` anspricht (Links und Kacheln kennen kein `disabled`).

   Drei Zusagen:
   • Abgeblendet heißt NICHT unsichtbar — 0,55 Deckkraft plus etwas herausgenommene
     Sättigung. Die Beschriftung bleibt zu entziffern, das Element bleibt auffindbar.
   • Kein Anheben, kein Hover-Glanz, keine Druckbewegung im gesperrten Zustand.
   • Der Zeiger sagt es mit: „nicht erlaubt".

   Der Block steht bewusst als LETZTES in der Datei: So gewinnt er in der Reihenfolge
   gegen jede vorher notierte Hover- oder Anhebe-Regel, ohne dass irgendwo eine
   künstlich hochgeschraubte Spezifität nötig wäre. Farben aus der Palette werden
   nicht angefasst — der Zustand arbeitet ausschließlich über Deckkraft und Filter.
   ==================================================================================== */
.btn:disabled,
.btn[aria-disabled="true"],
button:disabled,
button[aria-disabled="true"],
input:disabled,
select:disabled,
textarea:disabled,
.chip-link[aria-disabled="true"],
.role-choice[aria-disabled="true"],
.uq-kachel[aria-disabled="true"],
.sponsor-box[aria-disabled="true"] {
  opacity: .55;
  filter: saturate(.4);
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
  pointer-events: auto; /* der Zeiger soll den Zustand zeigen, nicht durchfallen */
}

/* Bereits vergebene Sonderrolle bleibt erhalten: der Rundenverlauf-Kopf ohne
   Aufklappinhalt ist kein „verboten", sondern schlicht nichts zum Anklicken. */
.yd-head:disabled {
  opacity: 1;
  filter: none;
  cursor: default;
}

/* (B) Kollisionsausschluss zur Karten-Anhebung aus Welle 1: Ein gesperrtes Element
   rührt sich unter der Maus nicht, weder selbst noch als Karte darum herum. */
@media (hover: hover) {
  .btn:disabled:hover,
  .btn[aria-disabled="true"]:hover,
  button:disabled:hover,
  button[aria-disabled="true"]:hover,
  .card[aria-disabled="true"]:hover,
  .post-card[aria-disabled="true"]:hover,
  .uq-aktkarte[aria-disabled="true"]:hover,
  .uq-kachel[aria-disabled="true"]:hover,
  .stat[aria-disabled="true"]:hover,
  .sponsor-box[aria-disabled="true"]:hover,
  .chip-link[aria-disabled="true"]:hover,
  .role-choice[aria-disabled="true"]:hover,
  .split-feld[aria-disabled="true"]:hover {
    transform: none;
    box-shadow: none;
    border-color: var(--line);
  }
}

/* Auch die Druckbewegung entfällt — ein gesperrter Knopf darf sich nicht
   anfühlen, als hätte er den Klick angenommen. */
.btn:disabled:active,
.btn[aria-disabled="true"]:active,
button:disabled:active,
button[aria-disabled="true"]:active {
  transform: none;
}

/* (C) Abgrenzung zur Akzentfarbe: Der aktive Knopf steht in vollem Akzent. Damit ein
   gesperrter niemals wie ein aktiver wirkt, verliert er zusätzlich zur Deckkraft die
   Akzentfläche — er tritt in den neutralen Flächenton zurück und trägt eine feine
   Kante. Die Akzentvariablen selbst bleiben unverändert. */
.btn:disabled:not(.secondary):not(.ghost),
.btn[aria-disabled="true"]:not(.secondary):not(.ghost) {
  background: var(--surface-3);
  color: var(--text); /* volle Textfarbe, weil die 0,55 Deckkraft schon abblendet */
  border: 1px solid var(--line);
}

/* ====================================================================================
   BALD VERFÜGBAR — der eine Bereich für alles, was noch nicht offen ist
   ------------------------------------------------------------------------------------
   Florian am 15.08.2026: „pack das auch unter einen bereich wo das nochmal drüber
   steht. nicht das funktionierende module immer dazwischen stehen oder andersherum."

   Die Gestaltung hat genau eine Aufgabe: auf den ersten Blick als ETWAS ANDERES lesbar
   zu sein als die Listen darüber. Deshalb liegt der Bereich auf der ruhigeren Fläche,
   seine Zeilen tragen keine Knopfkante, und rechts steht in jeder Zeile die Kappe.

   ⚠ Die Zeilen sind <div>, nicht <button> (siehe baldBereichHTML in app.js). Sie dürfen
   deshalb auch KEINE Anhebung bekommen — eine Fläche, die sich unter der Maus bewegt,
   verspricht einen Klick, den es hier nicht gibt.
   ==================================================================================== */
.bald-karte { background: var(--surface); border-style: dashed; }

.bald-zeile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--line);
  cursor: default;
}
.bald-zeile:last-of-type { border-bottom: 0; }
.bald-zeile .ico { display: inline-flex; align-items: center; justify-content: center; color: var(--text-mute); flex: 0 0 auto; }
.bald-zeile .ico svg { flex: 0 0 auto; }
.bald-txt { flex: 1; min-width: 0; }
.bald-txt .lbl { font-size: 16px; font-weight: 700; color: var(--text); }
.bald-txt small { display: block; font-weight: 500; color: var(--text-mute); font-size: 13px; }

/* Die Kappe. Klein, ruhig, ohne Signalfarbe — sie meldet keinen Fehler, sondern ein
   Datum, das noch nicht da ist. Bricht auf schmalen Geräten nicht um. */
.bald-kappe {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: var(--text-mute);
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
}

.bald-trenner { height: 1px; background: var(--line); margin: 10px 0 4px; }

/* Die Themenliste. Zugeklappt, weil sie bewusst lang ist. <details> braucht kein
   JavaScript — ohne Skript bleibt sie damit trotzdem bedienbar. */
.bald-gruppe { border-bottom: 1px solid var(--line); }
.bald-gruppe:last-child { border-bottom: 0; }
.bald-gruppe > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 4px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.bald-gruppe > summary::-webkit-details-marker { display: none; }
/* Eigenes Dreieck, damit es in beiden Browserfamilien gleich aussieht und die Farbe
   der Umgebung annimmt. */
.bald-gruppe > summary::before {
  content: "";
  flex: 0 0 auto;
  width: 0; height: 0;
  border-left: 6px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  color: var(--text-mute);
  transition: transform .18s ease;
}
.bald-gruppe[open] > summary::before { transform: rotate(90deg); }
.bald-anzahl {
  margin-left: auto;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-mute);
  background: var(--surface-3);
  border-radius: 999px;
  padding: 2px 9px;
  min-width: 24px;
  text-align: center;
}
.bald-gruppe ul { margin: 0 0 12px; padding: 0 4px 0 24px; }
.bald-gruppe li {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-mute);
  margin-bottom: 6px;
  list-style: disc;
}

@media (prefers-reduced-motion: reduce) {
  .bald-gruppe > summary::before { transition: none; }
}

/* ====================================================================================
   RENNLEITUNG — eine Zeile je Starter, sortiert nach Startnummer
   ------------------------------------------------------------------------------------
   Florian am 15.08.2026: „beim backyard muss auch der veranstalter die möglichkeit haben
   leute für nächste runden raus zu nehmen oder als im ziel angekommen markieren."

   Anders als der Splitscreen läuft diese Liste UNTEREINANDER und ist damit an keine
   Feldgröße gebunden. Getippt wird hier nicht im Dunkeln und nicht unter Zeitdruck —
   deshalb gewöhnliche Knöpfe statt Kacheln, aber mit derselben Mindesthöhe fürs Handy.
   ==================================================================================== */
.rl-zeile .rl-bib {
  font-size: 17px;
  min-width: 2.2em;
  text-align: right;
  color: var(--text);
}

/* Wer draußen ist, bleibt lesbar, tritt aber zurück — die Zeile ist Geschichte,
   kein Fehler. ⚠ Nicht ausblenden: Der Veranstalter muss sehen, wen er rausgenommen
   hat, sonst findet er den Knopf zum Zurückholen nicht wieder. */
.rl-zeile.raus { opacity: .72; }

/* Eine Reihe je Starter (Florian, 18.08.2026: „sowas bitte in eine reihe, nicht im ziel
   und rausnehmen in eine extra reihe"). Links Startnummer und Name, rechts Zustand und
   Handlungen — die Liste bleibt damit auch bei zwanzig Startern überschaubar.
   ⚠ min-width:0 an der Mitte ist Pflicht: Ohne sie wächst der Flex-Kasten mit dem Namen
   und schiebt die Knöpfe aus der Karte (dieselbe Falle wie bei 1fr im Grid). */
.rl-zeile .rl-reihe { display: flex; align-items: center; gap: 10px; }
.rl-zeile .rl-mitte { flex: 1 1 auto; min-width: 0; }
.rl-zeile .rl-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rl-zeile .rl-sub {
  font-size: 12px; color: var(--text-mute); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rl-zeile .rl-knoepfe { display: flex; gap: 6px; flex: 0 0 auto; }
.rl-zeile .badge { flex: 0 0 auto; white-space: nowrap; }

/* Auf dem Handy fallen die langen Wortteile weg, damit die Reihe eine Reihe bleibt:
   aus „Runde 3 unterwegs" wird „unterwegs", aus „Rausnehmen" wird „Raus". Der Sinn
   steht jeweils am Ende — deshalb verschwindet nur der Zusatz davor. */
/* Der Zustand steht doppelt bereit: als Marke rechts (breit) und als Wort in der
   Nebenzeile (schmal). Sichtbar ist immer genau einer von beiden. */
.rl-zustand-schmal { display: none; }
/* ⚠ Die Grenze liegt bei 700 px, nicht bei 560: Gemessen blieben dem Namen in einem
   600-px-Fenster nur 72 px, sobald eine Zeile zwei lange Knöpfe trägt (Einlauf
   zurücknehmen + Rausnehmen). Echte Tablets ab 768 px behalten die volle Beschriftung. */
@media (max-width: 700px) {
  .rl-lang { display: none; }
  .rl-zeile .badge { display: none; }
  .rl-zustand-schmal { display: inline; color: var(--text-mute); }
  .rl-zeile .rl-reihe { gap: 8px; }
  .rl-zeile .rl-bib { min-width: 1.6em; font-size: 16px; }
  .rl-zeile .pill { padding-left: 10px; padding-right: 10px; font-size: 13px; }
}

/* Kachel = Filter. Sie behält die Optik der Anzeige-Kachel; dass sie schaltet, zeigt
   der Akzentrahmen der aktiven Wahl. ⚠ Als <button> braucht sie Schrift und Farbe
   ausdrücklich zurück — sonst erbt sie die des Browsers. */
.statfilter {
  font: inherit; color: inherit; width: 100%; cursor: pointer;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.statfilter.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.statfilter:hover { border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .statfilter { transition: none; } }


/* Genug Fläche für einen Daumen — dieselbe Untergrenze wie bei den übrigen
   Bedienelementen der App. */
.rl-zeile .pill { min-height: 40px; }

/* Die beiden Handlungen tragen ihre Bedeutung in der Farbe: Werten ist die
   Alltagshandlung (Akzent), Rausnehmen greift ein (Warnton).
   ⚠ Kein Rot auf Rot und keine Vollfläche — der Warnton bleibt Kante und Schrift,
   damit ein Fehlgriff nicht wie ein bestätigter Zustand aussieht. */
.rl-zeile .pill.rl-ziel {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 700;
}
.rl-zeile .pill.rl-raus {
  border-color: var(--warn);
  color: var(--warn);
}

/* ================= Feed: Reaktionen + Nachrichten (anonym) =================
   Die Zeile unter jeder Feed-Karte. Emoji-Pills sind bewusst kompakt (die Karte
   gehört dem Inhalt), die EIGENE Reaktion nutzt den bestehenden .pill.on-Akzent. */
.uq-reaktzeile { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; }
.uq-reaktzeile .uq-reakt {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px; font-size: 13.5px; min-height: 34px;
}
.uq-reakt-emoji { font-size: 16px; line-height: 1; }

/* Emoji-Schnellwahl im Reagieren-Blatt: großzügige Tippflächen, 8 je Zeile ist
   auf schmalen Handys zu eng — deshalb automatisch umbrechendes Raster. */
.uq-emoji-gitter { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 6px; }
.uq-emoji {
  font-size: 22px; line-height: 1; padding: 9px 0; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
}
.uq-emoji:active { background: color-mix(in srgb, var(--accent) 18%, var(--surface-2)); }

/* Eine Nachricht im Verlauf: Text links, Löschen (wo erlaubt) rechts. */
.uq-km { display: flex; gap: 8px; align-items: flex-start; padding: 8px 0; border-bottom: 1px solid var(--line); }
.uq-km:last-child { border-bottom: 0; }
.uq-km .iconbtn { width: 30px; height: 30px; font-size: 14px; flex: 0 0 auto; }

/* Wer hat reagiert? Nur auf dem EIGENEN Beitrag — der Server liefert die Namen
   sonst gar nicht erst aus. */
.uq-reakt-wer { font-size: 12px; margin-top: 5px; line-height: 1.5; }

/* Beendete Veranstaltungen auf der Startseite: Kartenhülle mit tippbarem Kopf und
   Reaktionsleiste darunter (Knopf im Knopf ist nicht erlaubt — deshalb DIV + Kopf). */
.uq-erledigt {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 14px; margin-bottom: 10px;
}
.uq-erledigt-kopf {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
  color: var(--text); font-size: 15px; font-weight: 600;
}

/* Kommentare: Aktionszeile (Reaktionen, Smiley, Antworten), eingerückte Antworten
   und die aufklappbare Emoji-Schnellwahl je Kommentar. */
.uq-km-zeile { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin-top: 6px; }
.uq-km-reakt { padding: 3px 9px !important; font-size: 12.5px !important; min-height: 28px !important; }
.uq-km-antwort { margin-left: 34px; }
.uq-km-emojiwahl { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.uq-emoji-sm { font-size: 18px; padding: 5px 8px; }

/* Lauf-Karte im Feed: tippbarer Kopf (die Aktkarte selbst ist kein Knopf mehr, damit
   Werte-Raster und Karte Platz haben) und die Mini-Karte der gelaufenen Spur. */
.uq-ev-kopf {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; padding: 0; color: var(--text); font: inherit;
}
.uq-spur {
  height: 160px; border-radius: 12px; overflow: hidden; margin-top: 10px;
  background: var(--surface-2); border: 1px solid var(--line);
}

/* ================= Meilensteine (Pokal) =================
   Eine Karte mit Meilenstein hebt sich golden ab — sparsam: getönter Rand und ein
   warmer Schimmer von oben, KEINE Vollfläche (der Beitrag muss lesbar bleiben) und
   kein Blinken. Die Farbe steht hier fest statt als Theme-Variable: Gold IST die
   Aussage, sie darf nicht mit der Akzentfarbe der Veranstaltung wandern. */
.uq-meilenstein {
  border-color: color-mix(in srgb, #f5b62f 55%, var(--line));
  background:
    linear-gradient(180deg, color-mix(in srgb, #f5b62f 12%, transparent) 0%, transparent 90px),
    var(--surface);
}
.uq-meilen-zeile {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 10px; padding: 8px 10px;
  border-radius: 10px;
  background: color-mix(in srgb, #f5b62f 14%, var(--surface-2));
  border: 1px solid color-mix(in srgb, #f5b62f 35%, transparent);
  font-size: 14px; line-height: 1.35;
}
.uq-meilen-pokal { font-size: 22px; line-height: 1; flex: 0 0 auto; }


/* ------------------------------------------------- Einrichtung eines Uhren-Dienstes
   Steht im Blatt „Uhr & Dienste" unter einem Anbieter, der noch keine Zugangsdaten hat.
   Zugeklappt, weil es den Betreiber der Instanz angeht und nicht den Läufer — aber
   erreichbar, damit die Spur nicht bei „nicht eingerichtet" endet. */
.conn-einrichtung {
  margin-top: 10px;
  border-top: 1px solid var(--line, #2A3644);
  padding-top: 8px;
}
.conn-einrichtung > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--text-dim, #9AA7B4);
  /* ⚠ list-style:none allein reicht in WebKit nicht — dort sitzt der Pfeil in einem
     eigenen Pseudo-Element, das die Regel nicht kennt. */
  list-style: none;
}
.conn-einrichtung > summary::-webkit-details-marker { display: none; }
.conn-einrichtung > summary::before { content: "› "; }
.conn-einrichtung[open] > summary::before { content: "⌄ "; }
.conn-einrichtung ol {
  margin: 8px 0 10px;
  padding-left: 20px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dim, #9AA7B4);
}
.conn-einrichtung li { margin-bottom: 5px; }
/* ⚠ Kein Rot auf Rot: Die Warnung bekommt die Warnfarbe als TEXT auf dem normalen
   Kartengrund, nicht als Fläche mit farbiger Schrift darauf. */
.conn-einrichtung .conn-warnung {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--warn, #F2B01E);
  margin: 6px 0 0;
}
/* ⚠ width:auto ist Pflicht — .btn bringt width:100% mit (dieselbe Falle wie beim
   Teamnote-Knopf), und der Link stünde sonst über die volle Blattbreite. */
.conn-einrichtung .btn { width: auto; display: inline-block; }

/* Die angesprungene Einheit im selbst gebauten Plan (31.08.2026)
   ---------------------------------------------------------------------------
   Gegenstück zu `.tr-einheit.hervor` im Trainerplan: Der Sprung aus dem
   Tagebuch hebt genau die Zeile hervor, um die es ging. Ohne Bewegung — sie
   steht, während gelesen wird. */
.check.uq-hervor {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface-2));
}
