/* Athlet-Monitoring — Stylesheet.
   Verbindliche Quelle: DESIGN.md. Haltung: Praezisionswerkzeug.
   Dunkelmodus ist die gestaltete Variante, hell gleichwertig gepflegt. */

/* --- Schriften ----------------------------------------------------------
   Selbst ausgeliefert, nicht vom CDN: die Datenschutzerklaerung sagt zu,
   dass keine externen Dienste eingebunden sind, und die CSP erlaubt
   font-src 'self'. Variable Fonts, damit alle Schnitte in je einer Datei
   stecken (zusammen 114 KB). SIL OFL 1.1, Lizenz in fonts/. */

@font-face {
  font-family: "Geist";
  src: url("fonts/Geist-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  /* swap: lieber sofort in der Fallback-Schrift lesen als auf die
     Webschrift warten - am Wurfring zaehlt die erste Sekunde. */
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("fonts/GeistMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --- Gestaltungsmarken --------------------------------------------------
   Hell zuerst definiert, damit jede Variable einen Wert hat; der
   Dunkelmodus ueberschreibt nur die Farben. */

:root {
  color-scheme: light dark;

  /* Flaechen */
  --page: #f7f8f9;
  --surface: #ffffff;
  --surface-2: #f1f3f5;
  --border: #dfe3e7;
  --border-strong: #c7cfd6;

  /* Text */
  --text: #11151a;
  --text-muted: #5b6672;
  --text-faint: #8b96a3;

  /* Akzent */
  --accent: #0f766e;
  --accent-deep: #115e59;
  --accent-wash: #f0fdfa;
  --accent-contrast: #ffffff;

  /* Status - fest, nie thematisiert */
  --good: #0ca30c;
  --warning: #fab219;
  --serious: #ec835a;
  --critical: #d03b3b;

  /* Diagramme */
  --chart-accent: var(--accent);
  --chart-context: #8b96a3;
  --chart-grid: #e8ebee;
  --chart-axis: #c7cfd6;

  /* Abstaende: Basis 4px, nur Vielfache */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s6: 24px; --s8: 32px; --s12: 48px; --s16: 64px;

  --radius: 8px;
  --radius-sm: 6px;
  --maxw: 72rem;

  --font: "Geist", ui-sans-serif, system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Bewegung */
  --t-micro: 120ms;
  --t-state: 180ms;
  --t-enter: 240ms;
  --ease: cubic-bezier(.2, .8, .2, 1);

  --shadow: 0 1px 2px rgba(17, 21, 26, .05), 0 4px 12px rgba(17, 21, 26, .06);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}

@media (prefers-color-scheme: dark) {
  :root {
    --page: #0b0d0f;
    --surface: #14171a;
    --surface-2: #1c2024;
    --border: #262b31;
    --border-strong: #343b43;

    --text: #e9edf2;
    --text-muted: #8b96a3;
    --text-faint: #5b6672;

    --accent: #2dd4a7;
    --accent-deep: #5ee9bd;
    --accent-wash: #10312a;
    --accent-contrast: #06201a;

    --chart-grid: #222830;
    --chart-axis: #343b43;

    /* Schatten sind auf dunklem Grund unsichtbar - Rahmen traegt die
       Erhoehung stattdessen. */
    --shadow: 0 0 0 1px var(--border-strong);
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* Spalte ueber die volle Fensterhoehe: ohne sie steht die Fusszeile auf
   kurzen Seiten mitten im Bild und darunter liegt leere Flaeche. 100dvh
   statt 100vh, weil die Leiste mobiler Browser sonst 100vh ueberschaetzt. */
body {
  margin: 0;
  min-height: 100vh;      /* Rueckfall fuer aeltere Browser */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--page);
  color: var(--text);
  font-family: var(--font);
  font-size: 0.95rem;
  line-height: 1.55;
  font-feature-settings: "ss01";
  -webkit-font-smoothing: antialiased;
  /* Deutsche Komposita ("Belastungsuebersicht") sind laenger als eine
     schmale Spalte. Umbrechen statt ueber den Rand schieben. */
  overflow-wrap: break-word;
}

/* --- Typografie --------------------------------------------------------- */

h1, h2, h3, h4 { margin: 0 0 var(--s2); line-height: 1.2; hyphens: auto; }
h1 { font-size: 1.75rem; font-weight: 650; letter-spacing: -0.025em; }
h2 { font-size: 1.15rem; font-weight: 600; letter-spacing: -0.015em; margin-top: var(--s8); }
h3 { font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em; margin-top: var(--s6); }
h4 { font-size: 0.9rem; font-weight: 600; }

p { margin: 0 0 var(--s3); }
.lede { color: var(--text-muted); margin-top: 0; }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.hint { font-size: 0.8rem; color: var(--text-muted); margin: var(--s1) 0 0; }

/* Die Monospace-Regel: JEDER Messwert. Siehe DESIGN.md. */
.num, td.num, th.num, .stat__value, .chart__endlabel {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--t-micro) ease-out;
}
a:visited { color: var(--accent); }
/* Hover nur, wo es einen Zeiger gibt: auf dem Telefon bleibt ein :hover
   nach dem Tippen kleben. Gilt fuer alle :hover-Regeln dieses Stylesheets. */
@media (hover: hover) {
  a:hover { color: var(--accent-deep); text-decoration-thickness: 2px; }
}

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- Grundgeruest ------------------------------------------------------- */

/* Deckende Flaeche, KEIN backdrop-filter: der erzeugt einen neuen
   Bezugsrahmen fuer position:fixed (wie transform), und die mobile
   Navigation unten im Fenster haengt dann an der Kopfzeile statt am
   Fenster. Nebeneffekt: spart GPU-Last auf aelteren Telefonen. */
.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
  flex: none;
}

/* Raender mit Safe-Area: viewport-fit=cover (base.html) laesst die Seite
   im Querformat sonst unter Notch und Kamerainsel laufen. */
.site-header__inner,
main,
.site-footer__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline:
    max(var(--s4), env(safe-area-inset-left))
    max(var(--s4), env(safe-area-inset-right));
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: 56px;
}

/* Zu Hause traegt die ganze Marke den Akzent - Striche UND Wort. Das ist
   die eine Stelle, an der Farbe nicht Status bedeutet, sondern Ort. */
.brand, .brand:visited {
  font-weight: 650;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  margin-right: auto;
  /* Nicht umbrechen: zweizeilig gesetzt sprengt die Marke die Kopfzeile. */
  white-space: nowrap;
  transition: color var(--t-state) var(--ease);
}
@media (hover: hover) {
  .brand:hover { color: var(--accent-deep); }
}

/* Marke als kleines Ziel statt Bildmarke: zwei Striche wie eine
   Messskala - passt zur Haltung und kostet kein Bild. */
.brand::before {
  content: "";
  width: 3px;
  height: 18px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: 6px 0 0 -1px var(--accent-deep);
  margin-right: 5px;
  transition:
    transform var(--t-state) var(--ease),
    background var(--t-state) var(--ease),
    box-shadow var(--t-state) var(--ease);
}
@media (hover: hover) {
  .brand:hover::before { transform: scaleY(1.25); }
}

/* Abseits der Startseite verliert die Marke ihre Farbe und bekommt sie
   beim Ueberfahren zurueck. Das ist der Hinweis "hier geht es zurueck",
   seit es keinen Punkt "Start" in der Navigation mehr gibt.

   Nicht hart #fff, sondern die Textfarbe: im Dunkelmodus ist das ein
   gebrochenes Weiss, im hellen ein fast schwarzer Strich. Ein weisser
   Strich auf weisser Kopfzeile waere unsichtbar - entfaerbt soll die
   Marke sein, nicht verschwunden. */
.brand--away, .brand--away:visited { color: var(--text); }
@media (hover: hover) {
  .brand--away:hover { color: var(--accent); }
}

.brand--away::before {
  background: var(--text);
  box-shadow: 6px 0 0 -1px var(--text-muted);
}
@media (hover: hover) {
  .brand--away:hover::before {
    background: var(--accent);
    box-shadow: 6px 0 0 -1px var(--accent-deep);
  }
}

nav.main-nav { display: flex; gap: var(--s1); min-width: 0; }

nav.main-nav a, nav.main-nav a:visited {
  color: var(--text-muted);
  text-decoration: none;
  padding: var(--s2) var(--s3);
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 500;
  position: relative;
  transition: color var(--t-micro) ease-out, background var(--t-micro) ease-out;
}

@media (hover: hover) {
  nav.main-nav a:hover { color: var(--text); background: var(--surface-2); }
}

nav.main-nav a[aria-current="page"] { color: var(--text); }

/* Markierung der aktiven Seite: waechst aus der Mitte, statt zu erscheinen. */
nav.main-nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: var(--s3);
  right: var(--s3);
  bottom: 2px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  animation: grow-x var(--t-state) var(--ease);
}

@keyframes grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* flex: 1 schiebt die Fusszeile an den unteren Rand, auch wenn der Inhalt
   kurz ist. min-width: 0 verhindert, dass eine breite Tabelle das
   Flex-Element aufblaeht und damit die ganze Seite quer scrollen laesst. */
main { padding-block: var(--s6) var(--s16); flex: 1 0 auto; min-width: 0; }

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  font-size: 0.82rem;
  color: var(--text-muted);
  flex: none;
}
/* Mittig - die eine Ausnahme vom linksbuendigen Layout (DESIGN.md): die
   Fusszeile traegt keinen Inhalt, nur Pflichtlinks, und steht dort, wo man
   sie von anderen Seiten kennt. */
.site-footer__inner { padding-block: var(--s4); text-align: center; }
.site-footer a, .site-footer a:visited { color: var(--text-muted); }
@media (hover: hover) {
  .site-footer a:hover { color: var(--text); }
}

/* --- Mobile Navigation --------------------------------------------------
   Unter 60rem wandert die Navigation in eine feste Leiste am unteren Rand:
   dort ist sie mit dem Daumen erreichbar, waehrend man am Ring steht.

   Warum 60rem und nicht 48rem: ein Leader sieht sieben Navigationspunkte,
   dazu Marke, Konto und Abmelden. Das braucht rund 830 px. Zwischen 768 px
   (48rem) und 830 px stand die Leiste deshalb ueber den Fensterrand hinaus
   - die ganze Seite liess sich quer schieben und "Abmelden" war
   abgeschnitten. 60rem (960 px) hat Luft, auch wenn die Schrift groesser
   gestellt ist. */

.nav-toggle { display: none; }

@media (max-width: 60rem) {
  .site-header__inner { min-height: 52px; }

  nav.main-nav {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    background: var(--surface);
    border-top: 1px solid var(--border);
    box-shadow: 0 -1px 12px rgba(0, 0, 0, .06);
    padding:
      var(--s2)
      max(var(--s2), env(safe-area-inset-right))
      max(var(--s2), env(safe-area-inset-bottom))
      max(var(--s2), env(safe-area-inset-left));
    gap: 0;
    justify-content: space-around;
  }

  /* Alle Punkte gleich breit (flex-basis 0), damit sie unabhaengig von der
     Wortlaenge ein gleichmaessiges Raster bilden. Nie umbrechen.

     Die Schrift schrumpfte frueher mit der Fensterbreite bis auf 9 px, weil
     ein Leader sieben Punkte hatte. Heute sind es hoechstens drei (Athlet)
     bzw. zwei (Trainer) - feste 13 px passen auch auf 320 px und sind
     draussen auf Armlaenge lesbar. */
  nav.main-nav a {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    font-size: 0.8125rem;
    white-space: nowrap;
    padding: var(--s2) 2px;
    min-height: 44px;             /* Touch-Ziel, siehe DESIGN.md */
    display: flex;
    align-items: center;
    justify-content: center;
  }

  nav.main-nav a[aria-current="page"]::after {
    left: 25%; right: 25%; top: 2px; bottom: auto;
  }

  /* Platz fuer die Leiste traegt die Fusszeile, nicht main: sie ist das
     letzte Element der Seite und lag sonst vollstaendig unter der Leiste -
     Impressum und Datenschutz waren am Telefon nicht antippbar. Die Hoehe
     ist die der Leiste: 8 px oben, 44 px Ziel, unten mindestens 8 px oder
     die Safe-Area, dazu 1 px Rand. */
  .site-footer {
    padding-bottom: calc(53px + max(var(--s2), env(safe-area-inset-bottom)));
  }
}

/* --- Reiter einer Athletenseite -----------------------------------------
   Zweite Navigationsebene. Sie sieht bewusst anders aus als die
   Hauptnavigation: eine Linie unter der Reihe traegt die Auswahl, damit
   klar bleibt, dass diese Reiter zu EINEM Athleten gehoeren und nicht zur
   ganzen Anwendung. */

.crumb { font-size: 0.8rem; margin: 0 0 var(--s1); }
.crumb a, .crumb a:visited { color: var(--text-muted); text-decoration: none; }
@media (hover: hover) {
  .crumb a:hover { color: var(--text); text-decoration: underline; }
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1);
  margin: var(--s4) 0 var(--s6);
  border-bottom: 1px solid var(--border);
}

.tabs a, .tabs a:visited {
  position: relative;
  padding: var(--s2) var(--s3);
  min-height: 44px;              /* Touch-Ziel, siehe DESIGN.md */
  display: inline-flex;
  align-items: center;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 550;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transition: color var(--t-micro) ease-out, background var(--t-micro) ease-out;
}

@media (hover: hover) {
  .tabs a:hover { color: var(--text); background: var(--surface-2); }
}
.tabs a[aria-current="page"] { color: var(--text); }

/* Die Markierung liegt auf der Trennlinie, nicht darueber - sonst springt
   die Zeile beim Wechsel um einen Pixel. */
.tabs a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: var(--s2);
  right: var(--s2);
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
  animation: grow-x var(--t-state) var(--ease);
}

@media (max-width: 30rem) {
  .tabs { gap: 0; }
  .tabs a { flex: 1 1 0; justify-content: center; padding-inline: var(--s1); font-size: 0.82rem; }
}

/* --- Flaechen ----------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s4) var(--s4);
}

/* Abstand zwischen untereinander stehenden Karten. Im Raster steht der
   Abstand im gap - dort hat der Rand die zweite und jede weitere Karte
   um 16 px nach unten geschoben und sie genau um diese 16 px kuerzer
   gemacht als ihre Nachbarin. Deshalb hier zuruecknehmen. */
.card + .card { margin-top: var(--s4); }
.grid > .card + .card { margin-top: 0; }

/* Kartenraster. Alle Spalten sind gleich breit; minmax(.., 1fr) mit
   min-width 0 verhindert, dass ein langes Wort eine Spalte aufblaeht und
   die Nachbarn schmaler macht. */
.grid {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
}

/* Karten einer Reihe sind gleich hoch (Grid streckt sie). Damit auch die
   Knoepfe auf einer Linie stehen und nicht je nach Textlaenge wandern,
   wird die Karte selbst zur Spalte und das letzte Element nach unten
   geschoben. */
.grid > .card { display: flex; flex-direction: column; }
.grid > .card > .actions,
.grid > .card > .btn { margin-top: auto; }
.grid > .card > .btn { align-self: flex-start; }

/* Formularraster. Bewusst NICHT 1fr: ein Datums- oder Auswahlfeld, das
   ueber 500 px breit ist, sieht aus wie ein Fehler und macht dieselbe
   Eingabe auf jeder Seite unterschiedlich gross. Die Spalten wachsen bis
   22rem und bleiben dann stehen - linksbuendig, wie das Layout insgesamt. */
.form-grid {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 20rem));
  justify-content: start;
  align-items: start;
}

/* Beschreibungen und Notizen duerfen ueber die ganze Breite laufen. */
.field--wide { grid-column: 1 / -1; max-width: 46rem; }

.stack > * + * { margin-top: var(--s4); }

.auth-shell { max-width: 25rem; margin: var(--s12) auto; }

/* Gestaffelter Eintritt. Hoechstens sechs Elemente, danach ohne Versatz -
   sonst wartet man auf die Seite statt sie zu lesen. */
@media (prefers-reduced-motion: no-preference) {
  .card, .stat {
    animation: rise var(--t-enter) var(--ease) both;
  }
  .grid > :nth-child(2), .stats > :nth-child(2) { animation-delay: 30ms; }
  .grid > :nth-child(3), .stats > :nth-child(3) { animation-delay: 60ms; }
  .grid > :nth-child(4), .stats > :nth-child(4) { animation-delay: 90ms; }
  .grid > :nth-child(5), .stats > :nth-child(5) { animation-delay: 120ms; }
  .grid > :nth-child(n+6), .stats > :nth-child(n+6) { animation-delay: 150ms; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* --- Knoepfe ------------------------------------------------------------ */

button, .btn {
  font: inherit;
  font-weight: 550;
  font-size: 0.9rem;
  line-height: 1.2;
  padding: var(--s3) var(--s4);
  min-height: 40px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--accent-contrast);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  transition:
    transform var(--t-micro) var(--ease),
    filter var(--t-micro) ease-out,
    box-shadow var(--t-micro) ease-out,
    background var(--t-micro) ease-out;
}

.btn:visited { color: var(--accent-contrast); }
@media (hover: hover) {
  button:hover, .btn:hover { filter: brightness(1.06); box-shadow: var(--shadow); }
}
/* Sinkt beim Druecken: die einzige Rueckmeldung, die vor dem Serverantwort kommt. */
button:active, .btn:active { transform: translateY(1px) scale(.985); filter: none; }

button:disabled, .btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}

.btn--secondary, button.btn--secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-strong);
}
.btn--secondary:visited { color: var(--text); }
@media (hover: hover) {
  .btn--secondary:hover { background: var(--surface-2); filter: none; }
}

.btn--danger, button.btn--danger {
  background: var(--critical);
  border-color: var(--critical);
  color: #fff;
}

.btn--small, button.btn--small {
  padding: var(--s1) var(--s3);
  min-height: 32px;
  font-size: 0.82rem;
}

.btn--block { width: 100%; }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
}

/* Eine Reihe, in der Eingabefeld und Knopf nebeneinander stehen (der
   Plan-Baukasten), bekommt eine einheitliche Hoehe. Vorher stand ein
   48 px hohes Feld neben einem 32 px hohen Knopf; die Reihe sah aus, als
   waere sie aus zwei Formularen zusammengesetzt. Der :has()-Test grenzt
   das auf echte Eingabereihen ein - Knopfreihen in Tabellen bleiben
   kompakt. */
.actions:has(input:not([type="hidden"]), select, textarea) > :where(input, select, button, .btn) {
  min-height: 44px;
}
/* Der Knopf nimmt die Hoehe der Reihe an, statt 7 px kleiner zu bleiben
   als das Feld daneben. */
.actions:has(input:not([type="hidden"]), select, textarea) > :where(button, .btn) {
  align-self: stretch;
}

/* --- Formulare ----------------------------------------------------------
   Grosszuegige Dichte: diese Felder werden mit kalten Fingern bedient. */

form .field { margin-bottom: var(--s4); }

label {
  display: block;
  font-size: 0.82rem;
  font-weight: 550;
  letter-spacing: 0.01em;
  color: var(--text);
  margin-bottom: var(--s1);
}

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], input[type="file"],
select, textarea {
  width: 100%;
  min-height: 48px;              /* Touch-Ziel */
  padding: var(--s3);
  font: inherit;
  font-size: 1rem;               /* unter 16px zoomt iOS beim Fokus hinein */
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  transition:
    border-color var(--t-micro) ease-out,
    box-shadow var(--t-state) var(--ease),
    background var(--t-micro) ease-out;
}

/* Zahlenfelder in Monospace - was gemessen wird, steht in Mono. */
input[type="number"],
input[inputmode="decimal"] {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* Die Feldbreite folgt dem Inhalt, nicht dem Container. Ein RPE-Wert von
   1 bis 10 in einem 1100 px breiten Kasten war der auffaelligste Fall von
   "alles verschieden gross": dieselbe Eingabe sah auf jeder Seite anders
   aus, je nachdem wie viele Nachbarn im Raster standen. Gilt nur fuer
   Felder in einem .field - Tabellenfelder regeln ihre Breite ueber die
   Spalte. */
/* Text, E-Mail, Passwort und Auswahl: eine Breite, dieselbe wie eine
   Spalte im Formularraster. Sonst ist dasselbe Feld einmal 320 px und
   einmal so breit wie die Karte, je nachdem ob ein zweites daneben
   steht. */
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="file"],
.field select { max-width: 20rem; }

/* Danach die Masse, denn ein Komma-Feld ist ein text-Feld mit
   inputmode="decimal": gleiche Spezifitaet, also entscheidet die
   Reihenfolge. Steht es oben, ist die Schlafdauer doppelt so breit wie
   der Ruhepuls daneben. */
.field input[type="date"] { max-width: 12rem; }
.field input[type="number"],
.field input[inputmode="decimal"] { max-width: 10rem; }

/* Ausnahme: in der schmalen Anmeldekarte fuellt das Feld die Karte - dort
   gibt die Karte das Mass vor. */
.auth-shell .field input,
.auth-shell .field select { max-width: 100%; }
/* Notizen und Beschreibungen: breit, aber nicht endlos - ueber 46rem
   wird eine Zeile zu lang zum Lesen. */
.field textarea { max-width: 46rem; }

@media (hover: hover) {
  input:hover, select:hover, textarea:hover { border-color: var(--text-faint); }
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}

input[readonly] {
  background: var(--surface-2);
  color: var(--text-muted);
  border-style: dashed;
}

textarea { min-height: 88px; resize: vertical; line-height: 1.5; }

select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 18px center, right 13px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: var(--s8);
}

.checkbox {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s3);
  align-items: start;
  padding: var(--s3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  transition: border-color var(--t-micro) ease-out;
}
.checkbox:has(input:checked) { border-color: var(--accent); background: var(--accent-wash); }
.checkbox input { width: 20px; height: 20px; margin-top: 2px; accent-color: var(--accent); }
.checkbox label { font-weight: 400; font-size: 0.88rem; margin: 0; line-height: 1.45; }

/* --- Meldungen ----------------------------------------------------------- */

.alert {
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-faint);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s4);
  background: var(--surface);
  font-size: 0.9rem;
}

/* Fehlermeldungen werden NICHT animiert - wer sie sucht, will sie sofort. */
.alert--error { border-left-color: var(--critical); }
.alert--ok { border-left-color: var(--good); }
.alert--warn { border-left-color: var(--warning); }

/* --- Tabellen ------------------------------------------------------------
   Dichte Variante fuer Trainerlisten. Unter 48rem werden sie zu Karten,
   siehe weiter unten - eine 9-spaltige Tabelle ist auf dem Handy nichts. */

/* Scrollt waagerecht, solange die Tabelle breiter ist als die Karte. Der
   negative Aussenabstand laesst den Scrollbereich bis an die Kartenkante
   laufen, damit nicht mitten im Inhalt abgeschnitten wird. */
.table-wrap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  margin-inline: calc(var(--s4) * -1);
  padding-inline: var(--s4);
}

table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }

th, td {
  text-align: left;
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

thead th {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* muted, nicht faint: faint erreicht nur 3:1 - fuer 11 px kleine
     Spaltenkoepfe zu wenig, in der Sonne am Platz gar nicht lesbar. */
  color: var(--text-muted);
  padding-bottom: var(--s2);
  white-space: nowrap;
}

td.num, th.num { text-align: right; }
td.nowrap, th.nowrap { white-space: nowrap; }

tbody tr { transition: background var(--t-micro) ease-out; }
@media (hover: hover) {
  tbody tr:hover { background: var(--surface-2); }
}
tbody tr:last-child td { border-bottom: 0; }

/* --- Abzeichen und Status ------------------------------------------------ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 2px var(--s2);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  border: 1px solid var(--border);
  white-space: nowrap;
}

.badge--ok { color: var(--good); border-color: color-mix(in srgb, var(--good) 35%, var(--border)); }
.badge--warn { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 35%, var(--border)); }
.badge--danger { color: var(--critical); border-color: color-mix(in srgb, var(--critical) 35%, var(--border)); }

/* Statusfarbe tritt nie allein auf: Punkt plus Zahl plus Wort. */
.status-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  margin-right: var(--s1);
  flex: none;
}
.status-dot--good { background: var(--good); }
.status-dot--warning { background: var(--warning); }
.status-dot--serious { background: var(--serious); }
.status-dot--critical { background: var(--critical); }
.status-dot--neutral { background: var(--text-faint); }

/* Der kritische Punkt pulsiert einmal beim Eintreffen - einmal, nicht dauernd. */
@media (prefers-reduced-motion: no-preference) {
  .status-dot--critical { animation: pulse-once 1.2s var(--ease) 1; }
}
@keyframes pulse-once {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  30% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--critical) 30%, transparent); }
}

/* --- Kennzahlen ---------------------------------------------------------- */

.stats {
  display: grid;
  gap: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}

.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  transition: border-color var(--t-state) var(--ease);
}
@media (hover: hover) {
  .stat:hover { border-color: var(--border-strong); }
}

.stat__label {
  font-size: 0.75rem;
  font-weight: 550;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  margin: 0 0 var(--s1);
}

.stat__value {
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: var(--s1);
}

.stat__unit { font-size: 0.9rem; font-weight: 500; color: var(--text-muted); font-family: var(--font); }
.stat__hint { font-size: 0.75rem; color: var(--text-muted); margin: var(--s1) 0 0; }

/* --- Diagramme ----------------------------------------------------------- */

/* Das SVG hat ein viewBox von 720x200 und keine feste Hoehe. Bekommt es
   eine andere Form als dieses Verhaeltnis, verzerrt der Browser den
   Inhalt: vorher war das Diagramm 200 px hoch und so breit wie die Karte,
   also auf dem Bildschirm 1,5-fach in die Breite gezogen und auf dem
   Telefon auf die halbe Breite gequetscht - sichtbar an den Zahlen der
   Achsen und an unterschiedlich dicken Gitterlinien.

   aspect-ratio haelt die Flaeche in derselben Form wie das viewBox. Der
   Inhalt wird damit gleichmaessig skaliert, nie gestaucht. Wer hier ein
   Diagramm mit anderem viewBox einhaengt, muss das Verhaeltnis mitgeben. */
.chart {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 720 / 200;
  overflow: visible;
}

/* Gleichmaessig skaliert heisst auch: die Schrift im Diagramm waechst und
   schrumpft mit. --chart-scale ist der ungefaehre Massstab je Groessen-
   bereich (Diagrammbreite / 720). Alles, was auf dem Bildschirm eine feste
   Groesse haben soll, wird damit gegengerechnet. */
:root { --chart-scale: 1; }
@media (min-width: 72rem) { .chart { --chart-scale: 1.5; } }
@media (max-width: 72rem) { .chart { --chart-scale: 1.2; } }
@media (max-width: 48rem) { .chart { --chart-scale: 0.8; } }
@media (max-width: 34rem) { .chart { --chart-scale: 0.5; } }

.chart__line {
  fill: none;
  stroke: var(--chart-accent);
  /* Alle Masse im Diagramm gegen den Massstab gerechnet, damit die Linie
     auf jedem Bildschirm gleich dick aussieht. */
  stroke-width: calc(2px / var(--chart-scale, 1));
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Die Linie zeichnet sich selbst. Reines SVG und CSS, kein JavaScript.
   pathLength="1" im Markup macht die Laenge unabhaengig von den Daten,
   sonst muesste man sie je Diagramm ausrechnen. */
@media (prefers-reduced-motion: no-preference) {
  .chart__line {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: draw 900ms ease-out forwards;
  }
  .chart__dot { animation: dot-in var(--t-enter) var(--ease) 800ms both; }
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes dot-in { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: none; } }

.chart__context {
  fill: none;
  stroke: var(--chart-context);
  stroke-width: calc(2px / var(--chart-scale, 1));
  stroke-linejoin: round;
  stroke-linecap: round;
  stroke-dasharray: calc(4px / var(--chart-scale, 1)) calc(4px / var(--chart-scale, 1));
}

.chart__bar { fill: var(--chart-accent); }

.chart__dot {
  fill: var(--chart-accent);
  stroke: var(--surface);
  stroke-width: calc(2px / var(--chart-scale, 1));
  transform-box: fill-box;
  transform-origin: center;
}
/* r als CSS-Eigenschaft: der Marker behaelt seine Groesse, auch wenn das
   Diagramm skaliert. Das r-Attribut im Markup bleibt als Rueckfall. Die
   stillen Punkte behalten ihren grossen Radius - sie sind die Ziele fuer
   den Tooltip, nicht sichtbar. */
.chart .chart__dot:not(.chart__dot--quiet) { r: calc(4px / var(--chart-scale, 1)); }
.chart__dot--quiet { fill: transparent; stroke: none; animation: none; }

.chart__grid { stroke: var(--chart-grid); stroke-width: calc(1px / var(--chart-scale, 1)); }
.chart__axis { stroke: var(--chart-axis); stroke-width: calc(1px / var(--chart-scale, 1)); }

/* Text traegt nie die Datenfarbe. */
.chart__tick, .chart__legend, .chart__empty {
  fill: var(--text-faint);
  font-size: calc(11px / var(--chart-scale, 1));
  font-family: var(--font);
}
.chart__endlabel {
  fill: var(--text);
  font-size: calc(12px / var(--chart-scale, 1));
  font-weight: 600;
  font-family: var(--mono);
}
.chart__empty { font-size: calc(13px / var(--chart-scale, 1)); }

.sparkline { display: block; }
.sparkline .chart__dot { stroke: none; }
.sparkline .chart__line { stroke-width: 1.5; }

.figure { margin: 0; }
.figure__caption { font-size: 0.8rem; color: var(--text-muted); margin-top: var(--s2); line-height: 1.5; }

/* --- HTMX ----------------------------------------------------------------
   Weicher Wechsel statt Sprung, damit man sieht WAS sich geaendert hat. */

.htmx-swapping { opacity: 0; transition: opacity var(--t-micro) ease-out; }
.htmx-settling { animation: rise var(--t-state) var(--ease); }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-indicator { opacity: 0; transition: opacity var(--t-micro) ease-out; }

/* --- Tabelle wird auf dem Handy zur Karte --------------------------------
   Eine neunspaltige Trainertabelle ist auf 390px Breite unbenutzbar.
   Die Kopfzeile wandert per data-label in die Zelle. Das Markup bleibt
   eine Tabelle - Screenreader und Sortierung funktionieren weiter. */

@media (max-width: 60rem) {
  /* Nur Tabellen, die hier zu Karten werden, geben das Scrollen auf.
     Vorher galt die Regel fuer JEDEN .table-wrap - die Tabellen ohne
     .cards (Plan-Dateien, Zuweisungen, Versuchsliste) liefen dann ohne
     Scrollbereich ueber den Fensterrand hinaus. */
  .table-wrap:has(> table.cards) { overflow-x: visible; margin-inline: 0; padding-inline: 0; }

  table.cards, table.cards thead, table.cards tbody,
  table.cards tr, table.cards th, table.cards td { display: block; }

  table.cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

  table.cards tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    padding: var(--s3);
    margin-bottom: var(--s3);
  }
  table.cards tr:hover { background: var(--surface); }

  /* Flex, NICHT Grid: Grid wuerde jedes Kind der Zelle zu einem eigenen
     Rasterfeld machen. Zellen mit mehreren Kindern (Statuspunkt + Zahl +
     Wort) brechen dann auseinander. Flex legt alle Kinder in eine Reihe
     hinter die Beschriftung, egal wie viele es sind. */
  table.cards td {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--s1) var(--s2);
    padding: var(--s2) 0;
    border: 0;
    text-align: left;
    min-height: 32px;
  }

  table.cards td::before {
    content: attr(data-label);
    flex: 0 0 7.5rem;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1.3;
    color: var(--text-muted);
    font-family: var(--font);
  }

  /* Die Sparkline ist breiter als der Rest - sie bekommt die naechste Zeile. */
  table.cards td:has(.sparkline) { align-items: center; }

  table.cards td.num { text-align: left; }

  /* Zellen ohne Beschriftung (Knopfspalten) nehmen die volle Breite. */
  table.cards td:not([data-label]) {
    display: block;
    margin-top: var(--s2);
    padding-top: var(--s2);
    border-top: 1px solid var(--border);
  }
  table.cards td:not([data-label]) .actions { justify-content: flex-start; }
}

/* --- Hilfsklassen -------------------------------------------------------- */

.row-between { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: center; justify-content: space-between; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --- Zugaenglichkeit -----------------------------------------------------
   Abschalten, nicht abschwaechen. Das ist eine Zusage, kein Feinschliff. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .chart__line { stroke-dashoffset: 0 !important; }
}

/* --- Kopfzeilen-Aktionen -------------------------------------------------
   Auf dem Handy wandert die Navigation nach unten; Konto und Abmelden
   bleiben oben rechts und duerfen dort schmaler werden. */

.header-actions { gap: var(--s2); flex: none; }
.header-actions form { display: contents; }

@media (max-width: 60rem) {
  .header-actions .btn--small,
  .header-actions button { padding-inline: var(--s2); font-size: 0.78rem; }
}

/* Auf dem Finger 44 px und mehr Abstand: "Abmelden" steht direkt neben
   "Konto", ein Fehltipp meldete vorher ab. Mit Maus bleiben sie kompakt. */
@media (pointer: coarse) {
  .header-actions { gap: var(--s3); }
  .header-actions .btn--small,
  .header-actions button { min-height: 44px; }
}

@media (max-width: 26rem) {
  .brand { font-size: 0.92rem; }
}

/* --- Eingabetabellen (Versuche, Saetze) ---------------------------------
   Diese Tabellen sind Formulare, keine Daten - sie bleiben auch auf dem
   Handy Tabellen, bekommen dort aber feste Spaltenbreiten. Ohne das frisst
   die Nummernspalte Platz und das Eingabefeld wird unbrauchbar schmal.

   max-width: ein Eingabefeld waechst nicht mit dem Fenster mit. Auf einem
   breiten Bildschirm stand "16.42" vorher in einem 950 px breiten Feld,
   waehrend das Feld daneben 95 px hatte. Die Tabelle hoert deshalb bei
   einer Breite auf, die zum Inhalt passt, und bleibt linksbuendig. */

#attempts, #sets { table-layout: fixed; width: 100%; }
#attempts { max-width: 32rem; }
#sets { max-width: 46rem; }

#attempts input, #sets input { min-height: 44px; padding-inline: var(--s2); }

/* Die Kopfzeilen dieser Tabellen duerfen umbrechen: "Fehlversuch" und
   "Gewicht (kg)" sind laenger als ihre Spalte, und die globale
   nowrap-Regel hat sie abgeschnitten. */
#attempts thead th, #sets thead th { white-space: normal; overflow-wrap: normal; line-height: 1.2; }

/* Versuche: Nr | Weite | Fehlversuch */
#attempts th:first-child, #attempts td:first-child { width: 2.75rem; padding-inline: 0 var(--s2); }
#attempts th:last-child,  #attempts td:last-child  { width: 7rem; text-align: center; }
#attempts td:last-child input[type="checkbox"] { width: 24px; height: 24px; accent-color: var(--accent); }

/* Saetze: Nr | Uebung | Wdh. | Gewicht | RPE. Die drei Zahlenspalten sind
   gleich breit - sie tragen gleich viele Stellen. */
#sets th:nth-child(1), #sets td:nth-child(1) { width: 2.75rem; padding-inline: 0 var(--s2); }
#sets th:nth-child(3), #sets td:nth-child(3),
#sets th:nth-child(4), #sets td:nth-child(4),
#sets th:nth-child(5), #sets td:nth-child(5) { width: 7rem; }

@media (max-width: 48rem) {
  #attempts thead th {
    font-size: 0.62rem;
    letter-spacing: 0.03em;
  }
  #attempts th:last-child, #attempts td:last-child { width: 5.5rem; }
}

/* Saetze: fuenf Spalten passen auf 390px nicht nebeneinander. Die Zeile
   wird dort zu einem Block - Nummer und Uebung oben, die drei Zahlen
   darunter in gleich breiten Spalten.

   Vorher standen die drei Zahlenfelder treppenfoermig untereinander: die
   Flaechenangabe nannte drei Spalten, das Raster hatte zwei, und damit
   war sie ungueltig - die Zellen landeten automatisch irgendwo. Dazu
   fehlte jede Beschriftung, man sah drei leere Kaesten ohne zu wissen,
   welcher die Wiederholungen nimmt. */
@media (max-width: 48rem) {
  #sets, #sets thead, #sets tbody, #sets tr, #sets th, #sets td { display: block; }
  #sets thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  #sets { max-width: none; }

  #sets tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--s3);
    margin-bottom: var(--s3);
    background: var(--surface);
    display: grid;
    grid-template-columns: 2.25rem repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "nr uebung  uebung  uebung"
      ".  wdh     gewicht rpe";
    gap: var(--s2);
    align-items: end;
  }
  #sets tbody tr:hover { background: var(--surface); }

  /* Die Spaltenbreiten der Tabellenansicht zuruecknehmen - hier bestimmt
     das Raster die Breite. Mit derselben Spezifitaet wie oben, sonst
     behalten die Zellen ihre 7rem und die Zeile laeuft ueber den Rand. */
  #sets td { padding: 0; border: 0; }
  #sets td:nth-child(1), #sets td:nth-child(3),
  #sets td:nth-child(4), #sets td:nth-child(5) { width: auto; }
  #sets td:nth-child(1) { grid-area: nr; font-family: var(--mono); color: var(--text-faint); }
  #sets td:nth-child(2) { grid-area: uebung; }
  #sets td:nth-child(3) { grid-area: wdh; }
  #sets td:nth-child(4) { grid-area: gewicht; }
  #sets td:nth-child(5) { grid-area: rpe; }

  /* Beschriftung aus data-label, wie in den Kartentabellen. */
  #sets td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-faint);
  }
}

/* --- Hilfsklassen --------------------------------------------------------
   Ersetzen die Inline-Styles in den Templates. Ein style="..." im Template
   schlaegt jede Regel hier und macht das System wirkungslos - siehe
   DESIGN.md. Wer etwas braucht, das es nicht gibt, ergaenzt es hier. */

.m-0  { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--s2); }
.mt-3 { margin-top: var(--s3); }
.mt-4 { margin-top: var(--s4); }
.mt-6 { margin-top: var(--s6); }
.mb-2 { margin-bottom: var(--s2); }
.mb-3 { margin-bottom: var(--s3); }

.prewrap { white-space: pre-wrap; }

/* Maschinentext: Token, Links, Dateinamen. Kein Messwert (dafuer .num) und
   kein Fliesstext - aber auch nichts, was man als Sprache liest. Etwas
   kleiner gesetzt, weil ein Einladungslink sonst die Zeile sprengt. */
.mono { font-family: var(--mono); font-size: 0.85rem; }

/* Die Karte mit dem Einladungslink. Akzentkante, weil sie das Ergebnis
   einer gerade ausgefuehrten Handlung ist und nur einmal erscheint. */
.invite-link { border-left: 3px solid var(--accent); }
.actions--between { justify-content: space-between; }
/* Kopfzeile einer Seite und der erste Inhalt darunter brauchen denselben
   Abstand wie zwei Karten - sonst klebt die Karte an der Ueberschrift. */
.actions--between + .card,
.actions--between + .stats { margin-top: var(--s4); }
.grow { flex: 1 1 14rem; }
.field--narrow { max-width: 18rem; }

/* Auf dem Telefon steht der Titel ueber dem Knopf statt daneben: beide
   nebeneinander lassen fuer keinen von beiden genug Platz. */
@media (max-width: 30rem) {
  .actions--between { align-items: stretch; }
  .actions--between > * { flex: 1 1 100%; }
  .actions--between > .btn { justify-content: center; }
}

/* Schmale Zahlenfelder im Plan-Baukasten. Sie stehen in einer Reihe mit
   der Beschreibung, duerfen aber nicht unter das Touch-Ziel fallen.
   Nur fuer Eingabefelder - fuer Tabellenspalten gibt es .col-*.

   Mit Elementnamen geschrieben (input.input--xs statt .input--xs): die
   allgemeine Feldregel waehlt ueber input[type="number"] aus und ist
   damit staerker als eine blosse Klasse. Ohne den Elementnamen hat keine
   dieser Breiten gegriffen - im Plan-Baukasten stand deshalb jedes Feld
   ueber die volle Breite und die Reihe war in Wahrheit eine Spalte. */
/* Felder in einer Knopfreihe richten sich nach ihrem Inhalt, nicht nach
   der Karte: width: 100% aus der allgemeinen Feldregel macht sonst aus
   jeder Reihe eine Spalte. Steht VOR den Breitenklassen, damit diese bei
   gleicher Spezifitaet gewinnen. */
.actions > input, .actions > select { width: auto; max-width: 100%; }

input.input--xs, input.input--sm, input.input--md { min-width: 0; }
input.input--xs { width: 5rem; }
input.input--sm { width: 6.5rem; }
input.input--md { width: 7.5rem; }

.actions > .grow { width: auto; flex: 1 1 14rem; }

@media (max-width: 48rem) {
  input.input--xs, input.input--sm, input.input--md { width: 100%; }
}

/* Spaltenbreiten in Datentabellen. Eigene Klassen, weil die input--*
   Klassen in Kopfzeilen gelandet waren: unter 48rem setzen die
   width: 100%, was eine Tabellenspalte auseinanderzieht. */
.col-nr { width: 3.5rem; }
.col-num { width: 7rem; }
/* Die Spalte, die den uebrigen Platz schluckt. Ohne sie verteilt der
   Browser die freie Breite gleichmaessig und schiebt die Zahlenspalten
   weit auseinander. */
.col-rest { width: 100%; }

/* Eine Einheit im Plan-Baukasten: eingerueckt mit Markierungslinie. */
.plan-unit {
  margin-top: var(--s4);
  padding-left: var(--s3);
  border-left: 2px solid var(--border);
}

/* --- Startseiten ----------------------------------------------------------
   Athlet: zwei Karten, jede als Ganzes ein Ziel. Trainer: eine Auswahlliste,
   jede Zeile als Ganzes ein Link. Begruendung in den Templates
   (dashboard/athlete.html, dashboard/leader.html). */

.start-title { margin-bottom: var(--s1); }

.start-cards {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  margin-top: var(--s4);
}
/* Abstand traegt das gap, wie bei .grid - sonst rutscht die zweite Karte
   um 16 px nach unten. */
.start-cards > .card + .card { margin-top: 0; }

/* Die Karte ist das Ziel: der Link spannt sich ueber sie (::after), ohne
   dass Text und Pfeil selbst zu Links werden muessen. So bleibt es EIN
   Link mit EINEM Namen - Rechtsklick, neuer Tab und Screenreader
   funktionieren wie bei jedem Link. */
.start-card {
  position: relative;
  min-height: 112px;
  padding: var(--s4) var(--s12) var(--s4) var(--s4);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s1);
  transition: border-color var(--t-micro) ease-out, background var(--t-micro) ease-out;
}

.start-card__title { margin: 0; font-size: 1.15rem; }
.start-card__link,
.start-card__link:visited { color: var(--accent); text-decoration: none; }
.start-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}

.start-card__hint,
.start-card__last { margin: 0; color: var(--text-muted); font-size: 0.88rem; }

/* Fokus: der Ring liegt um die ganze Karte, nicht um die Ueberschrift -
   die Karte ist das, was man trifft. */
.start-card__link:focus-visible { outline: none; }
.start-card:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Rueckmeldung beim Tippen; Hover nur dort, wo es einen Zeiger gibt -
   auf dem Telefon bliebe ein :hover nach dem Tippen kleben. */
.start-card:active { background: var(--surface-2); border-color: var(--border-strong); }
@media (hover: hover) {
  .start-card:hover { border-color: var(--accent); }
}

/* Pfeil rechts: "hier geht es weiter". Reine Form, kein Bild. */
.start-card__arrow,
.pick-list__arrow {
  flex: none;
  width: 9px;
  height: 9px;
  border-top: 2px solid var(--text-muted);
  border-right: 2px solid var(--text-muted);
  transform: rotate(45deg);
}
.start-card__arrow {
  position: absolute;
  right: var(--s6);
  top: 50%;
  margin-top: -5px;
}

/* Auswahlliste des Trainers. */
.pick-card { padding: 0; overflow: hidden; }

.pick-list__head {
  display: flex;
  justify-content: space-between;
  padding: var(--s3) calc(var(--s4) + 9px + var(--s4)) var(--s2) var(--s4);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* muted, nicht faint: faint erreicht nur 3:1, fuer 11 px zu wenig. */
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}

.pick-list { list-style: none; margin: 0; padding: 0; }
.pick-list li + li { border-top: 1px solid var(--border); }

/* Die ganze Zeile ist der Link: 56 px hoch, volle Breite. */
.pick-list__row,
.pick-list__row:visited {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: 56px;
  padding: var(--s2) var(--s4);
  color: var(--text);
  text-decoration: none;
  transition: background var(--t-micro) ease-out;
}
.pick-list__name { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.pick-list__meta {
  flex: none;
  color: var(--text-muted);
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

.pick-list__row:active { background: var(--surface-2); }
@media (hover: hover) {
  .pick-list__row:hover { background: var(--surface-2); }
  .pick-list__row:hover .pick-list__name { color: var(--accent); }
}
.pick-list__row:focus-visible { outline-offset: -2px; border-radius: 0; }
