/* ============================================================
   Trainingsplan

   Zwei Medien, ein Dokument. Was auf dem Bildschirm steht, muss auf Papier
   dasselbe sagen — deshalb steht der Druckteil unten in derselben Datei und
   nicht in einer zweiten, die nach dem dritten Umbau nicht mehr passt.

   Die Fläche ist schmaler als die Werkzeugseiten. Ein Plan wird gelesen,
   nicht bedient, und eine Textspalte über 1500 px ist keine Textspalte mehr.
   ============================================================ */

/* style.css sperrt fuer die Werkzeugseiten `html, body { height: 100%;
   overflow: hidden }` -- eine Ansicht, ein Rollbereich. Das gilt der Galaxie,
   die eine Leinwand ist. Diese Flaeche ist ein Dokument und rollt.

   Ohne diese zwei Zeilen war der Plan gebaut, gerendert, messbar da -- und ab
   der Fensterunterkante nicht mehr erreichbar. Genau dort beginnen die
   Zahlen, aus denen er kommt. Gemeldet am 22. August 2026.

   `visible` und nicht `auto`, aus demselben Grund wie in review.css: `auto`
   macht aus html und body je einen eigenen Rollbereich, und ein Rollbereich,
   der selbst nie rollt, nimmt jedem `position: sticky` darin den Spielraum.
   Gemeint ist ohnehin nur, das `hidden` aus style.css zurueckzunehmen. */
.planPage,
.planPage body { height: auto; overflow: visible; }

.planPage body {
  background: var(--space-deep);
  color: var(--text);
}

#planMain {
  /* 62rem statt der vollen Breite: Bei --fs-base und dieser Spalte stehen
     rund 90 Zeichen in der Zeile — die Obergrenze, ab der das Auge die
     nächste Zeile nicht mehr sicher findet. */
  max-width: 62rem;
  margin: 0 auto;
  padding: var(--sp-9) var(--sp-7) var(--sp-9);
}

.planHead { margin-bottom: var(--sp-8); }
.planHead h1 {
  font-size: var(--fs-hero);
  letter-spacing: -0.01em;
  margin: 0 0 var(--sp-2);
}
.planHead .dim { max-width: 46rem; }

/* ---------- Eingabe ---------- */

.setupPanel { margin-bottom: var(--sp-8); }
.setupPanel .platToggle { margin-bottom: var(--sp-6); }

.fieldLabel {
  display: block;
  font-size: var(--fs-small);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: var(--sp-2);
}

#planUser {
  width: 100%;
  min-height: var(--ctl-h);
  padding: 0 12px;
  margin-bottom: var(--sp-6);
  background: var(--indigo-900);
  border: 1px solid var(--panel-border);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-base);
}
#planUser:focus { border-color: var(--accent); }

/* Jedes Feld trägt seine Beschriftung und seinen Halbsatz. Die Felder sind
   deshalb Blöcke in der Rasterzelle, nicht nackte Auswahlfelder. */
.setupPanel .setupGrid { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.field { display: flex; flex-direction: column; }
.field .setupSel { width: 100%; }
.field .tiny { margin-top: var(--sp-2); }

#planGo { margin-top: var(--sp-7); }
#planErr:empty { display: none; }

/* Nach dem Bau tritt das Formular zurück, ohne zu verschwinden: Wer die
   Stunden ändern will, findet es an derselben Stelle. */
.setupPanel.done { opacity: 0.62; }
.setupPanel.done:hover,
.setupPanel.done:focus-within { opacity: 1; }

/* Sobald der Plan dasteht, stehen zwei gefüllte Knöpfe auf einer Ansicht:
   "Build my plan" im zurückgetretenen Formular und "Save as PDF" über dem
   Dokument. Gemessen am 25. August 2026 bei 375 × 812: y 597–645 und
   875–923 — 326 px auseinander und damit zusammen in einem Bild.

   Die Charta erlaubt einen; es bleibt der, der noch etwas zu tun hat.

   Die Polsterung gibt die zwei Pixel her, die der Rahmen nimmt: `.solidBtn`
   hat keinen, und der Knopf steht mit 48 px genau auf seiner Mindesthöhe —
   ohne den Ausgleich wuchs er beim Umschalten auf 50 und schob die Zeile
   darunter mit. */
.setupPanel.done #planGo {
  background: transparent;
  border: 1px solid var(--panel-border);
  padding: 13px 19px;
  color: var(--text-dim);
  font-weight: 400;
}
.setupPanel.done #planGo:hover {
  background: transparent;
  color: var(--text);
  border-color: var(--accent);
}

/* ---------- Fortschritt ---------- */

/* Der Fortschritt steht über der Fußleiste, statt dahinter.
 *
 * Gemessen am 25. August 2026 bei 375 × 812: Nach dem Absenden bleibt
 * `scrollY` bei 0, und das Formular darüber ist 600 px hoch. `#progressText`
 * lag damit bei y 767–784, die Leiste beginnt bei 754 — **0 von 17 px
 * sichtbar**, der Balken 0 von 4, der Abbruchknopf 0 von 44. Wer abschickte,
 * sah als einzige Änderung einen Knopf, der grau wurde; der Lauf dauert bei
 * "All games" über eine Minute.
 *
 * `sticky` mit `bottom` und nicht die Umsortierung aus review.css: Dort gibt
 * es Spalten, hier nur Fluss, und `#planMain` in ein Flexfeld zu verwandeln
 * hätte die Ränder aller sechs Kinder verändert. Sticky zieht die Karte genau
 * so weit hoch, wie sie sonst unter der Leiste läge, und hört von selbst auf,
 * sobald sie ihre Flussposition erreicht — kein Zustand in JavaScript, nichts,
 * was hängen bleiben kann.
 *
 * Ohne Medienabfrage, weil `--nav-h` am Rechner 0 ist: Dort greift die Regel
 * nur in einem flachen Fenster, und genau dort soll sie greifen. Die Leiste
 * bleibt in jedem Fall oben — --z-sticky ist 10, sie selbst liegt bei 30. */
#progressPanel {
  position: sticky;
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--sp-5));
  z-index: var(--z-sticky);
}

.progTrack {
  height: 4px;
  margin: var(--sp-5) 0;
  background: var(--indigo-900);
  border-radius: var(--r-xs);
  overflow: hidden;
}
.progFill {
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: var(--r-xs);
  transition: width var(--mo-calm) var(--mo-ease);
}

/* ---------- Das Dokument ---------- */

#planOut > section { margin-bottom: var(--sp-9); }

#planOut h3 {
  font-size: var(--fs-small);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  padding-bottom: var(--sp-3);
  margin: 0 0 var(--sp-6);
  border-bottom: 1px solid var(--panel-border);
}

.docHead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-7);
  flex-wrap: wrap;
  padding-bottom: var(--sp-6);
  margin-bottom: var(--sp-8);
  border-bottom: 1px solid var(--panel-border);
}
.docHead h2 { font-size: var(--fs-display); margin: 0 0 var(--sp-2); }
.docFoot { padding-top: var(--sp-6); border-top: 1px solid var(--panel-border); }

.lead { font-size: var(--fs-lead); line-height: 1.6; margin: 0 0 var(--sp-5); }
.lead:last-child { margin-bottom: 0; }
#planOut p.dim { line-height: 1.65; margin: 0 0 var(--sp-4); }

/* Der einzige Ort, an dem der Plan widerspricht. Coral heißt sonst
   "verloren" und heißt auch hier: an dieser Stelle geht etwas nicht auf. */
.warn {
  padding: var(--sp-5) var(--sp-6);
  border-left: 2px solid var(--loss);
  background: rgba(240, 115, 106, 0.07);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  line-height: 1.6;
  margin: 0 0 var(--sp-5);
}

/* ---------- Schwerpunkte ---------- */

.focusItem { margin-bottom: var(--sp-8); }
.focusItem:last-child { margin-bottom: 0; }

.focusHead {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  margin-bottom: var(--sp-4);
}
/* Die Ziffer ist Rangfolge und keine Wertung — deshalb --starlight und keine
   Bedeutungsfarbe. Gold hieße hier "dein Zug" und wäre schlicht gelogen. */
.focusNum {
  flex: none;
  font-size: var(--fs-hero);
  font-weight: 700;
  line-height: 1;
  color: var(--starlight);
  opacity: 0.28;
  font-variant-numeric: tabular-nums;
}
.focusHead h4 { font-size: var(--fs-lead); font-weight: 700; margin: 0; }

/* Der Beleg trägt den Befund. Er steht deshalb nicht klein und grau unter
   dem Rat, sondern in voller Textfarbe direkt unter dem Titel. */
.evidence {
  margin: 0 0 var(--sp-3);
  padding-left: calc(var(--fs-hero) + var(--sp-5));
  line-height: 1.6;
}
.caveat {
  margin: 0 0 var(--sp-4);
  padding-left: calc(var(--fs-hero) + var(--sp-5));
  font-size: var(--fs-small);
  color: var(--text-dim);
  line-height: 1.55;
}
.recipe {
  margin: 0;
  padding-left: calc(var(--fs-hero) + var(--sp-5) + 1.1em);
  list-style: none;
}
.recipe li {
  position: relative;
  margin-bottom: var(--sp-3);
  line-height: 1.6;
}
.recipe li::before {
  content: "";
  position: absolute;
  left: -1.1em;
  top: 0.62em;
  width: 5px;
  height: 1px;
  background: var(--text-dim);
}

/* ---------- Woche ---------- */

.weekTable { display: flex; flex-direction: column; gap: var(--sp-3); }
.weekRow {
  display: grid;
  grid-template-columns: minmax(9rem, 15rem) 1fr auto;
  align-items: center;
  gap: var(--sp-6);
}
.weekName { font-size: var(--fs-base); }
.weekBar {
  height: 6px;
  background: var(--indigo-900);
  border-radius: var(--r-xs);
  overflow: hidden;
}
/* Bedeutungsfrei: der Balken sagt dasselbe wie die Zahl daneben, nur
   schneller. Deshalb --starlight gedämpft und keine Datenfarbe. */
.weekBarFill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  background: var(--starlight);
  opacity: 0.32;
  border-radius: var(--r-xs);
}
.weekTime {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-base);
  color: var(--text-dim);
  white-space: nowrap;
}

/* ---------- Nebenbefunde ---------- */

.alsoList { margin: 0; padding: 0; list-style: none; }
.alsoList li {
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--panel-border);
  line-height: 1.6;
}
.alsoList li:last-child { border-bottom: 0; }

/* ---------- Zahlen ---------- */

#numbersBody {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
  gap: var(--sp-8) var(--sp-9);
}
.numBlockWide { grid-column: 1 / -1; }
.numBlock h4 {
  font-size: var(--fs-small);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin: 0 0 var(--sp-4);
}
.numRow {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: var(--sp-5);
  align-items: baseline;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--hairline, var(--panel-border));
  font-size: var(--fs-base);
}
.numRow:last-child { border-bottom: 0; }
.numRowPair { grid-template-columns: minmax(0, 1fr) auto; }
.numHead {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-dim);
  border-bottom-color: var(--panel-border);
}
.numName { min-width: 0; overflow-wrap: anywhere; }
.numN, .numWdl, .numScore {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
.numN, .numWdl { color: var(--text-dim); }
.numScore { font-weight: 600; }
.numRowPair .numScore { font-weight: 400; color: var(--text-dim); white-space: normal; text-align: right; }

/* ---------- Handy ---------- */

@media (max-width: 700px) {
  #planMain { padding: var(--sp-7) var(--sp-5) var(--sp-9); }
  .planHead h1 { font-size: var(--fs-display); }

  /* Der Balken ist das Erste, was gehen darf: Die Zahl daneben sagt
     dasselbe, und in 320 px ist sie das Wichtigere. */
  .weekRow { grid-template-columns: 1fr auto; gap: var(--sp-4); }
  .weekBar { display: none; }

  /* Die Einrückung unter der Rangziffer kostet auf dem Handy ein Drittel der
     Zeile. Der Text rückt an den Rand, die Ziffer bleibt als Marke oben. */
  .evidence, .caveat { padding-left: 0; }
  .recipe { padding-left: 1.1em; }
  .focusNum { font-size: var(--fs-display); }

  .numRow { gap: var(--sp-4); }
  .docHead { gap: var(--sp-5); }
}

/* ---------- Finger statt Zeiger ---------- */

/* Vier Felder blieben bei --ctl-h, also 40 px; Apples Richtwert ist 44.
   Dieselbe Regel steht für .ghostBtn schon in review.css — die Aufbaufelder
   hat sie nie erfasst. Auf dieser Fläche wiegt das schwerer als anderswo:
   Diese vier Felder sind alles, was ein Besucher hier trifft, bevor er
   irgendetwas zu sehen bekommt. */
@media (pointer: coarse) {
  #planUser,
  .planPage .setupSel { min-height: 44px; }
}

/* ============================================================
   Papier

   Der PDF-Weg dieser Ansicht ist der Druckweg — keine Bibliothek, kein
   zweites Layout, kein CDN, das die CSP ohnehin nicht durchließe. "Als PDF
   sichern" steht in jedem Druckdialog, der Text bleibt auswählbar, und das
   Dokument sieht aus wie das auf dem Bildschirm.

   Umgekehrte Farben: Ein Plan, den man ausdruckt, um ihn an die Wand zu
   hängen, darf keine Tintenpatrone kosten. Die Bedeutungsfarben bleiben, wo
   sie etwas heißen; alles andere wird Schwarz auf Weiß.
   ============================================================ */

@media print {
  @page { margin: 16mm 14mm; }

  html, body {
    background: var(--paper) !important;
    color: var(--ink) !important;
    font-size: 10.5pt;
  }
  /* Der Innenabstand für die Leiste muss weg — auf Papier gibt es sie nicht. */
  .planPage body { padding: 0 !important; }

  #sideNav,
  #setupPanel,
  #progressPanel,
  .planHead,
  .howCard,
  .noPrint,
  .weekBar { display: none !important; }

  /* Auf Papier gibt es kein Warten. Steht die Stichprobe noch aus, wird der
     ganze Abschnitt weggelassen statt als leerer Kasten gedruckt.

     "offer" gehört genauso dazu, und auf dem Telefon ist es sogar der
     Regelfall: Dort trägt das Gerät nur eine Engine, also läuft die
     Stichprobe nur auf Nachfrage (siehe engineAngebot in page.js). Gemessen
     am 25. August 2026: 220 Zeichen auf dem Papier, Überschrift und Angebot
     — "Only one engine fits on this device, so it takes several minutes and
     will warm the phone up" —, und darunter nichts. Ein Satz über dieses
     Gerät hat auf einem Blatt Papier ohnehin nichts verloren. */
  #engineSec[data-state="wait"],
  #engineSec[data-state="offer"] { display: none !important; }
  #engineBody a { color: var(--ink) !important; }

  #planMain { max-width: none; margin: 0; padding: 0; }

  /* Überschriften und Trennlinien in Druckfarben. */
  #planOut h3 {
    color: var(--ink-dim) !important;
    border-bottom: 0.6pt solid var(--ink-rule) !important;
    font-size: 8pt;
  }
  .docHead, .docFoot { border-color: var(--ink-rule) !important; }
  .docHead h2 { font-size: 16pt; }
  .alsoList li, .numRow { border-bottom-color: var(--ink-rule-soft) !important; }
  .numHead { border-bottom-color: var(--ink-rule) !important; }
  .dim, .caveat, .numN, .numWdl, .tiny,
  #planOut p.dim, .numRowPair .numScore { color: var(--ink-dim) !important; }
  .focusNum { color: var(--ink) !important; opacity: 0.3; }
  .recipe li::before { background: var(--ink-mark) !important; }

  /* Der Warnkasten behält seine Bedeutung, verliert aber die Fläche: Ein
     vollflächiger Farbblock auf Papier ist ein Fleck. Coral bleibt, weil es
     hier etwas heißt — es ist dieselbe Farbe wie eine verlorene Partie. */
  .warn {
    background: none !important;
    border-left: 2pt solid var(--coral-600) !important;
    color: var(--ink) !important;
  }

  /* Kein Befund darf über den Seitenrand zerrissen werden — der Beleg vom
     Rat getrennt ist genau das, was diese Ansicht vermeiden soll. */
  .focusItem, .numBlock, .weekRow, .alsoList li {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  #planOut > section { break-inside: auto; margin-bottom: 10mm; }
  #planOut h3 { break-after: avoid; page-break-after: avoid; }

  /* Zwei Spalten auf Papier sind bei dieser Schriftgröße eine zu viel. */
  #numbersBody { grid-template-columns: 1fr 1fr; gap: 8mm 12mm; }
}

/* ---------- Stufe B: was die Engine sieht ---------- */

/* Der Balken gehört zum Warten und verschwindet mit ihm — auch dann, wenn
   die Stichprobe scheitert: Ein Fortschrittsbalken, der auf 40 % stehen
   bleibt, sieht aus wie eine Seite, die hängt. */
#engineSec[data-state="done"] #engineTrack,
#engineSec[data-state="fail"] #engineTrack { display: none; }
#engineNote:empty { display: none; }

/* Eine Lücke ist eine Auskunft und wird auch so gesetzt: nicht rot, nicht
   als Fehler, sondern gedämpft wie jeder andere Vorbehalt auf dieser Seite. */
#engineSec[data-state="fail"] #engineLead { color: var(--text-dim); }

#engineBody > * + * { margin-top: var(--sp-6); }
#engineBody .numBlock h4 { margin-bottom: var(--sp-3); }
#engineBody .recipe { padding-left: 1.1em; }
/* Der Link bleibt in Textfarbe; der Hover faerbt die Unterstreichung.
   --accent als Textfarbe kaeme auf 3,33:1 und damit unter die Grenze — als
   Strich unter dem Text ist derselbe Ton in Ordnung, weil dort nichts
   gelesen wird. */
#engineBody a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--panel-border);
  text-underline-offset: 3px;
}
#engineBody a:hover { text-decoration-color: var(--text); }

/* Im Angebotszustand gibt es nichts zu zeigen als die Frage. */
#engineSec[data-state="offer"] #engineTrack { display: none; }
#engineSec[data-state="offer"] #engineGo { margin-top: var(--sp-5); }

.docActions { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; margin-bottom: var(--sp-5); }
#planClearNote:empty { display: none; }
#planClearNote { margin-top: 0; }

/* ---------- Der statische Text unter dem Werkzeug ---------- */

/* Eine Schrittfolge ist eine Reihenfolge, keine Aufzählung: Wer bei Schritt
   vier einsteigt, hat drei übersprungen. `.facts` blendet den Listenmarker aus
   und setzt einen Punkt davor — richtig für die Merkmalslisten der Galaxie,
   falsch hier. Ein <ul> mit derselben Optik zu nehmen wäre die bequeme
   Lösung und die unehrliche: Die Reihenfolge stünde dann nur im Text. */
.planPage ol.facts { counter-reset: schritt; }
.planPage ol.facts li { padding-left: var(--sp-8); }
.planPage ol.facts li::before {
  counter-increment: schritt;
  content: counter(schritt);
  top: 0;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

/* Die beiden Textblöcke gehören zur Seite, nicht zum Plan: Sie stehen unter
   dem Werkzeug und wandern nicht ins gedruckte Dokument. */
.planPage .howCard { margin-top: var(--sp-9); }
