/*
 * Ein Elternteil hält beim Bedienen oft ein Kind auf dem Arm und steht in der
 * Sonne: große Ziele, kräftiger Kontrast, keine Hover-Abhängigkeiten.
 *
 * ---------------------------------------------------------------------------
 * Design-System
 * ---------------------------------------------------------------------------
 * Drei Regeln, die alles darunter binden:
 *
 * 1. Schriftgrößen kommen aus `--fs-*` und nirgends sonst. Sieben Stufen,
 *    jede fluid per `clamp()`. Vorher waren es elf, weil überall eigene
 *    rem-Werte standen: `.9rem` ergibt 15.3px, `.92rem` ergibt 15.64px —
 *    zwei Stufen, die niemand entschieden hat und die man trotzdem sieht.
 *
 * 2. Abstände kommen aus `--sp-*`, alle Vielfache von 4. Aus demselben Grund:
 *    `.35rem` sind 5.95px, `.45rem` sind 7.65px. 78 % aller Abstände lagen
 *    außerhalb eines Rasters — das ist der Unterschied, den man sieht, ohne
 *    ihn benennen zu können.
 *
 * 3. Farben kommen aus den Tokens unten. Grün ist die einzige Akzentfarbe;
 *    Gelb und Rot bedeuten immer Wetter/Warnung und nie Dekoration.
 */

:root {
  /* --- Typo-Skala: sieben Stufen, fluid, Verhältnis ~1.25 ---------------
   * `clamp()` statt fester Größen und statt Media Queries: die Schrift wächst
   * stufenlos mit dem Fenster, ohne dass es an einer geratenen Grenze springt
   * (Intrinsic Layout, Regel 0 der Web-Guideline). Die kleinen Stufen wachsen
   * kaum — eine Achsenbeschriftung braucht auf 27 Zoll nicht mehr Platz, eine
   * Kennzahl schon. */
  /* Untergrenze 12px, nicht kleiner: die Uhrzeiten der Sonnen-Zeitleiste
     werden im Stehen gelesen, mit Sonne auf dem Schirm und Kind auf dem Arm. */
  --fs-xs: clamp(12px, 11.5px + .1vw, 13px);        /* Achsenbeschriftung, Fußnoten */
  --fs-sm: clamp(13.5px, 13px + .15vw, 15px);       /* Nebentext, Legenden, Tabellen */
  --fs-md: clamp(15.5px, 15px + .2vw, 17px);        /* Fließtext */
  --fs-lg: clamp(17px, 16px + .35vw, 19px);         /* hervorgehobener Text */
  --fs-xl: clamp(20px, 18px + .6vw, 24px);          /* Blocküberschrift */
  --fs-2xl: clamp(25px, 21px + 1.2vw, 33px);        /* Urteil */
  --fs-3xl: clamp(32px, 26px + 1.9vw, 46px);        /* Kennzahlen, Seitentitel */

  /* --- Abstände: 4er-Raster -------------------------------------------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  /* --- Gewichte: drei, nicht vier -------------------------------------- */
  --fw-normal: 400;
  --fw-medium: 500;
  --fw-bold: 700;

  /* --- Farben ----------------------------------------------------------
   * Wald- und Bergtöne aus dem Entwicklungsstack, an die vorhandene warme
   * Papierfläche angeglichen: das Creme des Hintergrunds war schon da und
   * trägt den „Berggefühl"-Charakter besser als ein neutrales Weiß. */
  --bg: #f6f3ee;
  --surface: #fffdfa;
  --surface-2: #f1ece4;
  --ink: #1b2721;
  --ink-soft: #6b6459;
  --line: #ddd5c8;
  --line-soft: #eae4da;
  --accent: #3d8a62;
  --accent-strong: #275f45;
  --accent-ink: #fff;
  --gut: #2f6b3f;
  --mittel: #9a6714;
  --schlecht: #a33a2a;
  --gut-bg: #e9f2ea;
  --mittel-bg: #f9f0dd;
  --schlecht-bg: #f9e8e3;

  /* --- Form ------------------------------------------------------------
   * Zwei Radien statt vier: groß für Karten, klein für alles darin. */
  --radius: 16px;
  --radius-sm: 8px;
  /* Sehr weiche Schatten — „Berggefühl" heißt viel Weißraum und wenige harte
   * Kanten, nicht schwebende Kacheln. */
  --shadow: 0 1px 2px rgb(27 39 33 / .04), 0 8px 24px rgb(27 39 33 / .05);
  --shadow-lift: 0 2px 4px rgb(27 39 33 / .06), 0 12px 32px rgb(27 39 33 / .08);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #14171a;
    --surface: #1c2023;
    --surface-2: #24292d;
    --ink: #edf0ee;
    --ink-soft: #a3aca6;
    --line: #333a3e;
    --line-soft: #292f33;
    --accent: #6dbb8e;
    --accent-strong: #8fd0a9;
    --accent-ink: #10221a;
    --gut: #8fce9c;
    --mittel: #e5b45f;
    --schlecht: #f0937f;
    --gut-bg: #1a2b21;
    --mittel-bg: #2d2617;
    --schlecht-bg: #33201b;
    --shadow: 0 1px 2px rgb(0 0 0 / .3), 0 8px 24px rgb(0 0 0 / .28);
    --shadow-lift: 0 2px 4px rgb(0 0 0 / .35), 0 12px 32px rgb(0 0 0 / .4);
  }
}

/* Dieselben Werte, wenn Dunkel ausdrücklich gewählt ist — der Block
   oben greift nur, wenn das Betriebssystem dunkel steht. */
:root[data-theme="dark"] {
  --bg: #14171a;
  --surface: #1c2023;
  --surface-2: #24292d;
  --ink: #edf0ee;
  --ink-soft: #a3aca6;
  --line: #333a3e;
  --line-soft: #292f33;
  --accent: #6dbb8e;
  --accent-strong: #8fd0a9;
  --accent-ink: #10221a;
  --gut: #8fce9c;
  --mittel: #e5b45f;
  --schlecht: #f0937f;
  --gut-bg: #1a2b21;
  --mittel-bg: #2d2617;
  --schlecht-bg: #33201b;
  --shadow: 0 1px 2px rgb(0 0 0 / .3), 0 8px 24px rgb(0 0 0 / .28);
  --shadow-lift: 0 2px 4px rgb(0 0 0 / .35), 0 12px 32px rgb(0 0 0 / .4);
}


/* Sagt dem Browser, welche eingebauten Bedienelemente er zeichnen soll —
 * Bildlaufleisten, Datums- und Zeitwähler, Auswahlfelder. Ohne diese Angabe
 * malt er sie im Systemmodus, und auf einem hellen System mit erzwungenem
 * Dunkel steht dann ein weißer Datumswähler in einer dunklen Karte. */
:root { color-scheme: light; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--fs-md)/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

/* ==========================================================================
   App-Gerüst — Seitenleiste, Kopfzeile, Arbeitsfläche
   ==========================================================================
   Zwei Spalten ab genügend Platz, eine darunter. Die Umschaltgrenze steht
   bewusst als Container-Breite und nicht als Gerätebreite: entscheidend ist,
   ob 240 px Leiste plus eine brauchbare Arbeitsfläche nebeneinander passen,
   nicht ob jemand ein Tablet hält.
   ========================================================================== */

.app {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 100vh;
}

@media (min-width: 60rem) {
  .app { grid-template-columns: 248px minmax(0, 1fr); }
}

/* --- Seitenleiste ------------------------------------------------------- */

/* Die Leiste hat zwei Erscheinungsformen, nicht zwei Bauarten.
 *
 * Bis 60rem ist sie eine Schublade, die über die Seite fährt; darüber eine
 * feste Spalte im Raster. Beides ist dasselbe Element mit demselben Inhalt —
 * die Alternative wäre gewesen, für Telefone ein zweites Menü zu bauen, und
 * dann pflegt man jeden neuen Punkt an zwei Stellen. Genau das ging vorher
 * schief: das Konto wurde umgehängt, Farbschema und Navigation blieben auf
 * dem Telefon unerreichbar.
 */
.side {
  display: flex;
  border-right: 1px solid var(--line);
  background: var(--surface);
  padding: var(--sp-6) var(--sp-5);
  flex-direction: column;

  /* --- Schublade (unter 60rem) ---
     `fixed`, damit sie über dem Inhalt liegt statt ihn zu verschieben. Der
     Einwand gegen `fixed` — verkleinert den sichtbaren Bereich bei offener
     Tastatur — gilt hier nicht: in der Schublade wird nichts eingetippt
     außer der E-Mail-Adresse, und dafür deckt sie ohnehin den Schirm. */
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 60;
  width: min(17rem, 82vw);
  /* `100dvh` statt `100vh`: folgt dem tatsächlich sichtbaren Bereich, wenn
     die Adressleiste ein- und ausfährt. */
  height: 100dvh;
  /* Der Inhalt kann länger sein als der Schirm — Navigation, Konto,
     Farbschema und der Hinweistext zusammen passen auf einem kleinen Gerät
     nicht immer. */
  overflow-y: auto;
  overscroll-behavior: contain;

  transform: translateX(-100%);
  transition: transform .22s ease;
  /* Ausgefahren wird sie nur über das Attribut, das auch der Knopf setzt —
     ein einziger Zustand für CSS und JavaScript. */
  visibility: hidden;
}

.side[data-offen="ja"] { transform: translateX(0); visibility: visible; }

/* Wer „weniger Bewegung" eingestellt hat, bekommt sie ohne Fahrt. */
@media (prefers-reduced-motion: reduce) {
  .side { transition: none; }
}

@media (min-width: 60rem) {
  /* --- Feste Spalte (ab 60rem) ---
     Alles Schubladenhafte zurücknehmen. `sticky` statt `fixed`, damit die
     Leiste im Raster steht und der Rest der Seite darunter durchscrollt. */
  .side {
    position: sticky;
    /* Reihenfolge zählt: `inset` ist die Kurzform für alle vier Seiten und
       setzt `top` mit zurück. Stünde es nach `top: 0`, wäre `top` wieder
       `auto` — und eine `sticky`-Leiste ohne `top` klebt an gar nichts.
       Genau so war es und niemand hat es gesehen. */
    inset: auto;
    top: 0;
    width: auto;
    transform: none;
    visibility: visible;
    align-self: start;

    /* Genau bildschirmhoch, nicht berichtshoch.
       Ohne feste Höhe streckt das Raster die Spalte auf die Höhe des
       Berichts; `sticky` hat dann nichts zum Kleben und die Leiste wäre nach
       dem ersten Scrollen weg. `align-self: start` verhindert das Strecken,
       `100dvh` gibt ihr stattdessen die Höhe des tatsächlich sichtbaren
       Bereichs — `dvh` statt `vh`, weil ein- und ausfahrende Browserleisten
       den sichtbaren Bereich verändern.

       Der Inhalt kann trotzdem höher sein als der Schirm, etwa auf einem
       niedrigen Fenster oder bei großer Schrifteinstellung. Dann scrollt die
       Leiste in sich selbst; `overscroll-behavior` sorgt dafür, dass das
       Scrollen an ihrem Ende nicht auf die Seite dahinter überspringt. */
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Balken erst zeigen, wenn er gebraucht wird — sonst steht auf breiten
       Fenstern dauerhaft eine graue Rinne neben der Navigation. */
    scrollbar-width: thin;
  }
}

/* --- Burger-Knopf --------------------------------------------------------
 *
 * Links oben, fest über dem Inhalt. Nicht in der Kopfzeile: die scrollt weg,
 * und ein Menü, das man nur oben auf der Seite erreicht, ist auf einem langen
 * Bericht wertlos.
 * ----------------------------------------------------------------------- */

.menue-knopf {
  position: fixed;
  top: var(--sp-3);
  left: var(--sp-3);
  z-index: 50;

  display: flex;
  align-items: center;
  justify-content: center;
  /* 44px — die Fingergröße, die für alle Bedienelemente auf Telefonen gilt. */
  width: 44px;
  height: 44px;

  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow);
}
.menue-knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Ab 60rem steht die Leiste ohnehin da — ein Knopf, der sie „öffnet", wäre
   dann sinnlos. */
@media (min-width: 60rem) { .menue-knopf { display: none; } }

.menue-schatten {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgb(0 0 0 / .45);
}
@media (min-width: 60rem) { .menue-schatten { display: none; } }

.menue-zu {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  /* 44px: dieser Knopf existiert ausschließlich unter 60rem, wo die Leiste
     eine Schublade ist — er wird also immer mit dem Finger getroffen. */
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}
.menue-zu:hover { background: var(--surface-2); color: var(--ink); }
.menue-zu:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (min-width: 60rem) { .menue-zu { display: none; } }

.brand {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: -.02em;
  color: var(--ink);
  text-decoration: none;
  margin-bottom: var(--sp-8);
}

/* Der Schriftzug ist auch ein Link auf die Startseite und in der Schublade
   damit ein Fingerziel. Die Trefferfläche wächst über ein Pseudo-Element
   statt über Polster: der Zeilenabstand im Kopf soll unverändert bleiben. */
.brand::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 0;
  translate: 0 -50%;
  width: 100%;
  height: max(100%, 44px);
}
.brand-mark { color: var(--accent); flex: none; }

.side-nav { display: grid; gap: var(--sp-1); }

.side-link {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-3);
  /* Navigationsziel, kein Link im Fließtext: unter 60rem wird die Leiste
     als Schublade mit dem Finger bedient. */
  min-height: 44px;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  transition: background .15s, color .15s;
}
.side-link:hover { background: var(--surface-2); color: var(--ink); }
.side-link.is-active { background: var(--gut-bg); color: var(--accent-strong); }
.side-link svg { flex: none; }

/* --- Hinweiszeile über einer gespeicherten Auswertung -------------------- */

/* Steht über den Kennzahlen, nicht darunter: sie sagt, wie das zu lesen ist,
   was folgt. Eine Einordnung nach dem Bericht kommt zu spät. */
.gespeichert {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}
.gespeichert p { margin: 0; flex: 1 1 16rem; min-width: 0; line-height: 1.45; }
.gespeichert strong { color: var(--ink); }
.gespeichert-ic { flex: none; color: var(--ink-soft); }
.gespeichert .btn { flex: none; }

.gespeichert.is-ok { border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
.gespeichert.is-ok .gespeichert-ic { color: var(--accent-strong); }
.gespeichert.is-warn { border-color: color-mix(in srgb, var(--bad, #c2410c) 40%, var(--line)); }
.gespeichert.is-warn .gespeichert-ic { color: var(--bad, #c2410c); }

/* Ein kleinerer Knopf für die Hinweiszeile: der volle 44-px-Knopf sprengt
   sie und wirkt wie die Hauptsache, obwohl der Bericht darunter es ist.
   Die Mindestgröße für Finger bleibt über das Padding erhalten. */
.btn-sm {
  min-height: 36px;
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm);
}

/* --- Gespeicherte Touren in der Seitenleiste ----------------------------- */

.side-touren { margin-top: var(--sp-6); min-width: 0; }

.side-touren-titel {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
}

.tourenliste { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }

/* Öffnen und Löschen nebeneinander. Der Löschknopf erscheint erst beim
   Berühren der Zeile — dauerhaft sichtbar zieht er in einer schmalen Liste
   mehr Aufmerksamkeit auf sich als das Öffnen, und getroffen wird er
   ungewollt. Auf Geräten ohne Zeiger steht er dauerhaft da: „beim Berühren"
   gibt es dort nicht. */
.tour-zeile { display: flex; align-items: stretch; gap: 2px; min-width: 0; }

.tour-oeffnen {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  gap: 1px;
  text-align: left;
  padding: var(--sp-2) var(--sp-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.tour-oeffnen:hover { background: var(--surface-2); }
.tour-oeffnen:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tour-oeffnen[disabled] { opacity: .5; cursor: default; }

.tour-name {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tour-meta {
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Das Urteil als Wort, nicht als Farbfleck: ein grüner Punkt allein ist für
   Farbenblinde bedeutungslos, und in einer Liste aus zwanzig Touren fragt
   man sich sonst, wofür er steht. */
.tour-urteil { font-weight: var(--fw-medium); }
.tour-urteil.is-gut { color: var(--ok-text, var(--accent-strong)); }
.tour-urteil.is-mittel { color: var(--warn-text, var(--ink)); }
.tour-urteil.is-schlecht { color: var(--bad-text, var(--ink)); }

.tour-weg {
  flex: none;
  width: 30px;
  display: grid; place-items: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
}
.tour-zeile:hover .tour-weg,
.tour-weg:focus-visible { opacity: 1; }
.tour-weg:hover { background: var(--surface-2); color: var(--ink); }
/* Ohne Zeiger gibt es kein „beim Berühren" — dort steht er immer. */
@media (hover: none) { .tour-weg { opacity: 1; } }

.side-touren-leer {
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--ink-soft);
  margin: var(--sp-2) 0 0;
  padding: 0 var(--sp-3);
}

.side-foot { margin-top: auto; padding-top: var(--sp-6); }

/* --- Farbschema-Umschalter ----------------------------------------------
 *
 * Drei Radioknöpfe, die wie ein Segment-Umschalter aussehen. Das Markup
 * bleibt aber ein `fieldset` mit echten `<input type="radio">`: damit
 * funktionieren Pfeiltasten, Tabulator und Screenreader ohne eine einzige
 * Zeile JavaScript, und ein Knopf, der nur so aussieht, kann das nicht.
 * ----------------------------------------------------------------------- */

.thema {
  /* Ein `fieldset` bringt Rahmen und Innenabstände mit, die hier stören. */
  border: 0;
  margin: 0 0 var(--sp-4);
  padding: 0;
}

.thema-titel {
  /* `legend` sitzt standardmäßig im Rahmen des `fieldset` und bringt eigene
     Abstände mit — beides weg, damit die Beschriftung wie jede andere
     Kleinüberschrift in der Leiste steht. */
  padding: 0;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}

.thema-gruppe {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  padding: 2px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.thema-wahl {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 44px, solange die Seitenleiste als Schublade bedient wird. Die frühere
     Begründung „die Leiste gibt es erst ab 60rem, also nur mit Maus" war
     falsch: unter 60rem ist sie nicht weg, sondern nur eingeklappt — der
     Menü-Knopf öffnet sie auch auf 320px, und dann trifft ein Finger die
     Ziele. Ab 60rem steht sie fest neben dem Inhalt und wird gezeigt, dort
     dürfen 34px bleiben. */
  min-height: 44px;
  border-radius: 6px;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
  transition: background .15s, color .15s;
}

/* Der eigentliche Radioknopf wird nicht ausgeblendet, sondern unsichtbar
   über sein Label gelegt. `display: none` nähme ihm die Fokussierbarkeit,
   und die Gruppe wäre mit der Tastatur nicht mehr erreichbar. */
.thema-wahl input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

/* Ab hier steht die Leiste fest neben dem Inhalt und wird mit der Maus
   bedient — die 44px-Regel gilt für Finger, nicht für Zeiger. */
@media (min-width: 60rem) {
  .thema-wahl { min-height: 34px; }
}

.thema-wahl:hover { color: var(--ink); }

.thema-wahl:has(input:checked) {
  background: var(--surface);
  color: var(--ink);
  font-weight: var(--fw-medium);
  box-shadow: var(--shadow);
}

/* Der Fokusrahmen gehört sichtbar ans Label, nicht an den unsichtbaren
   Knopf darunter — sonst sieht man beim Tabben nicht, wo man ist. */
.thema-wahl:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.side-note {
  margin: 0;
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--ink-soft);
  border-top: 1px solid var(--line-soft);
  padding-top: var(--sp-4);
}

/* --- Arbeitsfläche ------------------------------------------------------ */

.main {
  min-width: 0;
  padding: clamp(var(--sp-4), 2.5vw, var(--sp-8));
  padding-bottom: var(--sp-16);
}

/* --- Kopfzeile ---------------------------------------------------------- */

.top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4) var(--sp-6);
  margin-bottom: var(--sp-6);
  min-height: 44px;
}

/* Platz für den Burger-Knopf, der links oben fest über der Seite sitzt.
   Ohne diese Zeile liegt er auf der Überschrift. Ab 60rem gibt es ihn nicht
   mehr, dort fällt der Einzug weg. */
@media (max-width: 59.99rem) {
  .top { padding-left: calc(44px + var(--sp-3)); }
}

.top-title h1 {
  font-size: var(--fs-3xl);
  line-height: 1.08;
  margin: 0 0 var(--sp-2);
  letter-spacing: -.025em;
  font-weight: var(--fw-bold);
}

.sub {
  color: var(--ink-soft);
  margin: 0;
  max-width: 62ch;
  font-size: var(--fs-lg);
  line-height: 1.5;
}

/* Dateizeile: erscheint erst, wenn eine Tour geladen ist, und ersetzt dann
   den Produktanspruch — der ist ab da gelesen und nimmt nur Platz weg.
 *
 * `flex: 1 1 12rem` ist hier das Entscheidende, und es stand vorher nicht da.
 * Ohne Angabe gilt `flex: 0 1 auto`, und „auto" heißt: die Ausgangsbreite ist
 * der ganze Titel. Bei einem Namen wie „Blick über das Leutaschtal –
 * Hochfeldernalm Runde von Ehrwald" war die Zeile damit voll, bevor die
 * Knöpfe überhaupt drankamen — sie rutschten in eine zweite Zeile, obwohl
 * daneben Platz gewesen wäre.
 *
 * Jetzt beansprucht die Dateizeile 12rem und wächst in den übrigen Platz
 * hinein. Reicht er nicht, schrumpft sie bis 12rem und der Titel kürzt sich
 * mit Auslassungspunkten — er ist der einzige Teil der Kopfzeile, von dem ein
 * Stück genügt. Erst wenn auch 12rem plus Knöpfe nicht mehr nebeneinander
 * passen, bricht die Zeile um, und dann ist der Umbruch richtig.
 */
.top-file {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  flex: 1 1 12rem;
}
.top-file-ic { color: var(--accent); flex: none; }
/* `min-width: 0` muss auf jeder Ebene stehen, durch die das Schrumpfen
   hindurch muss: ein Flex-Element schrumpft von sich aus nie unter die Breite
   seines Inhalts, und ein einziges vergessenes `min-width` weiter innen
   blockiert die ganze Kette. */
.top-file-txt { min-width: 0; flex: 1 1 auto; }
.top-file-txt strong {
  display: block;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: -.01em;
  /* Dateinamen aus Komoot sind lang; abschneiden statt umbrechen, damit die
     Kopfzeile eine Zeile hoch bleibt. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.top-file-meta {
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  display: block;
  /* Auch die Kennzahlenzeile kürzen statt umbrechen — sonst wird die
     Dateizeile zweizeilig und schiebt die Knöpfe wieder nach unten. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Die Einstellungen wandern nach dem Hochladen nach oben: dort ändert man sie
   ständig, und der Weg zurück zur Upload-Karte wäre jedes Mal ein Scrollen
   über den halben Bericht. */
/* Beim Verteilen des Platzes gewinnen die Knöpfe gegen den Titel: „Tour
 * speichern" mit halbem Wort ist unbrauchbar, ein gekürzter Tourname nicht.
 *
 * Das steht in `flex-shrink: 0` — aber `flex-basis: auto` gehört dazu, und
 * das ist der feine Unterschied zu `flex: 0 0 auto`. Letzteres hindert auch
 * den Container selbst am Schrumpfen; auf einem 390-px-Telefon blieb er dann
 * 542 px breit und lief seitlich aus dem Bild, obwohl das `flex-wrap`
 * darunter die Knöpfe längst hätte umbrechen können. `min-width: 0` macht
 * genau das wieder möglich: der Container gibt nach, die Knöpfe darin nicht —
 * sie brechen um.
 */
.top-actions {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-left: auto;
  flex-wrap: wrap;
  /* `flex-basis: 0` statt `auto`: bei `auto` ist die Ausgangsbreite die Summe
     aller Knöpfe (hier 542 px), und die bleibt auch auf einem 390-px-Telefon
     stehen — der Kasten lief seitlich aus dem Bild, obwohl das `flex-wrap`
     darüber die Knöpfe längst hätte umbrechen können. Mit `0` startet er bei
     nichts und wächst nur so weit, wie Platz da ist; die Knöpfe darin brechen
     dann von selbst um. `flex-grow: 0`, damit übriger Platz dem Titel
     zufällt und nicht als Leerraum zwischen den Knöpfen landet. */
  flex: 0 1 auto;
  min-width: min(100%, 9rem);
}
/* Die einzelnen Bedienelemente behalten ihre Größe und brechen lieber um —
   ein Knopf mit halb abgeschnittener Beschriftung ist unbrauchbar. */
.top-actions > * { flex: 0 0 auto; }

.top-field {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  min-width: 92px;
}
.top-field label { font-size: var(--fs-xs); color: var(--ink-soft); }
.top-field output { font-size: var(--fs-sm); font-weight: var(--fw-medium); font-variant-numeric: tabular-nums; }

.btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 44px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.btn:hover { border-color: var(--accent); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-ghost { background: transparent; }

/* Der Speichern-Knopf nach getaner Arbeit.
   Farbe statt Häkchen-Symbol: ein Symbol, das erscheint und wieder geht,
   wechselt die Knopfbreite und schiebt die Nachbarn hin und her. */
.btn.is-fertig {
  color: var(--ok, var(--accent-strong));
  border-color: currentColor;
}
/* Ein gesperrter Knopf ist sonst blass — hier heißt gesperrt aber „erledigt",
   nicht „geht gerade nicht", und das muss man lesen können. */
.btn.is-fertig[disabled] { opacity: 1; cursor: default; }

/* Die Upload-Karte und der Erklärteil bleiben auf Lesebreite — ein
   Eingabefeld über 1100 px sieht verloren aus. */
#input-card, .intro { max-width: 880px; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: clamp(var(--sp-4), 3vw, var(--sp-6));
}

/* ---------- Datei-Auswahl ---------- */

.drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  text-align: center;
  padding: var(--sp-8) var(--sp-4);
  border: 2px dashed var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}

.drop:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.drop.over { border-color: var(--accent); background: var(--gut-bg); }
.drop-icon { font-size: 2.2rem; }
.drop-title { font-weight: var(--fw-bold); font-size: var(--fs-lg); }
.drop-hint { color: var(--ink-soft); font-size: var(--fs-sm); }

/* ---------- Alter ---------- */

.age-row { margin-top: var(--sp-6); }
.age-row > label { display: block; font-weight: var(--fw-bold); margin-bottom: var(--sp-2); }

.age-control { display: flex; align-items: center; gap: var(--sp-4); }

/* 44 px ist die Mindestgröße für ein Bedienelement, das man im Stehen mit
   einem Kind auf dem Arm trifft. */
input[type="range"] {
  flex: 1;
  min-height: 44px;
  accent-color: var(--accent);
}

#age-out {
  min-width: 5.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-bold);
}

.age-note { color: var(--ink-soft); font-size: var(--fs-sm); margin: var(--sp-1) 0 0; }

/* ---------- Status ---------- */

/* `[hidden]` muss gewinnen: `display: flex` in einer Klassenregel ist
   spezifischer als das `display: none` aus dem Browser-Stylesheet, und die
   Statuszeile blieb deshalb nach dem fertigen Bericht sichtbar stehen —
   „Sonne und Schatten rechnen …" über einem längst gerechneten Ergebnis. */
[hidden] { display: none !important; }

.status {
  margin-top: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.status.error {
  background: var(--schlecht-bg);
  border-color: var(--schlecht);
  color: var(--schlecht);
  /* Die Zeile ist sonst ein einzeiliger Flex-Streifen. Mit Meldung *und*
     Knopf braucht sie zwei Zeilen — und der Knopf gehört unter den Text,
     nicht daneben: eine dreizeilige Erklärung neben einem Knopf drückt ihn
     auf schmalen Schirmen zu einem Streifen zusammen. */
  flex-wrap: wrap;
  align-items: flex-start;
}

.fehler-text {
  margin: 0;
  flex: 1 1 100%;
  line-height: 1.5;
}

.fehler-nochmal {
  /* Erbt die Fehlerfarbe vom Elternelement, sonst stünde ein grüner
     Standardknopf in einer roten Meldung. */
  color: var(--schlecht);
  border-color: var(--schlecht);
  background: transparent;
}
.fehler-nochmal:hover { border-color: var(--schlecht); background: var(--surface); }
.fehler-nochmal[disabled] { opacity: .6; cursor: default; }

/* Der Text darf schrumpfen und umbrechen, die Sekundenzahl nie — sonst
   verschwindet sie auf schmalen Schirmen als Erstes. */
.status-text { flex: 1 1 auto; min-width: 0; }
.status-count {
  flex: none;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  font-size: var(--fs-sm);
}

.spinner {
  width: 18px; height: 18px; flex: none;
  border: 2.5px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.5s; } }

/* ---------- Bericht ---------- */

/*
 * Bericht-Aufbau.
 *
 * Der Bericht ist ein einspaltiger Stapel aus breiten Blöcken — Urteil,
 * Karte, Höhenprofil — und dazwischen einem Feld schmaler Karten, das sich
 * selbst in Spalten legt. Die breiten Blöcke brauchen die ganze Breite: das
 * Urteil, weil es die Hauptaussage ist, das Profil, weil eine gestauchte
 * Zeitachse unlesbar wird.
 */
.report {
  margin-top: var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/*
 * Kartenfeld.
 *
 * Vorher stand hier ein `auto-fit`-Raster, und das hat sichtbar schlecht
 * ausgesehen: ein Raster richtet Karten in Reihen aus, und eine Reihe ist so
 * hoch wie ihre höchste Karte. Neben der langen Schatten-Karte klaffte
 * dadurch eine Lücke von mehreren hundert Pixeln, und die nächste Reihe fing
 * erst darunter an statt sie zu füllen.
 *
 * `grid-auto-flow: dense` hätte das nicht gelöst — das sortiert Karten in
 * bestehende Lücken um, aber die Lücke hier entsteht ja erst dadurch, dass
 * die Reihe auf gleiche Höhe gestreckt wird.
 *
 * Deshalb Spalten statt Raster: `columns` verteilt die Karten von oben nach
 * unten in Spalten, ohne Reihenbindung. Jede Karte schließt direkt an die
 * darüber an — das gesuchte Mauerwerk-Muster. Sobald `grid-template-rows:
 * masonry` breit unterstützt ist, kann das hier wieder ein Raster werden;
 * bis dahin ist das die einzige Fassung ohne JavaScript.
 *
 * Die Spaltenzahl ergibt sich aus `column-width`: der Browser nimmt so viele
 * Spalten, wie bei mindestens 22rem Breite hineinpassen. Kein Breakpoint,
 * keine geratene Gerätegröße — auf dem Telefon wird das eine Spalte, auf dem
 * Schreibtisch drei.
 */
.report-karten {
  /* Rückfall ohne JavaScript: `columns` steht den Karten immerhin
     nebeneinander, wenn auch mit Lücken. Sobald `kachelfeld.js` gelaufen ist,
     stehen hier Spalten-Elemente, und die Regel darunter übernimmt. */
  columns: 22rem;
  column-gap: var(--sp-5);
}

/* Ab hier hat `kachelfeld.js` die Karten in Spalten einsortiert.
   `--kachel-spalten` setzt das Modul auf die Zahl, die es tatsächlich
   gewählt hat — sie steht damit an genau einer Stelle. */
.report-karten[data-geordnet="ja"] {
  columns: auto;
  display: grid;
  grid-template-columns: repeat(var(--kachel-spalten, 3), minmax(0, 1fr));
  gap: var(--sp-5);
  align-items: start;
}

/* Eine Spalte ist ein senkrechter Stapel. Die Karten darin schließen direkt
   aneinander an — das ist der ganze Zweck der Übung. */
.kachelspalte {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  min-width: 0;
}

/*
 * `break-inside: avoid` ist der Kern: ohne das reißen die Spalten eine Karte
 * mitten im Text auseinander und setzen den Rest oben in der nächsten Spalte
 * fort. Bei Fließtext ist das gewollt, bei Karten mit Rahmen und Hintergrund
 * sieht es aus wie ein Darstellungsfehler.
 *
 * `margin-bottom` statt `gap`: der senkrechte Abstand in einem Spaltenfluss
 * kommt vom Aussenabstand der Elemente, `gap` wirkt dort nur waagrecht.
 */
/* Gilt nur für den Rückfall ohne JavaScript: im Spaltenfluss kommt der
   senkrechte Abstand vom Aussenabstand, `gap` wirkt dort nur waagrecht, und
   ohne `break-inside` reißt es Karten mittendrin auseinander. Sobald das Feld
   geordnet ist, übernimmt das `gap` der Spalten — deshalb die Einschränkung
   auf den ungeordneten Zustand, sonst stünde unter jeder Karte der doppelte
   Abstand. */
.report-karten:not([data-geordnet="ja"]) > * {
  break-inside: avoid;
  margin-bottom: var(--sp-5);
}

/* Gleiches Innenmaß wie `.block`: bei unterschiedlichem Padding startet der
   Text der Urteilskarte weiter innen, und sie wirkt schmäler als die Karten
   darunter, obwohl beide exakt gleich breit sind (gemessen: 358 px). */
/*
 * Das Urteil ist der einzige Block, den man gelesen haben muss. Es bekommt
 * deshalb die größte Schrift der Seite und einen farbigen Rand links statt
 * einer vollflächigen Tönung: die Fläche färbte auf 1360 px Breite den halben
 * Bildschirm rot ein und ließ eine machbare Tour wie einen Fehler aussehen.
 */
.verdict {
  border-radius: var(--radius);
  padding: var(--sp-6) var(--sp-8);
  border: 1px solid var(--line);
  border-left: 4px solid;
  box-shadow: var(--shadow);
  min-width: 0;
  background: var(--surface);
}

.verdict.gut { border-left-color: var(--gut); }
.verdict.mittel { border-left-color: var(--mittel); }
.verdict.schlecht { border-left-color: var(--schlecht); }

.verdict h2 {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-2xl);
  line-height: 1.15;
  letter-spacing: -.02em;
  font-weight: var(--fw-bold);
  display: flex; align-items: center; gap: var(--sp-3);
}
.verdict.gut h2 { color: var(--gut); }
.verdict.mittel h2 { color: var(--mittel); }
.verdict.schlecht h2 { color: var(--schlecht); }

.verdict .meta {
  color: var(--ink-soft);
  font-size: var(--fs-md);
  margin: 0 0 var(--sp-5);
  max-width: 70ch;
}
.verdict ul { margin: 0; padding-left: var(--sp-5); }
.verdict li { margin: var(--sp-2) 0; }

/* `min-width: 0` an jeder Karte: Grid-Items wachsen sonst mit ihrem breitesten
   unteilbaren Kind mit, statt es scrollen zu lassen. */
.block {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-6);
  box-shadow: var(--shadow);
  min-width: 0;
}

/* Überschriften sitzen auf einer eigenen Zeile über einer Haarlinie: bei
   sechs Karten nebeneinander ist der Kartentitel sonst kaum vom Inhalt zu
   unterscheiden, und das Raster wirkt wie eine Textwüste. */
.block h3 {
  margin: 0 0 var(--sp-5);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: -.01em;
  display: flex; align-items: center; gap: var(--sp-2);
}

/* Untergrund-Balken */
.bar { display: flex; height: 28px; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--line); }
.bar span { display: block; }
/* Drei Untergrund-Klassen, von „hart" nach „weich" auch farblich gestuft:
   Grau = Teer, Sandbraun = Schotter/Forstweg, Grün = gewachsener Boden. */
.bar .hard { background: #8a8178; }
.bar .forst { background: #b99457; }
.bar .natur { background: var(--accent); }
.bar .unknown { background: repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 6px, var(--line) 6px, var(--line) 12px); }

.bar .shaded { background: var(--accent); }
.bar .sunny { background: #e0a838; }
.swatch.shaded { background: var(--accent); }
.swatch.sunny { background: #e0a838; }

/* Sonnenstand-Verlauf: Balkenhöhe = Höhenwinkel */
.shade-lead { margin: 0 0 var(--sp-3); }

/* `overflow-x: auto` allein genügt nicht: ohne `min-width: 0` darf der
   Behälter nicht unter die Summe seiner Kinder schrumpfen und schiebt
   stattdessen die ganze Seite auf. Bei 9 Zeitschritten à 2,6 rem waren das
   419 px in einer 358 px breiten Karte — gemessen 475 px Seitenbreite auf
   einem 390-px-Schirm, also waagerechtes Wackeln im ganzen Bericht. */
.sun-timeline {
  display: flex; align-items: flex-end; gap: var(--sp-1);
  margin-top: var(--sp-4); padding-top: var(--sp-2);
  overflow-x: auto;
  min-width: 0;
  /* Nicht am Rand abschneiden, sondern sichtbar auslaufen lassen. */
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
}
.sun-step { flex: 0 0 auto; min-width: 2.6rem; display: flex; flex-direction: column; align-items: center; height: 5rem; justify-content: flex-end; }
.sun-bar { width: 100%; max-width: 1.6rem; background: linear-gradient(#e0a838, #c98a1e); border-radius: 4px 4px 0 0; min-height: 2px; }
/* Nicht unter 12 px: darunter wird die Uhrzeit im Stehen, mit Sonne auf dem
   Schirm und Kind auf dem Arm, nicht mehr zuverlässig gelesen. */
.sun-t { font-size: var(--fs-xs); color: var(--ink-soft); margin-top: var(--sp-1); font-variant-numeric: tabular-nums; }
.sun-a { font-size: var(--fs-xs); color: var(--ink-soft); font-variant-numeric: tabular-nums; }

.start-control { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.start-control input {
  flex: 1 1 8rem;
  min-height: 2.9rem;
  padding: var(--sp-2) var(--sp-3);
  font: inherit;
  /* Unter 16px zoomt iOS Safari beim Antippen in das Feld hinein und kommt
     nicht von allein wieder heraus. `font: inherit` erbt hier --fs-sm, das
     bei 15px deckelt — deshalb der ausdrückliche Boden. */
  font-size: max(16px, var(--fs-sm));
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  /* Ohne das erben die Datums-Felder in iOS Safari die Systemfarbe und
     verschwinden im dunklen Modus fast vollständig. */
  color-scheme: light dark;
}

.legend { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); margin-top: var(--sp-3); font-size: var(--fs-sm); }
.legend div { display: flex; align-items: center; gap: var(--sp-1); }
.swatch { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--line); flex: none; }
.swatch.hard { background: #8a8178; }
.swatch.forst { background: #b99457; }
.swatch.natur { background: var(--accent); }
.swatch.unknown { background: repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 4px, var(--line) 4px, var(--line) 8px); }

.note { color: var(--ink-soft); font-size: var(--fs-sm); margin: var(--sp-3) 0 0; }

/* Stopp-Liste */
.stops { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.stops li { display: flex; align-items: baseline; gap: var(--sp-3); padding: var(--sp-2) 0; border-bottom: 1px solid var(--line); }
.stops li:last-child { border-bottom: 0; }
.stops .km { font-variant-numeric: tabular-nums; color: var(--ink-soft); min-width: 4.2rem; font-size: var(--fs-sm); }
.stops .ico { font-size: var(--fs-lg); }
.stops .txt strong { font-weight: var(--fw-medium); }
.stops .off { color: var(--ink-soft); font-size: var(--fs-sm); }

.empty { color: var(--ink-soft); margin: 0; }

/* Der Bericht darf 1360 px breit sein, Fließtext nicht: über etwa 85 Zeichen
   je Zeile findet das Auge beim Umbruch den Anschluss nicht mehr. Deshalb
   bekommt die Fußzeile — der einzige Ort mit langem Fließtext über die volle
   Breite — eine eigene Lesebreite. */
.foot { margin-top: var(--sp-12); color: var(--ink-soft); font-size: var(--fs-sm); }
/* 68 statt 78: `ch` misst die Breite der Ziffer Null, und deutscher Fließtext
   ist im Schnitt schmaler — bei 78ch standen gemessen 94 Zeichen in der Zeile,
   also über der Grenze, ab der das Auge beim Umbruch den Anschluss verliert. */
.foot p { max-width: 68ch; }
.foot a { color: inherit; }
.foot-warn { border-left: 3px solid var(--line); padding-left: var(--sp-3); }

/*
 * Auf schmalen Schirmen bleibt die Kilometer-Angabe in derselben Zeile.
 * Ein Umbruch auf eine eigene Zeile verdoppelt die Höhe jedes Eintrags —
 * bei einem Dutzend Ausstiegen scrollt man dann sinnlos.
 */
@media (max-width: 30rem) {
  .stops .km { min-width: 3.6rem; font-size: var(--fs-sm); }
  .stops li { gap: var(--sp-2); }
  .stops .txt { min-width: 0; }
}

/* ==========================================================================
   Strichzeichen statt Bildzeichen
   Emoji werden auf jedem Gerät anders gerendert und lassen sich nicht auf die
   Textfarbe abstimmen; ein Bericht sieht damit aus wie ein Chat. Die Icons
   erben `currentColor` und passen sich damit hellem wie dunklem Modus an.
   ========================================================================== */

.ic { flex: none; vertical-align: -.18em; }

.drop-icon { color: var(--accent); margin-bottom: var(--sp-1); }

.stops .ico { display: inline-flex; align-items: center; color: var(--accent); }
.stops li { align-items: center; }

.verdict h2 { display: flex; align-items: center; gap: var(--sp-2); }
.verdict-ic { flex: none; }

/* Begründungen: Sachaussage und Einschränkung der Datenlage sehen anders aus.
   Sonst liest sich "dafür fehlen uns die Daten" wie ein Mangel der Tour. */
.reasons { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-1); }
.reasons .rs { display: flex; gap: var(--sp-2); align-items: baseline; }
.reasons .rs.fakt::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: .45; flex: none;
  transform: translateY(-.15em);
}
.reasons .rs.datenlage { color: var(--ink-soft); font-size: var(--fs-sm); }

/* Wetter steht optisch zwischen beidem: es ist eine echte Aussage über den
   Tag (also nicht ausgegraut wie die Datenlage), aber sie gilt nur für diesen
   einen Termin — der senkrechte Strich markiert genau diese Befristung. */
.reasons .rs.wetter {
  border-left: 3px solid var(--line);
  padding-left: var(--sp-2);
  margin-left: var(--sp-1);
}
.rs-ic { flex: none; transform: translateY(.2em); }

/* ==========================================================================
   Wetter
   ========================================================================== */

/* Sechs Spalten passen auf kein Telefon. Statt Spalten zu opfern, darf die
   Tabelle für sich waagerecht scrollen — die Seite selbst bleibt ruhig. */
.wx-scroll { overflow-x: auto; margin-top: var(--sp-2); -webkit-overflow-scrolling: touch; }

.wx { border-collapse: collapse; width: 100%; min-width: 26rem; font-size: var(--fs-sm); }
.wx th, .wx td { padding: var(--sp-2) var(--sp-2); text-align: left; white-space: nowrap; }
.wx thead th {
  font-weight: var(--fw-medium); font-size: var(--fs-xs); letter-spacing: .02em;
  color: var(--ink-soft); border-bottom: 1px solid var(--line);
}
/* Zeilentrenner statt Zebrastreifen: bei sechs schmalen Spalten sind Flächen
   unruhiger als Linien. */
.wx tbody tr + tr td { border-top: 1px solid var(--line); }
.wx tbody td:first-child { font-variant-numeric: tabular-nums; color: var(--ink-soft); }
/* Mit Höhenspalte wird die Tabelle eine Spalte breiter — sonst quetscht sie
   sich auf dem Handy in 26rem und die Temperatur bricht um. */
.wx[data-cols="7"] { min-width: 31rem; }

/* Der Modellwert unter der korrigierten Temperatur: klein und zurückgenommen,
   weil er nur zum Wiedererkennen da ist ("meine Wetter-App sagt 18°"), nicht
   zum Ablesen. Eigene Zeile, damit die Spalte nicht doppelt so breit wird. */
.wx-roh { display: block; font-size: var(--fs-xs); color: var(--ink-soft); }

/* Erklärt, warum die Zahl von der Wetter-App abweicht. Gleiche Randmarkierung
   wie .note-cloud: beides relativiert Zahlen, die darüber stehen. */
.note-hoehe { border-left: 3px solid var(--line); padding-left: var(--sp-3); }

/* Die labile Wetterlage. Farbiger Rand statt der grauen Linie der anderen
   Hinweise: dieser Absatz steht genau dann da, wenn die Vorhersage darüber
   schweigt — mit derselben Zurückhaltung wie eine Fußnote gestaltet, würde er
   in einem trockenen Bericht schlicht übersehen. Bernstein und nicht Rot: es
   ist eine Möglichkeit, keine Vorhersage, und Rot ist für gemeldete Gewitter
   reserviert. */
.note-neigung {
  border-left: 3px solid #e8b53f;
  padding-left: var(--sp-3);
}

.h-ic { flex: none; vertical-align: -.15em; margin-right: var(--sp-1); }

/* Steht im Sonne-&-Schatten-Block und relativiert dessen Zahlen — dieselbe
   Randmarkierung wie bei den Wetter-Begründungen, damit erkennbar bleibt:
   gilt nur für diesen Tag. */
.note-cloud { border-left: 3px solid var(--line); padding-left: var(--sp-3); }

/* ==========================================================================
   Tourenprofil — die zentrale Ansicht
   Höhe, Untergrund, Schatten, Steigung, Stopps und Wetter auf einer Achse.
   Bewusst 2D: in einer 3D-Ansicht verdeckt der Berg sich selbst und "wie
   steil wird es bei km 4" ist schwerer abzulesen, nicht leichter.
   ========================================================================== */

.prof-intro {
  margin: 0 0 var(--sp-5);
  color: var(--ink-soft);
  max-width: 70ch;
}

/* --- Kennzahlenreihe ----------------------------------------------------
 * Die einzige Stelle im Bericht mit großen Zahlen. Wenn Zahlen überall groß
 * sind, ist keine mehr wichtig — deshalb bleibt der Rest des Berichts bei
 * Fließtextgröße. `auto-fit` statt fester Spalten: auf dem Handy stehen zwei
 * nebeneinander, auf dem Schreibtisch vier, ohne einen einzigen Breakpoint. */
.prof-stats {
  display: grid;
  /* Gleich breite Spalten statt inhaltsabhängiger: „1117–1719" ist dreimal so
     breit wie „596" und schöbe alle anderen Werte aus dem Raster. Die
     Mindestbreite ist an dem längsten Wert bemessen. */
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-4);
  padding: var(--sp-4) 0 var(--sp-5);
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: var(--sp-5);
}

.prof-stat { display: flex; flex-direction: column; gap: var(--sp-1); }

.prof-stat-v {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

/* Die Einheit klein und in gedämpfter Farbe: "596" ist die Information,
   "Hm" nur die Maßeinheit — beide gleich groß zu setzen halbiert die
   Wirkung der Zahl. */
.prof-stat-u {
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  color: var(--ink-soft);
  margin-left: 3px;
  letter-spacing: 0;
}

/* Eine Stufe kleiner für den einen Wert, der aus zwei Zahlen besteht. */
.prof-stat-v.is-wide { font-size: var(--fs-2xl); }

.prof-stat-l {
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}

/* --- Ebenen-Schalter -----------------------------------------------------
 * Echte Checkboxen, optisch als Chips. Die Box selbst bleibt sichtbar statt
 * `appearance: none`: ein Häkchen ist die Form, die jeder als "an/aus"
 * erkennt, und sie bringt Tastatur- und Screenreader-Bedienung mit. */
.tp-layers {
  border: 0;
  margin: 0 0 var(--sp-5);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
}

.tp-layers-legend {
  padding: 0;
  margin-right: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ink-soft);
  float: left;
  line-height: 32px;
}

.tp-layer {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  cursor: pointer;
  /* 32 px hoch reicht hier: die Chips liegen im Bericht, nicht im
     Haupt-Bedienweg, und man trifft sie im Sitzen. */
  min-height: 32px;
  transition: border-color .15s, background .15s, color .15s;
  user-select: none;
}

.tp-layer:hover { border-color: var(--accent); }
.tp-layer:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Ein eingeschalteter Chip ist gefüllt, kein bloß dunkler umrandeter:
   der Unterschied muss aus zwei Metern Abstand erkennbar sein. */
.tp-layer.on {
  background: var(--gut-bg);
  border-color: var(--accent);
  color: var(--accent-strong);
  font-weight: var(--fw-medium);
}

.tp-layer input { width: 15px; height: 15px; accent-color: var(--accent); margin: 0; }
.tp-layer-ic { flex: none; }

/* --- Das Diagramm --------------------------------------------------------
 * Auf sehr schmalen Schirmen darf es seitlich scrollen, statt bis zur
 * Unlesbarkeit zusammengedrückt zu werden. `min-width: 0` ist Pflicht: ohne
 * das darf der Behälter nicht unter seine Kinder schrumpfen und sprengt die
 * Seitenbreite — genau der Fehler, der die Sonnen-Zeitleiste überlaufen ließ. */
.prof-scroll { overflow-x: auto; min-width: 0; -webkit-overflow-scrolling: touch; }

.tourprofile {
  display: block;
  width: 100%;
  min-width: 340px;
  /* Höhe ergibt sich aus der viewBox, damit die Achsenbeschriftung nicht
     verzerrt: `preserveAspectRatio="xMidYMid meet"` hält die Proportionen,
     anders als das frühere `none`, das Text mitgestreckt hat. */
  height: auto;
}

.tourprofile .tp-area { opacity: .92; }
.tourprofile .tp-area-plain { fill: var(--accent); opacity: .18; }
.tourprofile .tp-ridge { stroke: var(--ink); stroke-width: 2; opacity: .7; fill: none; }
.tourprofile .tp-grid { stroke: var(--line); stroke-width: 1; }
.tourprofile .tp-rowline { stroke: var(--line-soft); stroke-width: 1; }
.tourprofile .tp-ax { fill: var(--ink-soft); font-size: 13px; }
.tourprofile .tp-ax-y { text-anchor: end; }
.tourprofile .tp-ax-x { text-anchor: middle; }
.tourprofile .tp-ax-unit { text-anchor: end; }
.tourprofile .tp-rowlabel { font-size: 12px; }
.tourprofile .tp-wx { text-anchor: middle; font-size: 11px; fill: var(--ink); }

/* Der längste Anstieg am Stück — die Stelle, an der Kinder getragen werden.
   Ein Streifen auf der Grundlinie statt einer Fläche über dem Profil: die
   Fläche sah aus wie ein Darstellungsfehler und verdeckte den Aufstieg. */
.tourprofile .tp-climb { fill: var(--schlecht); opacity: .9; }

/* Marker: weißer Ring, damit sie sich auch auf einer dunklen Profilfläche
   absetzen, und das Symbol in der Kartenfarbe statt in Weiß — ein weißes
   Symbol auf farbigem Kreis verliert bei 8 px Radius jede Kontur. */
.tourprofile .tp-marker circle { stroke: var(--surface); stroke-width: 1.5; }
.tourprofile .tp-marker-ic { stroke: #fff; stroke-width: 3.2; fill: none; }

/* --- Legende -------------------------------------------------------------
 * Nach Ebenen gruppiert statt als eine lange Reihe: bei eingeschalteter
 * Steigung stehen sonst elf Einträge nebeneinander und man findet nicht
 * mehr, welche Farbe zu welcher Ebene gehört. */
.tp-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-8);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
  font-size: var(--fs-sm);
}

.tp-legend-group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-4); }

.tp-legend-title {
  font-weight: var(--fw-medium);
  color: var(--ink);
  /* Der Doppelpunkt gehört nicht ins Markup: er ist Typografie, keine
     Information, und im Screenreader stört er. */
}
.tp-legend-title::after { content: ":"; color: var(--ink-soft); }

.tp-legend-item { display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--ink-soft); }
.tp-sw { width: 12px; height: 12px; border-radius: 3px; flex: none; display: inline-block; }

.note-climb { border-left: 3px solid var(--schlecht); padding-left: var(--sp-3); }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tourprofile .tp-area { opacity: .78; }
  :root:not([data-theme="light"]) .tourprofile .tp-marker-ic { stroke: #fff; }
}

/* Dieselben Werte, wenn Dunkel ausdrücklich gewählt ist — der Block
   oben greift nur, wenn das Betriebssystem dunkel steht. */
:root[data-theme="dark"] .tourprofile .tp-area { opacity: .78; }
:root[data-theme="dark"] .tourprofile .tp-marker-ic { stroke: #fff; }


/* ==========================================================================
   Startzeit-Regler
   Beantwortet die einzige Frage, die man vor einer Sommertour wirklich stellt:
   wann losgehen. Die Kurve zeigt die Antwort, bevor man überhaupt zieht.
   ========================================================================== */

.start-slider {
  margin-top: var(--sp-5);
  padding: var(--sp-4);
  background: var(--surface-2);
  border-radius: var(--radius);
}

.slider-head {
  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
  align-items: baseline; justify-content: space-between;
}
.slider-title { font-weight: var(--fw-medium); }
.slider-val { color: var(--ink-soft); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

.daycurve { display: block; width: 100%; height: 70px; margin: var(--sp-2) 0 var(--sp-1); overflow: visible; }
.daycurve-line { stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.daycurve .best-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 2.5; }
.daycurve .needle { stroke: var(--ink); stroke-width: 2; opacity: .55; }
/* Startzeiten, bei denen man im Dunkeln ankäme — als Option wertlos. */
.daycurve .dark-zone { fill: var(--ink); opacity: .07; }

.start-slider input[type="range"] { width: 100%; margin: 0; accent-color: var(--accent); }

.slider-scale {
  display: flex; justify-content: space-between;
  color: var(--ink-soft); font-size: var(--fs-xs); margin-top: var(--sp-1);
  font-variant-numeric: tabular-nums;
}

.slider-out { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); }

/* Ein Knopf, der wie ein Link aussieht: die Aktion ist nebensächlich genug,
   dass sie den Blick nicht vom Regler ziehen darf. */
.linklike {
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; text-decoration: underline;
  cursor: pointer;
}

.note-limit { border-left: 3px solid var(--line); padding-left: var(--sp-3); }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .daycurve .dark-zone { fill: #fff; opacity: .08; }
}

/* Dieselben Werte, wenn Dunkel ausdrücklich gewählt ist — der Block
   oben greift nur, wenn das Betriebssystem dunkel steht. */
:root[data-theme="dark"] .daycurve .dark-zone { fill: #fff; opacity: .08; }


/* Auf dem Handy fällt die Kilometer-Achse enger aus. */
@media (max-width: 30rem) {
  .profile { min-width: 300px; }
  .slider-val { font-size: var(--fs-sm); }
}

/* ==========================================================================
   Rechtsseiten (Impressum, Datenschutz)
   Reiner Fließtext — hier gilt die Lesebreite, nicht die Rasterbreite des
   Berichts. Über etwa 85 Zeichen je Zeile findet das Auge beim Umbruch den
   Anschluss nicht mehr, und genau solche Seiten liest man am Stück.
   ========================================================================== */

/* Die Rechtsseiten nutzen kein App-Gerüst — sie sind reine Dokumente und
   brauchen weder Seitenleiste noch Kopfzeile. */
.wrap {
  max-width: 1360px;
  margin: 0 auto;
  padding: clamp(var(--sp-4), 3vw, var(--sp-10)) clamp(var(--sp-4), 3vw, var(--sp-8)) var(--sp-16);
}
.wrap-text { max-width: 780px; }

.back { margin: 0 0 var(--sp-5); font-size: var(--fs-sm); }
.back a { color: var(--ink-soft); }

.legal h2 {
  font-size: var(--fs-xl);
  margin: var(--sp-10) 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line-soft);
}
.legal h2:first-child { margin-top: 0; }

.legal h3 {
  font-size: var(--fs-lg);
  margin: var(--sp-8) 0 var(--sp-2);
  font-weight: var(--fw-bold);
}

.legal p { margin: 0 0 var(--sp-4); }
.legal hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-12) 0; }
.legal code { background: var(--surface-2); padding: 2px 6px; border-radius: 4px; font-size: .9em; }

/* Die Tabelle der Drittdienste darf für sich scrollen, statt die Seite
   aufzuschieben — dieselbe Regel wie bei der Wettertabelle. */
.legal-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-sm);
  display: block;
  overflow-x: auto;
}
.legal-table th, .legal-table td {
  padding: var(--sp-2) var(--sp-3);
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
.legal-table th { font-weight: var(--fw-medium); color: var(--ink-soft); }

.legal-date { color: var(--ink-soft); font-size: var(--fs-sm); margin-top: var(--sp-8); }

/* Rechtslinks im Fuß der Hauptseite. */
/* Eine Navigationszeile, kein Fließtext — die beiden Links stehen allein im
   Absatz und werden angetippt, nicht gelesen. Deshalb gilt hier die
   44px-Regel, anders als beim Link mitten in einem Satz darüber. */
.foot-legal { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }
.foot-legal a { display: inline-flex; align-items: center; min-height: 44px; }

/* ==========================================================================
   Erklärteil für Erstbesucher
   Sichtbar, solange kein Bericht da ist. Danach im Weg — `main.js` blendet
   ihn aus, sobald eine Datei ausgewertet wurde.
   ========================================================================== */

.intro { margin-top: var(--sp-12); }

.intro h2 {
  font-size: var(--fs-xl);
  margin: var(--sp-12) 0 var(--sp-4);
  letter-spacing: -.015em;
  /* Überschriften dürfen umbrechen, aber nicht auf drei Zeilen: bei 26ch
     zerfiel „Zehn Kilometer, 600 Höhenmeter — und trotzdem weiß man nichts"
     in drei kurze Zeilen und verlor den Satzrhythmus. */
  max-width: 40ch;
}
.intro h2:first-child { margin-top: 0; }

.intro-lead {
  font-size: var(--fs-lg);
  color: var(--ink-soft);
  max-width: 62ch;
  margin: 0 0 var(--sp-8);
}

/* Drei Spalten auf dem Schreibtisch, eine auf dem Handy — ohne Breakpoint.
   Die 280px Mindestbreite sind an der längsten Überschrift bemessen. */
.intro-grid {
  display: grid;
  /* 280px waren zwei Pixel zu viel: der Erklärteil ist auf 880px begrenzt,
     drei Spalten bräuchten damit 3×280 + 2×24 = 888px. Das Raster brach auf
     2+1 um, und eine einzelne Karte in der zweiten Reihe sieht nicht nach
     Absicht aus, sondern nach Fehler. 260px lassen die drei nebeneinander
     stehen und ändern sonst nichts. */
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: var(--sp-6);
}

.intro-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-6);
}

.intro-item h3 {
  font-size: var(--fs-lg);
  margin: 0 0 var(--sp-2);
  font-weight: var(--fw-bold);
}
.intro-item p { margin: 0; color: var(--ink-soft); }

/* Fragen und Antworten als Definitionsliste, nicht als Überschriften-Kette:
   das ist die Auszeichnung, die den Zusammenhang zwischen Frage und Antwort
   auch für Screenreader und Suchmaschinen trägt. */
/* Fließtext im Erklärteil. Dieselbe Zeilenlänge wie die FAQ, damit die
   Abschnitte untereinander eine gemeinsame Kante behalten. */
.intro-text {
  margin: 0 0 var(--sp-4);
  max-width: 68ch;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* --- Ablauf in drei Schritten ------------------------------------------- */

/* Nummerierung selbst gesetzt statt über den Listenpunkt: der eingebaute
   Marker lässt sich nicht formatieren, und eine Ziffer, die neben statt über
   dem Text steht, bricht auf schmalen Geräten die Ausrichtung. */
.schritte {
  list-style: none;
  counter-reset: schritt;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-5);
  /* Dieselbe Mindestbreite wie `.intro-grid` — die beiden Blöcke stehen
     untereinander und sollen an denselben Stellen umbrechen. */
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.schritte li {
  counter-increment: schritt;
  padding-top: var(--sp-4);
  border-top: 2px solid var(--line-soft);
}

.schritte li::before {
  content: counter(schritt);
  display: block;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  margin-bottom: var(--sp-2);
}

.schritte h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
}
.schritte p { margin: 0; color: var(--ink-soft); font-size: var(--fs-sm); line-height: 1.55; }

/* --- Vergleichstabelle --------------------------------------------------- */

/* Der Behälter scrollt, nicht die Seite: eine Tabelle mit drei Spalten passt
   auf einem 360-px-Telefon nicht, und die Alternative — Spalten umbrechen —
   zerstört genau die Gegenüberstellung, um die es geht. */
.vergleich-huelle {
  max-width: 68ch;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Ohne diese Zeile schneidet der Fokusrahmen einer Zelle am Rand ab. */
  padding-bottom: var(--sp-2);

  /* Ein Schatten am rechten Rand, solange noch etwas kommt.
   *
   * Ohne ihn war die dritte Spalte auf dem Telefon schlicht unsichtbar: man
   * sah „Tourenportal: beantwortet“ und hielt die Tabelle für vollständig —
   * ausgerechnet die Wandercheck-Spalte, um die es geht, blieb verborgen.
   *
   * Die zwei Verläufe sind aneinandergehängt: der erste hängt am Inhalt
   * (`local`) und verschwindet beim Scrollen ans Ende, der zweite steht fest
   * am Behälter und deckt ihn ab, solange nicht gescrollt wurde. Das ist der
   * übliche Weg, ohne JavaScript zu erkennen, ob noch etwas kommt. */
  background:
    linear-gradient(to right, transparent calc(100% - 3rem), var(--surface-2)) local,
    linear-gradient(to right, transparent calc(100% - 3rem), transparent) scroll;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

/* Auf breiten Bildschirmen passt die Tabelle ohnehin — dort wären Schatten
   und Wisch-Hinweis nur Rauschen. */
@media (min-width: 46rem) {
  .vergleich-huelle { background: none; }
  .vgl-wisch { display: none; }
}

.vergleich {
  border-collapse: collapse;
  width: 100%;
  /* Unterhalb dieser Breite werden die Zellen unlesbar schmal — dann lieber
     scrollen lassen. */
  min-width: 34rem;
  font-size: var(--fs-sm);
}

.vgl-titel {
  text-align: left;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  padding-bottom: var(--sp-2);
}

.vgl-wisch {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}

.vergleich th,
.vergleich td {
  text-align: left;
  padding: var(--sp-3);
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

.vergleich thead th {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--ink-soft);
  border-bottom-color: var(--line);
}

/* Die Fragen in der ersten Spalte sind der Anker — sie tragen die
   Zeilenbedeutung und dürfen nicht wie Nebentext aussehen. */
.vergleich tbody th {
  font-weight: var(--fw-normal);
  color: var(--ink);
  padding-left: 0;
}

/* Farbe allein trägt die Aussage nicht: der Text sagt bereits „beantwortet"
   gegen „nicht die Aufgabe". Die Farbe verstärkt nur, was dasteht — sonst
   ginge die Tabelle für Farbfehlsichtige verloren. */
.vgl-ja { color: var(--accent-strong); font-weight: var(--fw-medium); }
.vgl-nein { color: var(--ink-soft); }

.faq { margin: 0; max-width: 68ch; }
.faq dt {
  font-weight: var(--fw-bold);
  margin-top: var(--sp-6);
  font-size: var(--fs-lg);
}
.faq dt:first-child { margin-top: 0; }
.faq dd { margin: var(--sp-2) 0 0; color: var(--ink-soft); }

/* ==========================================================================
   Hero-Kennzahlen im Urteil
   Fünf Werte, jeder mit Zeichen, Zahl und Bezug. Die Zahl allein sagt nichts:
   „10,0 km" wird erst durch „über Faustregel (9,0 km)" zur Aussage.
   ========================================================================== */

/* `auto-fit` erzeugte bei fünf Werten eine Reihe zu drei plus eine zu zwei,
   mit einer leeren Zelle daneben — das sieht nach Fehler aus, nicht nach
   Layout. `auto-fill` mit fester Spaltenzahl geht nicht, weil die Anzahl der
   Werte von den vorhandenen Daten abhängt. Also Flexbox: alle in eine Reihe,
   jede Zelle mindestens so breit wie ihr Inhalt, Umbruch nur wenn es wirklich
   nicht mehr passt — und dann ohne Loch, weil Flex keine Raster füllt. */
.hero-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin: 0;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--line-soft);
}

.hm {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-4);
  background: var(--surface);
  flex: 1 1 120px;
  min-width: 0;
}

.hm-ic { color: var(--accent); }
/* Auffällige Werte bekommen ein warmes Zeichen — nicht die ganze Zelle:
   fünf getönte Flächen nebeneinander sind eine Ampelwand, keine Hierarchie. */
.hm.warn .hm-ic { color: var(--mittel); }

.hm-v {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
}
.hm-u {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ink-soft);
  margin-left: 2px;
  letter-spacing: 0;
}
.hm-l { font-size: var(--fs-xs); color: var(--ink-soft); line-height: 1.35; }

/* ==========================================================================
   Ringdiagramm
   ========================================================================== */

.donut-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-6);
}

.donut { width: 140px; height: 140px; flex: none; }
.donut .dn-track { fill: none; stroke: var(--line-soft); stroke-width: 18; }
.donut .dn-seg {
  fill: none;
  stroke-width: 18;
  /* Ohne die Drehung beginnt der erste Abschnitt rechts auf drei Uhr —
     gelesen wird ein Ring aber von oben. */
  transform: rotate(-90deg);
  transform-origin: 70px 70px;
}
.donut .dn-v {
  text-anchor: middle;
  font-size: 24px;
  font-weight: 700;
  fill: var(--ink);
}
.donut .dn-l { text-anchor: middle; font-size: 11px; fill: var(--ink-soft); }

.donut-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  min-width: 0;
  flex: 1 1 200px;
}
.donut-legend li { display: flex; align-items: baseline; gap: var(--sp-2); }
.donut-legend b { font-variant-numeric: tabular-nums; min-width: 3.4em; }

/* ==========================================================================
   Kartenansicht
   Flach statt 3D — Begründung in `lib/karte.js`, 3D als offener Punkt in
   MASTER_ROADMAP.md. Die Farben sind dieselben wie im Tourenprofil.
   ========================================================================== */

.map-frame {
  position: relative;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
}

/* Die Höhe folgt der viewBox, die sich nach der Form der Route richtet. Bei
   einer langgezogenen Tour auf einem schmalen Schirm bleiben davon aber
   hundert Pixel übrig — dann ist die Karte ein Strich. `min-height` fängt das
   ab; `object-fit` sorgt dafür, dass die Route dabei zentriert bleibt statt
   sich zu verzerren. */
.karte {
  display: block;
  width: 100%;
  height: auto;
  min-height: 190px;
  object-fit: contain;
}

/* Die helle Unterlinie gibt der Route eine Kontur, damit sie sich auf hellem
   wie dunklem Grund absetzt — ohne sie verschwindet Grün im Dunkelmodus. */
.karte .km-halo {
  fill: none;
  stroke: var(--surface);
  stroke-width: 9;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.karte .km-seg {
  fill: none;
  stroke-width: 5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.karte .km-pin { stroke: var(--surface); stroke-width: 2; }
.karte .km-pin-ic { stroke: #fff; stroke-width: 2.6; }

.karte .km-start { fill: var(--accent); stroke: var(--surface); stroke-width: 3; }
.karte .km-start-dot { fill: var(--surface); }
.karte .km-ziel { fill: var(--ink); stroke: var(--surface); stroke-width: 3; }
.karte .km-ziel-mark { stroke: var(--surface); stroke-width: 2.2; fill: none; stroke-linecap: round; stroke-linejoin: round; }

/* Die Legende sitzt unter dem Bild, nicht darin. Im Entwurf liegt sie über
   der Karte — dort funktioniert das, weil ein Luftbild an den Rändern leer
   ist. Unsere Route füllt die Fläche bis zum Rand, und die Legende lag genau
   auf dem Weg. */
.km-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
  align-items: center;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm);
  background: var(--surface);
  border-top: 1px solid var(--line-soft);
  border-radius: 0;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}
.km-legend-title { font-weight: var(--fw-medium); color: var(--ink); }
.km-legend-item { display: inline-flex; align-items: center; gap: var(--sp-1); }

/* Urteil und Karte — die beiden Elemente, die zusammen die Frage beantworten
   — stehen nebeneinander, sobald beide dafür genug Platz haben.

   Kein Breakpoint: `auto-fit` mit einer Mindestbreite von 26rem entscheidet
   das selbst. Passen zwei Spalten zu je 26rem nicht nebeneinander, wird
   daraus stufenlos eine — eine auf ein Drittel gestauchte Route ist nicht
   mehr lesbar, und ein zerquetschtes Urteil ebenso wenig. */
.report-kopf {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(26rem, 100%), 1fr));
  align-items: start;
}

/* Die räumliche Berglage ist eine Übersicht, kein kleines Gegenstück zum
   Urteil. Im 3D-Modus nimmt sie deshalb die ganze Zeile ein; Karte und Urteil
   bleiben dagegen kompakt nebeneinander. */
.report-kopf > .map-block:has(.map-frame.is-3d) { grid-column: 1 / -1; }

/* ==========================================================================
   Räumliche Ansicht
   Ohne 3D-Engine — die Begründung steht in `lib/karte3d.js`.
   ========================================================================== */

.karte3d { display: block; width: 100%; height: auto; min-height: 200px; }

/* Der Boden: ein Raster, dessen perspektivische Verjüngung die Tiefe zeigt,
   noch bevor man die Route ansieht. Sehr zurückhaltend, sonst konkurriert es
   mit dem, worum es geht. */
.karte3d .d3-grid { stroke: var(--line); stroke-width: 1; opacity: .85; }

/* Der Schatten der Route auf dem Boden. Die Höhe liest man am Abstand
   zwischen Route und Schatten ab — ohne ihn schwebt ein Band im Nichts. */
.karte3d .d3-schatten {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2;
  opacity: .24;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Die Fallinien binden die Route an ihren Schatten. Gestrichelt, nicht
   durchgezogen: sie sind eine Ablesehilfe, kein Gegenstand in der Szene —
   durchgezogen sahen sie aus wie Stützen einer Brücke. */
.karte3d .d3-fall {
  stroke: var(--ink);
  stroke-width: 1;
  opacity: .22;
  stroke-dasharray: 2 3;
}

.karte3d .d3-halo {
  fill: none;
  stroke: var(--surface);
  stroke-width: 8;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.karte3d .d3-seg {
  fill: none;
  stroke-width: 4.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.karte3d .d3-ablauf {
  fill: none;
  stroke: var(--ink);
  stroke-width: 7;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: .42;
}
.karte3d .d3-wanderer {
  fill: var(--accent-strong);
  stroke: var(--surface);
  stroke-width: 3;
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / .28));
}

.karte3d .d3-start { fill: var(--accent); stroke: var(--surface); stroke-width: 2.5; }
.karte3d .d3-ziel { fill: var(--ink); stroke: var(--surface); stroke-width: 2.5; }
.karte3d .d3-skala { fill: var(--ink-soft); font-size: 12px; }
.karte3d .d3-marker circle { stroke: var(--surface); stroke-width: 2.5; }
.karte3d .d3-marker text {
  fill: #fff;
  font-size: 10px;
  font-weight: 800;
  text-anchor: middle;
  pointer-events: none;
}

/* Beim Ziehen darf nichts markiert werden — sonst wählt der Zeiger die
   Beschriftung aus und die Drehung fühlt sich klebrig an. */
.map-frame.is-3d .map-view { cursor: grab; touch-action: none; }
.map-frame.is-3d .map-view.zieht { cursor: grabbing; user-select: none; }

/* --- Bedienelemente über dem Bild --------------------------------------- */

.map-frame { position: relative; }

.track-player {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) 4.8rem;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-soft);
  border-top: 0;
  background: var(--surface);
}
.track-play {
  width: 34px;
  height: 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--accent-strong);
  cursor: pointer;
  font: inherit;
}
.track-play:hover { border-color: var(--accent); }
.track-play:focus-visible, #track-regler:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#track-regler { width: 100%; accent-color: var(--accent-strong); cursor: pointer; }
.track-player output { font-size: var(--fs-sm); font-variant-numeric: tabular-nums; text-align: right; color: var(--ink-soft); }

.map-switch {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  display: flex;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.ms-btn {
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  padding: 0 var(--sp-4);
  min-height: 34px;
  cursor: pointer;
}
.ms-btn + .ms-btn { border-left: 1px solid var(--line); }
.ms-btn:hover { color: var(--ink); }
.ms-btn.on { background: var(--gut-bg); color: var(--accent-strong); }
.ms-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.map-tools {
  position: absolute;
  top: var(--sp-3);
  right: var(--sp-3);
  display: grid;
  gap: var(--sp-1);
}

.mt-btn {
  width: 34px; height: 34px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-md);
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow);
}
.mt-btn:hover { border-color: var(--accent); }
.mt-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .karte3d .d3-schatten { opacity: .28; stroke: #000; }
  :root:not([data-theme="light"]) .karte3d .d3-fall { opacity: .2; stroke: #000; }
}

/* Dieselben Werte, wenn Dunkel ausdrücklich gewählt ist — der Block
   oben greift nur, wenn das Betriebssystem dunkel steht. */
:root[data-theme="dark"] .karte3d .d3-schatten { opacity: .28; stroke: #000; }
:root[data-theme="dark"] .karte3d .d3-fall { opacity: .2; stroke: #000; }


/* Kopfzeile während der Auswertung: derselbe Vorgang wie in der Statuszeile,
   nur knapper. Ohne das stand oben weiter die Aufforderung, eine Datei zu
   wählen — während die Datei längst gerechnet wurde. */
.top-file-meta.is-busy {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--ink-soft);
}
.spinner-sm { width: 13px; height: 13px; border-width: 2px; }

/* ==========================================================================
   Platzhalter während der Auswertung
   Ohne sie stünde zwischen Statuszeile und Fußzeile zwanzig Sekunden lang
   eine leere Fläche — die Seite sähe aus, als wäre sie fertig und leer.
   ========================================================================== */

.sk {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  /* Ein zartes Verlaufsband statt einer Animation: auf einem Telefon in der
     Sonne ist Pulsieren kaum zu sehen, und es kostet Rechenzeit, die gerade
     die Auswertung braucht. */
  background-image: linear-gradient(105deg,
    transparent 30%, color-mix(in srgb, var(--line-soft) 60%, transparent) 50%, transparent 70%);
}

/* Die Platzhalter tragen dieselben Mindesthöhen wie die Blöcke, die sie
   ersetzen — sonst springt die Seite beim Einsetzen des Berichts. Sie liegen
   im selben Gerüst wie der fertige Bericht (`.report-kopf` für Urteil und
   Karte), damit der Sprung auch waagrecht ausbleibt. */
.sk-metrics { height: 96px; }
.sk-verdict { min-height: 220px; }
.sk-map { min-height: 260px; }
.sk-profile { min-height: 320px; }

/* ==========================================================================
   Zeiger im Tourenprofil
   Die gemeinsame Achse wird erst richtig lesbar, wenn man an einer Stelle
   alle Werte gleichzeitig bekommt statt senkrecht durch fünf Bänder zu
   schauen und zu schätzen.
   ========================================================================== */

.prof-scroll { position: relative; }

.tourprofile { cursor: crosshair; }

.tp-cursor.is-off, .tp-cursor-dot.is-off { display: none; }
.tp-cursor-line { stroke: var(--ink); stroke-width: 1; opacity: .45; stroke-dasharray: 3 3; }
.tp-cursor-dot { fill: var(--surface); stroke: var(--ink); stroke-width: 2; }

.tp-tip {
  position: absolute;
  top: var(--sp-2);
  /* Der Zeiger darf das Fähnchen nicht selbst treffen — sonst flackert es
     zwischen „drüber" und „daneben", weil der Zeiger sein eigenes Ziel
     verdeckt. */
  pointer-events: none;
  transform: translateX(var(--sp-3));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
  padding: var(--sp-3);
  font-size: var(--fs-sm);
  min-width: 190px;
  max-width: 260px;
  z-index: 2;
}
.tp-tip.is-off { display: none; }
/* Am rechten Rand kippt das Fähnchen auf die andere Seite, sonst ragt es
   aus der Karte und wird abgeschnitten. */
.tp-tip.links { transform: translateX(calc(-100% - var(--sp-3))); }

.tp-tip-km {
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--sp-2);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line-soft);
}

.tp-tip-row { display: flex; align-items: baseline; gap: var(--sp-2); margin-top: var(--sp-1); }
.tp-tip-k { color: var(--ink-soft); min-width: 5.6em; }
.tp-tip-v { font-weight: var(--fw-medium); min-width: 0; }
.tp-sw-leer { background: transparent; border-color: transparent; }
.tp-tip-ic { color: var(--accent); flex: none; transform: translateY(2px); }

.tp-tip-nah {
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--line-soft);
}

/* Öffnungsstatus zur voraussichtlichen Ankunftszeit. Als Marke, nicht als
   Fließtext: „geschlossen" ist die Information, die eine Einkehr im Bericht
   entwertet, und die soll man nicht überlesen. */
.oe {
  display: inline-block;
  margin-left: var(--sp-2);
  padding: 1px var(--sp-2);
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
}
.oe-zu { background: var(--schlecht-bg); color: var(--schlecht); }
.oe-auf { background: var(--gut-bg); color: var(--gut); }

/* Geländeflächen: keine Konturen, sonst überlagert das Liniennetz die
   Schummerung und aus der Landschaft wird ein Drahtgitter. */
.karte3d .d3-terrain { stroke: none; }

/* Knopf zum Nachladen des Geländes. Nicht am unteren Rand: dort liegen
   Filterleiste und Legende, und der Knopf legte sich darüber. Er sitzt
   deshalb links oben unter dem Ansichtsumschalter. */
.btn-terrain {
  position: absolute;
  left: var(--sp-3);
  top: calc(var(--sp-3) + 34px + var(--sp-2));
  min-height: 34px;
  font-size: var(--fs-sm);
  box-shadow: var(--shadow);
  z-index: 1;
}

/* Fehlgeschlagener Ladeversuch: der Knopf sagt es selbst, statt still zu
   bleiben. Ein Knopf, auf den man drückt und bei dem nichts passiert, ist
   das Ärgerlichste an einer Oberfläche. */
.btn-terrain.hat-fehler { border-color: var(--schlecht); color: var(--schlecht); }

/* ==========================================================================
   Vollbild der Kartenansicht
   ========================================================================== */

/* Im Vollbild füllt der Rahmen den Schirm. `:fullscreen` greift nur, wenn der
   Browser die Ansicht tatsächlich übernommen hat — im normalen Fluss bleibt
   alles wie zuvor. */
.map-frame:fullscreen {
  width: 100vw;
  height: 100vh;
  border-radius: 0;
  border: 0;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

/* Der Browser färbt Vollbild-Elemente standardmäßig schwarz. Ohne diese Regel
   säße die helle Karte in einem schwarzen Rahmen. */
.map-frame:fullscreen::backdrop { background: var(--bg); }

.map-frame:fullscreen .map-view {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Im Vollbild darf die Zeichnung die ganze Höhe nutzen — sonst bliebe sie in
   der Höhe stecken, die sie in der Karte hatte, und der halbe Schirm wäre
   leer. */
.map-frame:fullscreen .karte3d,
.map-frame:fullscreen .karte {
  width: 100%;
  height: 100%;
  max-height: none;
}

.map-frame:fullscreen .km-legend {
  border-top: 1px solid var(--line);
  padding: var(--sp-4) var(--sp-6);
}

/* Filter für die Punkte auf der Karte. Unten links, wo sie die Route am
   wenigsten verdecken — und im Vollbild groß genug zum Treffen. */
.map-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--line-soft);
  background: var(--surface);
}

.mf-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  cursor: pointer;
  min-height: 30px;
  user-select: none;
}
.mf-chip:hover { border-color: var(--accent); }
.mf-chip:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.mf-chip.on { background: var(--gut-bg); border-color: var(--accent); color: var(--accent-strong); }
.mf-chip input { width: 13px; height: 13px; accent-color: var(--accent); margin: 0; }
.mf-chip b { font-variant-numeric: tabular-nums; opacity: .7; }

/* ---------------------------------------------------------------------------
 * Konto
 *
 * Ein Knopf in der Kopfzeile mit aufklappbarem Bereich darunter. Bewusst kein
 * eigener Bildschirm und kein Modal: die Anmeldung ist hier ein Zusatz, kein
 * Schritt, den man durchlaufen muss. Wer nur eine Tour prüfen will, soll den
 * Block nie öffnen müssen — und wer ihn öffnet, soll dabei die Seite nicht
 * verlieren.
 *
 * `margin-left: auto` schiebt ihn ans rechte Ende der Kopfzeile. Da die
 * Kopfzeile umbricht (`flex-wrap`), rutscht er auf schmalen Geräten in eine
 * eigene Zeile statt die Überschrift zu quetschen.
 * --------------------------------------------------------------------------- */

.konto {
  position: relative;
  /* Der Knopf ist der einzige Inhalt, der nicht mit der Kopfzeile wachsen
     soll — sonst zieht das aufgeklappte Menü die Zeile auseinander. */
  align-self: flex-start;

  /* Zuerst in der Reihenfolge, nicht zuletzt.
   *
   * Die Kopfzeile bricht um (`flex-wrap`). Ohne diese Zeile landete der
   * Knopf auf einem 360-px-Telefon *unter* der Überschrift und dem
   * Einleitungstext — nachgemessen bei y=180. Von dort aus reichte das
   * aufgeklappte Menü über den unteren Bildschirmrand hinaus, und der
   * Absenden-Knopf war nicht erreichbar.
   *
   * `order` zieht ihn in die erste Zeile, ohne die Reihenfolge im Quelltext
   * zu ändern — dort steht er weiterhin hinten, was für die Tastatur- und
   * Screenreader-Reihenfolge richtig ist: erst der Inhalt, dann das Konto.
   *
   * Gilt nur ohne Seitenleiste: ab 60rem hängt `konto-ui.js` den Block in
   * die Leiste um, und dort ist die Reihenfolge ohnehin die des Quelltexts. */
  order: -1;
}

.konto-knopf { white-space: nowrap; }

/* --- Konto in der Seitenleiste ------------------------------------------
 *
 * Ab hier steht der Block in `#konto-platz-seite` statt in der Kopfzeile.
 * In der Kopfzeile saß er links vor der Überschrift und sah verrutscht aus —
 * ein Konto gehört zur Navigation, nicht neben den Seitentitel.
 *
 * `:has()` statt einer eigenen Klasse am Block: der Stil hängt damit daran,
 * wo das Element tatsächlich steht, und kann nicht mit dem JavaScript
 * auseinanderlaufen, das es dorthin hängt.
 * ----------------------------------------------------------------------- */
#konto-platz-seite:has(.konto) {
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line-soft);
}

#konto-platz-seite .konto {
  margin-left: 0;
  align-self: stretch;
  order: 0;
}

/* Über die volle Breite der Leiste, wie die Navigationsziele darüber —
   ein Knopf, der schmaler ist als alles andere, sieht nach Versehen aus. */
#konto-platz-seite .konto-knopf {
  width: 100%;
  justify-content: flex-start;
}

/* Das Menü klappt hier nach oben auf, nicht nach unten: der Block sitzt am
   unteren Ende der Leiste, nach unten ist kein Platz mehr. Und es beginnt
   am linken Rand, weil der Knopf dort steht. */
#konto-platz-seite .konto-menu {
  top: auto;
  bottom: calc(100% + var(--sp-2));
  right: auto;
  left: 0;
  /* Die Leiste ist schmaler als das Menü — ohne diese Zeile bliebe es auf
     Leistenbreite gestaucht und die E-Mail-Adresse bräche mitten im Wort. */
  width: max(100%, 19rem);
  /* Nach oben aufklappend zählt der Platz *über* dem Menü, nicht unter ihm.
     `--konto-oben` ist hier die Unterkante des Knopfes. */
  max-height: calc(var(--konto-oben, 60dvh) - var(--sp-4));
}

/* Aufklappteil.
 *
 * `position: absolute` und nicht im Fluss: im Fluss würde das Aufklappen den
 * gesamten Bericht nach unten schieben, und man verlöre die Stelle, an der
 * man gerade gelesen hat.
 *
 * Rechtsbündig ausgerichtet, weil der Knopf am rechten Rand sitzt — links
 * ausgerichtet ragte das Menü aus dem Fenster. */
.konto-menu {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 100;

  /* Breit genug für eine E-Mail-Adresse in voller Länge, schmal genug, um auf
     einem 320-px-Telefon nicht anzustoßen. */
  width: min(25rem, calc(100vw - var(--sp-8)));

  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: var(--sp-5);

  /* Auf niedrigen Geräten — kleines Telefon, oder eines mit eingeblendeter
     Tastatur — ragte der Block unten aus dem Fenster und der Absenden-Knopf
     war nicht erreichbar. Nachgemessen bei 360x480: der Block endete bei
     655px, also 175px unterhalb des Bildschirms.

     `dvh` und nicht `vh`: `vh` rechnet auf mobilen Browsern mit dem Fenster
     *ohne* Adressleiste und ist damit größer als der tatsächlich sichtbare
     Bereich — genau der Fehler, den die Regel beheben soll.

     Gerechnet wird ab der Oberkante des Menüs, nicht ab der des Fensters:
     eine feste Obergrenze wie `100dvh - 5rem` half nicht, solange der Knopf
     selbst weit unten stand. Der Abstand vom Fensteranfang steckt in
     `--konto-oben`, das JavaScript beim Öffnen setzt; fehlt der Wert, greift
     ein sicherer Standard. */
  max-height: calc(100dvh - var(--sp-8));
  overflow-y: auto;
  /* Verhindert, dass das Scrollen im Menü am Ende die Seite dahinter
     weiterschiebt. */
  overscroll-behavior: contain;
}

body.konto-modal-offen { overflow: hidden; }
body.konto-modal-offen::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 90;
  background: color-mix(in srgb, var(--bg) 35%, #000);
  backdrop-filter: blur(3px);
}

.konto-titel {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-lg);
  color: var(--ink);
}

.konto-lead {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-soft);
}
.konto-lead strong { color: var(--ink); word-break: break-all; }

.konto-label {
  display: block;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  margin-bottom: var(--sp-2);
}

.konto-feld {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  /* Bewusst nicht `--fs-sm`, obwohl es sonst überall für Nebentext steht:
     Safari auf iOS zoomt beim Antippen eines Feldes automatisch hinein, wenn
     dessen Schrift unter 16px liegt — und zoomt danach nicht zurück. Die
     Seite bleibt verzerrt, bis der Nutzer selbst herauszieht. `--fs-md`
     beginnt bei 15.5px und wäre knapp darunter, deshalb hier die Zahl. */
  font-size: 16px;
  margin-bottom: var(--sp-3);
}
.konto-feld:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Ohne diese Zeile zeichnet der Browser Eingabefelder im Dunkelmodus mit
   hellem Grund und dunkler Schrift — der Platzhalter wird dabei unlesbar. */
.konto-feld { color-scheme: light dark; }

.konto-absenden,
.konto-google {
  width: 100%;
  justify-content: center;
}
.konto-absenden {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.konto-absenden:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
.konto-absenden[disabled] { opacity: .6; cursor: default; }

/* Trennlinie mit „oder" in der Mitte. Die Linien entstehen aus den beiden
   Flex-Kindern rundum, damit kein zusätzliches Markup nötig ist. */
.konto-oder {
  display: flex; align-items: center; gap: var(--sp-3);
  margin: var(--sp-4) 0;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}
.konto-oder::before,
.konto-oder::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line-soft);
}

.konto-hinweis {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--ink-soft);
  border-top: 1px solid var(--line-soft);
  padding-top: var(--sp-3);
}

.konto-meldung {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-sm);
  line-height: 1.45;
  padding: var(--sp-3);
  border-radius: var(--radius-sm);
  background: var(--gut-bg);
  color: var(--accent-strong);
}
.konto-meldung.ist-fehler {
  background: var(--schlecht-bg);
  color: var(--schlecht);
}

/* Tagesvergleich im Wetterfenster: der beste Tag muss auf einen Blick
   herausstechen, ohne dass die anderen wie Fehler aussehen. */
.fenster-tage > div {
  display: flex;
  gap: .4rem;
  align-items: baseline;
  flex-wrap: wrap;
  padding: .15rem 0;
}
.fenster-tage .best {
  font-weight: 600;
}
.fenster-tage .best strong {
  color: var(--ok, #2e7d32);
}
