/* Analysebrett – vierte Ansicht.
 *
 * Diese Datei ist mit Absicht kurz. Panel, Ghost- und Solid-Knopf, Brettrahmen,
 * Bewertungsbalken, Brettleiste und die drei Engine-Zeilen stehen bereits in
 * review.css, und die Seite lädt sie mit. Zwei Quellen für denselben Knopf
 * laufen auseinander – das steht im Kopf von review.css und gilt hier weiter.
 * Was hier steht, gibt es auf keiner anderen Fläche.
 *
 * Die Bedeutungsfarben sind die der Charta, nicht die der Review: Gold heißt
 * hier wieder „dein Zug", Violett „Zug des Gegners". Die Review kennt keine
 * Besitzfarbe und benutzt Gold für „Ungenauigkeit"; auf diesem Brett stehen
 * die eigenen Partien daneben, also gilt wieder der Besitz.
 */

/* ---------- Rahmen ---------- */

#boardMain {
  max-width: 1560px;
  margin: 0 auto;
  padding: 26px 24px 60px;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.boardHead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
  margin-bottom: var(--sp-6);
}
/* Die rechte Spalte ist ein Flexcontainer, und Flexkinder schrumpfen von
   selbst. Gemessen: Bei drei Fächern von zusammen 852 px in einer 717 px
   hohen Spalte wurde das Engine-Fach auf 42 px gequetscht – Kopfzeile
   sichtbar, drei Zeilen weggeschnitten, kein Rollbalken, weil nichts
   überstand. Die Fächer behalten ihre Höhe; gerollt wird die Spalte. */
.boardPage .sideCol > .panel { flex: none; }

.boardHeadText h1 { font-size: var(--fs-title); margin-bottom: 2px; }
.boardHeadText p { margin: 0; }
.boardHeadActions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
/* Der Browser blendet [hidden] nur aus, solange nichts anderes ein display
   setzt. Auf dieser Seite tragen fast alle schaltbaren Teile eine Flex-Regel,
   und dreimal hintereinander blieb deshalb etwas stehen, das weg sein sollte:
   das Namensfeld ueber der Statistik, die es erzeugt hatte, und der
   Farbschalter ueber einer Karte, die noch gar keine Farben kannte. Eine
   Regel fuer alle statt drei einzelne, mit demselben !important wie die
   Klasse .hidden in style.css - [hidden] heisst versteckt, ohne Ausnahme. */
.boardPage [hidden] { display: none !important; }

/* Das Brett misst sich an dem, was Kopfzeile, Leiste und Zeile darunter
   übrig lassen – dieselbe Rechnung wie in review.css, nur mit der kürzeren
   Kopfzeile dieser Seite: Kopf (58) + Abstand (16) + Brettleiste (48) +
   Zeile (20) + zwei Abstände (20) + Innenabstand (86) = 248, aufgerundet.

   Die Gasse links vom Brett trägt jetzt zweierlei: den Bewertungsbalken
   (immer) und das Praxisfach (nur wenn Partien geladen sind). Ohne Partien
   darf es keinen Platz kosten – deshalb hängt seine Breite am :has() und
   nicht an einer festen Zahl. Alles, was sich in dieser Spalte am Brett
   ausrichtet (Brettleiste, Zeile darunter), rechnet über --lane mit. */
.boardPage .boardCol {
  --dash-w: 116px;
  --dash-lane: 0px;
  --lane: calc(var(--dash-lane) + var(--bar-w) + var(--bar-gap));
  --board: min(100% - var(--lane), max(240px, calc(100vh - 268px)));
}
.boardPage .boardCol:has(.practiceDash:not([hidden])) {
  --dash-lane: calc(var(--dash-w) + var(--bar-gap));
}

/* ---------- Das Praxisfach links am Brett ---------- */

.practiceDash {
  width: var(--dash-w);
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

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

/* Zwei Spalten, drei Zeilen: Zug und Anteil oben, der Balken quer darunter,
   die Siegquote rechts. In 116 px ist das die einzige Anordnung, in der beide
   Zahlen ohne Abkürzung stehen.
   Die Siegquote schreibt ihr Wort mit ("scored 47 %"), der Anteil nicht: Der
   Anteil steht neben dem Zug und wird von der Kopfzeile ("You play") getragen,
   die Quote steht allein und wäre ohne Wort nur eine zweite Prozentzahl. */
.dashRow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1px var(--sp-2);
  align-items: baseline;
  padding: var(--sp-2) var(--sp-2) 5px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.dashRow:hover { border-color: var(--accent); background: rgba(140, 130, 205, 0.12); }
/* Die Zeilen ohne Pfeil treten ganz zurueck, nicht nur mit dem Zugnamen: Ein
   einzelner Farbunterschied bei 13 px ist bei zwei nebeneinander liegenden
   Violettoenen kaum zu sehen, zwei sind es. */
.dashRow--off .dashPct { color: var(--text-dim); }
.dashMove { font-size: var(--fs-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.dashPct { font-size: var(--fs-base); color: var(--text); font-variant-numeric: tabular-nums; }
.dashBar {
  grid-column: 1 / -1;
  height: 4px;
  background: var(--indigo-800);
  border-radius: var(--r-xs);
  overflow: hidden;
  margin-top: 3px;
}
.dashBar i { display: block; height: 100%; border-radius: var(--r-xs); }
.dashScore {
  grid-column: 1 / -1;
  font-size: var(--fs-small);
  font-weight: 600;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#anBoard {
  width: var(--board);
  aspect-ratio: 1;
  height: auto;
  border-radius: 10px;
  display: block;
  cursor: grab;
  touch-action: none; /* Figuren ziehen statt die Seite zu scrollen */
  /* Die Leinwand ist ein einziges Element, also färbt die eingebaute
     Tipp-Markierung von Android und iOS bei jeder Berührung das **ganze**
     Brett — gemessen rgba(51, 181, 229, 0.4) über 315 x 315 px, ein Blau, das
     in keiner Leiter dieses Projekts vorkommt. Die Startseite schaltet sie
     für ihre 64 Feldknöpfe längst ab (hub.css). Was ein Tipp bewirkt, sagt
     das Brett selbst: Das gewählte Feld und seine Ziele werden gezeichnet. */
  -webkit-tap-highlight-color: transparent;
}
#anBoard:active { cursor: grabbing; }

/* Das Brett wird nie gestreckt, an keiner Fensterbreite.
 *
 * review.css stellt die Brettzeile auf `align-items: stretch` — richtig für
 * den Bewertungsbalken, der auf Bretthöhe wachsen soll. Auf dieser Fläche
 * steht in derselben Zeile aber noch das Praxisfach, und dessen Höhe kommt
 * aus seinen Zeilen: gemessen am 25. August 2026 mit fünf Fortsetzungen
 * 307 px. Sobald die Kantenlänge darunter fiel, streckte die Zeile das Brett
 * auf die Höhe des Fachs — bei 901 x 900 auf 229 x 307, bei 960 x 900 auf
 * 288 x 307, bei 1200 x 500 auf 240 x 307. Die Felder waren dabei sichtbar
 * rechteckig.
 *
 * `aspect-ratio: 1` hilft dagegen nicht: Ein gestrecktes Flexkind bekommt
 * seine Höhe zugewiesen, und eine zugewiesene Höhe schlägt jedes
 * Seitenverhältnis. Ein verzerrtes Brett ist keine Unschönheit, sondern eine
 * falsche Auskunft über die Stellung — 64 Felder, die nicht quadratisch sind,
 * lassen eine Diagonale wie eine Reihe aussehen.
 *
 * Der Balken behält seine Streckung: Er ist der einzige Teil der Zeile, der
 * seine Höhe von außen bekommen soll. Wo das Fach höher ist als das Brett,
 * steht er ein Stück tiefer als dessen Unterkante — die zwei Anordnungen
 * weiter unten sorgen dafür, dass dieser Fall nur noch in einem 14 px breiten
 * Fensterhöhenbereich überhaupt eintritt. */
.boardPage #anBoard { align-self: flex-start; }

.navBtn--wide {
  width: auto;
  padding: 0 var(--sp-5);
  font-family: inherit;
  font-size: var(--fs-small);
}

/* ---------- Das aufklappbare Fach ---------- */

/* Zugeklappt ist es eine Zeile: Name der Sache, Zustand, Winkel. Der
   eingebaute Dreiecksmarker fällt weg – er sitzt links, und links steht hier
   der Text, der die Zeile trägt. */
#practiceCard > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
#practiceCard > summary::-webkit-details-marker { display: none; }
#practiceCard[open] > summary { margin-bottom: var(--sp-5); }

/* Name über Zustand, nicht daneben. Nebeneinander brauchten „Analyse from
   your games" und „darkhorse210291 · 248 games" zusammen 353 px in einer
   340 px breiten Karte – beide brachen um, und aus einer Zeile wurden vier.
   Untereinander ist die Höhe dagegen immer dieselbe. */
.practiceSummaryText {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}
.practiceSummaryTitle { font-size: var(--fs-title); font-weight: 600; color: var(--text); }
#practiceMeta {
  margin: 0;
  font-size: var(--fs-small);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.practiceChevron {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--text-dim);
  transition: transform .15s ease;
}
#practiceCard[open] .practiceChevron { transform: rotate(180deg); }
#practiceCard > summary:hover .practiceChevron,
#practiceCard > summary:hover .practiceSummaryTitle { color: var(--text); }
@media (prefers-reduced-motion: reduce) {
  .practiceChevron { transition: none; }
}

/* ---------- Wer hier ist ---------- */

.whoForm { display: flex; flex-direction: column; gap: var(--sp-4); }
.whoForm .platToggle { margin: 0; }
.whoForm .solidBtn { min-height: var(--ctl-h); padding: 0 18px; font-size: var(--fs-base); }
#whoUser {
  min-height: var(--ctl-h);
  padding: 0 12px;
  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);
}
/* Kein `outline: none` mehr. Der Rahmenwechsel allein trägt den Fokus nicht:
   gemessen 2,61:1 gegen den unfokussierten Rahmen und 3,56:1 gegen die
   Feldfläche — beides unter der Lesbarkeitsschwelle, und die Charta führt
   sichtbaren Tastaturfokus unter Qualitätsuntergrenze, ohne Ausnahme. Der
   Rahmen darf bleiben, er ist ein zweites Signal; der Ring aus style.css:48
   ist das erste. */
#whoUser:focus { border-color: var(--accent); }
#whoUser.err { border-color: var(--loss); }
#whoErr:empty { display: none; }
#whoErr { margin-top: 0; }

/* .setupGrid und .setupSel standen bis zum 22. August 2026 hier. Sie sind ins
   review.css gewandert, als der Trainingsplan dieselben Felder brauchte —
   zwei Kopien derselben Auswahlfeld-Gestalt wären zwei Kopien geblieben. */

/* ---------- Die eigene Praxis ---------- */

/* Zwei Zahlen, die zusammen gelesen werden: wie oft, und wie es ausging. */
.practiceHead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.practiceCount { font-size: 22px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.practiceCount small { font-size: var(--fs-base); font-weight: 400; color: var(--text-dim); margin-left: 4px; }
.practiceScore { font-size: var(--fs-lead); font-weight: 700; font-variant-numeric: tabular-nums; }
.practiceLine { font-size: var(--fs-base); color: var(--text-dim); margin-bottom: var(--sp-3); word-break: break-word; }
.practiceName { font-size: var(--fs-base); color: var(--text); margin-bottom: 2px; }
/* Keine Fläche für eine Auskunft, die es nicht gibt. */
.practiceName:empty, .practiceLine:empty { display: none; }
.practiceEmpty { font-size: var(--fs-base); color: var(--text-dim); }
.practiceEmpty b { color: var(--text); font-weight: 600; }

/* Der Weg zu einem anderen Konto steht unten in der Karte, nicht oben:
   Er wird einmal im Leben gebraucht und darf die Zahlen nicht anführen. */
.practiceFoot { margin-top: var(--sp-5); }

/* ---------- Zugstreifen ---------- */

/* Eine Zeile, die umbricht, statt einer Tabelle: Die Zugliste eines
   Analysebretts ist selten lang, und wo sie lang wird, liest man sie wie
   Notation und nicht wie eine Aufstellung. */
.moveStrip {
  display: flex;
  flex-wrap: wrap;
  gap: 2px var(--sp-2);
  align-items: baseline;
  font-size: var(--fs-base);
  max-height: 168px;
  overflow-y: auto;
  margin-bottom: var(--sp-3);
}
/* Nur die Auskunft, nicht die Anweisung. „drag a piece" stand hier und war
   damit 271 px vom Brett entfernt, das gemeint war; die Anweisung steht jetzt
   in der Zeile unter dem Brett (renderNote in js/analysis/page.js). Zweimal
   dasselbe an zwei Stellen ist die Redundanz, die eine Fläche billig
   aussehen lässt. */
.moveStrip:empty::before {
  content: "No moves yet.";
  color: var(--text-dim);
}
.moveNo { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.moveBtn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-base);
  padding: 1px 5px;
  cursor: pointer;
}
.moveBtn:hover { border-color: var(--accent); }
.moveBtn[aria-current="true"] { background: var(--indigo-800); color: var(--text); font-weight: 600; }

/* ---------- Stellung laden ---------- */

#posInput {
  width: 100%;
  background: var(--indigo-900);
  border: 1px solid var(--panel-border);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: var(--fs-small);
  padding: 8px 10px;
  resize: vertical;
}
#posInput:focus { border-color: var(--accent); }
.posRow { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; margin-top: var(--sp-3); }
.posRow .status { margin-top: 0; }
#posErr:empty { display: none; }

/* ---------- Umwandlung ---------- */

/* Der einzige Ort dieser Fläche, der über der Fußleiste liegen darf: Ein
   Dialog, der die Wahl der Figur abwartet, und der seinen eigenen Ausweg
   mitbringt („Cancel" und Escape). Die Zahl steht als Sprosse der Leiter aus
   tokens.css da und nicht als 40 — wer die Leiter verschiebt, verschiebt
   diesen Dialog mit. */
.promoOverlay {
  position: fixed;
  inset: 0;
  background: rgba(3, 4, 10, 0.72);
  display: grid;
  place-items: center;
  z-index: var(--z-escape);
}
.promoBox {
  background: var(--indigo-950);
  border: 1px solid var(--panel-border);
  border-radius: var(--r-sm);
  padding: var(--sp-7);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  align-items: center;
  text-align: center;
}
.promoRow { display: flex; gap: var(--sp-3); flex-wrap: wrap; justify-content: center; }
.promoBtn {
  min-height: var(--ctl-h);
  padding: 0 14px;
  background: transparent;
  border: 1px solid var(--panel-border);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-base);
  cursor: pointer;
}
.promoBtn:hover { border-color: var(--accent); }

/* ---------- Kein Platz für die dritte Spalte ----------
 *
 * Die Brettzeile hat drei Spalten: Praxisfach, Bewertungsbalken, Brett. Die
 * erste kostet 124 px und ist erst dann eine gute Idee, wenn daneben noch ein
 * Brett steht. Gemessen am 25. August 2026 mit fünf Fortsetzungen und
 * geladenen Partien:
 *
 *     901 x 900   Brett 229 breit  — Fach halb so breit wie das Brett
 *     960 x 900   Brett 288 breit
 *    1000 x 900   Brett 326 breit  — ab hier trägt die Anordnung
 *    1200 x 500   Brett 240 breit  — flaches Fenster, dieselbe Enge
 *
 * Dazu lief die Brettleiste über: Ihr Einzug ist die ganze Gasse (156 px), und
 * was übrig blieb, war schmaler als ihre sechs Symbolknöpfe — gemessen 45 px
 * Innenüberlauf bei 901 px, 39 px bei 1200 x 500. Ein Deck, das sich seitlich
 * verschieben lässt, steht auf jeder Fläche dieses Projekts als Mangel im
 * Selbsttest.
 *
 * Das Telefon löst dasselbe Problem seit Langem, indem das Fach unter das
 * Brett rückt; hier gilt derselbe Satz einfach eine Stufe früher. Die
 * Bruchstelle ist die 1080er der Leiter aus tokens.css, und ihre Frage ist
 * wörtlich diese: „Ist Platz für die dritte Spalte?" Die zweite Abfrage nimmt
 * das flache Fenster dazu — dort ist nicht die Breite knapp, sondern die
 * Höhe, aus der die Kantenlänge kommt.
 *
 * Nach der Änderung, dieselben Fenster: 901 → Brett 351 x 351 statt 229 x 307
 * und 0 statt 45 px Überlauf; 960 → 410 x 410; 1080 → 530 x 530;
 * 1200 x 500 → 240 x 240 statt 240 x 307. */
@media (max-width: 1080px), (max-height: 560px) {
  /* Über die Kennung und nicht über .boardPage: Die Gasse wird oben in
     `:has(.practiceDash:not([hidden]))` gesetzt, und dagegen kommt nur ein
     Selektor mit einer Kennung an. review.css setzt dieselbe Null unter
     900 px noch einmal — dieselbe Zahl, nicht eine zweite Quelle: Dort hängt
     sie an der Rechnung fürs Deck, hier an der Anordnung der Zeile. */
  #boardMain .boardCol { --dash-lane: 0px; }

  .boardWrap { flex-wrap: wrap; }
  /* Raster statt Flexzeile: Mit `flex: 1 1 84px` passten vier Felder in die
     erste Zeile und das fünfte zog sich als einziges seiner Zeile auf die
     vollen 355 px auseinander – eine Zahl, die viermal so breit war wie ihre
     Nachbarn und dadurch wichtiger aussah. Das Raster lässt die übrigen
     Zellen einfach leer. */
  .practiceDash {
    order: 3;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: var(--sp-2);
    margin-top: var(--sp-2);
  }
  .dashHead { grid-column: 1 / -1; margin: 0; }
}

/* ---------- Schmal ---------- */

@media (max-width: 900px) {
  /* Wie in der Review: Die Spalten stehen untereinander und die Seite
     scrollt als Ganzes. Ohne das rechnet --board weiter gegen die
     Fensterhöhe und das Brett wird auf einem hohen Telefon winzig. */
  /* `var(--main-pad-x)` und nicht 10px: review.css rechnet mit einem
     negativen Außenabstand derselben Größe dagegen an, damit das Deck bis an
     den Bildschirmrand reicht. Zwei Zahlen, die dasselbe meinen und einzeln
     geändert werden können, sind die zwei Ritzen, durch die der Text vorher
     am Deck vorbeilief. */
  #boardMain { height: auto; display: block; padding: 14px var(--main-pad-x) 40px; }

  /* Das Praxisfach steht hier unter dem Brett und nicht daneben — die Regeln
     dafür stehen seit dem 25. August 2026 im Abschnitt darüber. Sie gelten
     jetzt schon ab 1080 px und nicht erst ab 900, weil es dieselbe Enge ist:
     116 px seitlich sind auf dem Telefon ein Drittel der Breite und bei
     901 px die Hälfte des Bretts. Zwei Blöcke mit derselben Anordnung wären
     zwei Quellen für eine Sache.
     `--dash-lane: 0px` stand ebenfalls hier. Die Zeile steht jetzt zweimal:
     in review.css an `#boardMain .boardCol` unter 900 px, wo sie an der
     Rechnung fürs Deck hängt, und oben für den Bereich bis 1080. */

  .boardCol { justify-content: flex-start; }
  .boardHead { margin-bottom: var(--sp-5); }
  /* `#colourToggle` stand hier bis zum 25. August 2026 mit einer Begründung
     und einer Rechnung. Den Schalter gibt es auf dieser Seite nicht und in
     keiner anderen Datei des Projekts — die Farbe wird seit dem Umbau im
     Fach über `#whoColor` gewählt. Eine Regel ohne Ziel ist eine Falle für
     den, der die Datei liest. */
  .boardHeadActions { width: 100%; }

  /* Die rechte Spalte behält die Reihenfolge des großen Fensters: erst die
     eigene Praxis, dann die Engine, zuletzt die Züge. Das stand hier schon
     als Absicht, und es stimmte nicht.
     review.css setzt im selben Bereich eine Ordnungszahl auf `#linesCard`
     (erst 2, seit dem 25. August 4). Dort meint sie die Stellung **im
     Raster**, denn in review.html hängt die Enginekarte direkt am Raster und
     soll sich unter ihren eigenen Schalter einfügen; hier hängt sie in der
     Spalte, und dieselbe Regel schob sie damit ans Ende der Spalte. Gemessen
     am 25. August 2026 bei 375 x 812 mit 49 geladenen Partien: Die
     Enginekarte begann bei Dokument-y 1188 von 1512 — als Letztes, 434 px
     unter der Falz, hinter „Load a position". Damit lag die eine Hälfte der
     Frage, für die es diese Ansicht gibt („was soll ich hier spielen"), zwei
     Karten tief. Danach 891 von 1521, also zweite Karte, 254 px vor der
     Zugkarte.
     Auf diesem Brett gibt es den Schalter nicht, für den die Zahl in
     review.css gedacht ist — die Engine ist hier der Grundzustand. Alle drei
     Zahlen stehen deshalb ausgeschrieben da: Die Spalte trägt ihre eigene
     Reihenfolge und nicht die einer fremden Datei, und sie ändert sich nicht
     mehr mit, wenn die Review ihre umstellt. */
  .boardPage .sideCol > #practiceCard { order: 0; }
  .boardPage .sideCol > #linesCard    { order: 1; }
  .boardPage .sideCol > #movesCard    { order: 2; }

  /* Solange das Formular offen steht, klebt das Brett nicht.
   *
   * Das Deck lässt einen Lesestreifen von 340 px übrig — gemessen am
   * 25. August 2026 bei 375 x 812. Die Praxiskarte ist aufgeklappt 489 px
   * hoch und stand damit an 0 von 46 Rollpositionen ganz im Bild; höchstens
   * 70 % von ihr waren je zugleich zu sehen. Sie ist die zweite Hälfte der
   * Frage, für die es diese Ansicht gibt („und was spiele ich tatsächlich?"),
   * und eine Antwort, die man nie ganz sieht, ist keine.
   *
   * Kürzen ist hier die falsche Antwort, weil die Karte zwei verschiedene
   * Dinge trägt und nur eines davon zum Brett gehört:
   *
   *   Die Zahlen (#practiceBody) ändern sich mit jedem Halbzug. Sie müssen
   *   neben dem Brett stehen — und sie passen dorthin: gemessen 251 px in
   *   einem 284 px hohen Streifen, ganz lesbar.
   *
   *   Das Formular (#whoForm) ist einmal im Leben auszufüllen. Wer seinen
   *   Namen eintippt und vier Filter setzt, sieht nicht auf das Brett; es
   *   liegen in diesem Augenblick nicht einmal Pfeile darauf, denn die
   *   Partien sind ja noch nicht da. Ein Brett, das dafür 414 von 754 px
   *   festhält, hält nichts fest, was gebraucht wird.
   *
   * Also gibt es das Deck für die Dauer des Formulars ab. Der Lesestreifen ist
   * dann das ganze Fenster über der Fußleiste, 754 statt 340 px; gemessen
   * danach steht die Karte an 13 von 46 Rollpositionen ganz im Bild und ist an
   * jeder davon zu 100 % zu sehen. Danach kommt das Deck von selbst zurück:
   * `#whoForm` bekommt beim Laden sein `hidden`, und damit greift diese Regel
   * nicht mehr — gemessen `position: sticky` und ein Brett von 280 px, wie
   * zuvor.
   *
   * Aussehen und Ränder bleiben, wie sie sind. Ein dunkles Band mit Kante ist
   * auch im mitrollenden Zustand die Rückseite des Bretts und die Grenze zu
   * den Karten; nähme man sie weg, rückte das Brett beim Aufklappen um 10 px
   * zur Seite — eine Bewegung im Chrome, für die es keinen Grund gibt.
   *
   * Die Wache in js/analysis/page.js liest `position` und rechnet dann mit
   * einer Deckhöhe von 0. Sie muss dafür nicht angefasst werden — sie fragt
   * seit Runde 1 den berechneten Stil und nicht die Fensterbreite. */
  .boardPage:has(#practiceCard[open] #whoForm:not([hidden])) .boardCol {
    position: static;
    z-index: auto;
  }
  /* Der Rollrand aus review.css hält Ziele unter der Deckkante frei. Ohne
     Deck ist er nur noch ein Loch: Gemessen am 25. August 2026 bei 375 x 812
     landete das Namensfeld, von unten angerollt, bei y 423 in einem Fenster,
     das bis 754 reicht — mehr als die halbe freie Höhe stand leer über einem
     Formular, das ganz hineingepasst hätte. Mit dieser Zeile bei y 8. */
  .boardPage:has(#practiceCard[open] #whoForm:not([hidden]))
    .sideCol :is(a[href], button, input, select, textarea, summary) {
    scroll-margin-top: 8px;
  }
}


/* ---------- Was ein Finger treffen muss ----------
 *
 * `pointer: coarse` und nicht eine Breite: Es geht um den Finger, nicht um
 * den Bildschirm — dieselbe Begründung wie beim 16-px-Netz in shell.css.
 *
 * Gemessen am 25. August 2026 bei 375 x 812: „Copy FEN" war 60 x 15 px, das
 * einzige Ziel der Fläche unter dem WCAG-Mindestmaß von 24 px, und die Zeile
 * zum Aufklappen des Praxisfachs 313 x 39. Beide sind Text ohne Rahmen, also
 * sieht man ihnen ihre Höhe nicht an; man tippt daneben und nichts passiert.
 *
 * Nur die Trefferfläche wächst, nicht die Schrift: Der Text bleibt, wo er
 * war, und die Zeile darüber rückt nicht. */
@media (pointer: coarse) {
  /* „Copy FEN" stand hier eine Fassung lang auf 24 px — dem Mindestmaß von
     WCAG 2.2 AA (2.5.8). Das Projekt hat aber ein eigenes, strengeres Maß,
     und es steht seit Monaten im Kopf von css/shell.css: 44 x 44, die Stufe
     AAA. Zwei Zahlen für dieselbe Frage sind schlechter als jede von beiden,
     also gilt hier die des Projekts. `.linkBtn` bekommt sie dort zentral;
     diese Regel ist deshalb ersatzlos weggefallen und nicht etwa vergessen
     worden. Der Knopf steht in einer Zeile mit Feldern, die über --ctl-h
     ohnehin 44 hoch sind — er richtet sich damit an ihnen aus, statt als
     einziges Element aus der Reihe zu fallen. */

  /* Die volle Zeilenhöhe, weil sie über die ganze Kartenbreite geht und der
     häufigste Griff dieser Karte ist. */
  .boardPage #practiceCard > summary { min-height: 44px; }

  /* Die 16-px-Regel aus shell.css nennt `input, select, textarea` — ein
     <button> ist keines von dreien. Gemessen am 25. August 2026 bei 375 x 812:
     Namensfeld und die vier Auswahlfelder auf 16 px, der Knopf darunter als
     einziges Element dieses Formulars auf 13. Er ist sein Abschluss und die
     Handlung, für die man das Fach überhaupt aufklappt; kleiner gesetzt als
     die Felder darüber liest er sich wie deren Fußnote.
     Nur hier und nicht in der Grundgestalt: Am Rechner stehen Feld und Knopf
     beide auf --fs-base, und dort stimmt das Bild. */
  .boardPage #whoGo { font-size: 16px; }

  /* Nachwirkung der 16-px-Regel aus shell.css, und zwar eine gewollte, die
     nur noch ein Feld nachziehen muss: Ein FEN ist 56 Zeichen. Bei den 12 px,
     für die dieses Feld entworfen wurde, passte er in die zwei Zeilen von
     `rows="2"`. Mit 16 px braucht er bei 320 px Bildschirmbreite drei —
     gemessen am 25. August 2026 73 px Inhalt in einem 54 px hohen Feld, die
     letzte Zeile also nicht zu sehen. Wer eine Stellung einfügt, muss lesen
     können, was er eingefügt hat.
     73 px Inhalt plus die zwei Pixel der Kante, weil die Höhe hier den
     Rahmen mitmisst. Drei Zeilen und nicht mehr: Ein PGN läuft ohnehin über
     jede Höhe hinaus, dafür ist das Feld `resize: vertical`. */
  .boardPage #posInput { min-height: 75px; }

  /* Der senkrechte Wisch gehört der Seite, das Ziehen gehört der Figur.
   *
   * Zeile 142 bleibt, wie sie ist: Mit der Maus gibt es keinen Wisch, dort
   * ist `none` richtig. Diese Regel gilt dem Finger. Gemessen am 25. August
   * 2026 bei 375 x 812 mit einer echten Geste über 200 px mitten auf dem
   * Brett: `scrollY` blieb 0. Das Brett belegt hier 315 von 375 px Breite —
   * es blieb eine Gasse von 46 px links und 14 px rechts, in der die Seite
   * überhaupt noch rollte.
   *
   * `pan-y` allein wäre ein Tausch und keine Lösung: Dann fängt der Browser
   * jede Bewegung mit senkrechtem Übergewicht ab, und das sind die meisten
   * Schachzüge — ein Bauernzug nach vorn käme nicht mehr an. Die Wache in
   * js/review/touch-scroll.js gehört zu dieser Regel und ist nicht optional;
   * sie bestellt das Rollen ab, sobald der Finger auf einer eigenen Figur
   * aufsetzt. js/analysis/page.js hängt sie an.
   *
   * `pinch-zoom` kommt dazu, weil das Brett bisher auch das Aufziehen
   * verschluckt hat — auf einem Brett mit 39 px je Feld ist das der einzige
   * Weg, eine Stellung genauer anzusehen.
   *
   * review.css setzt dieselbe Regel für `#revBoard` und lässt `#anBoard`
   * ausdrücklich aus: board.css wird nach review.css geladen, eine gleich
   * spezifische Zeile dort verlöre gegen die hier. */
  .boardPage #anBoard { touch-action: pan-y pinch-zoom; }

  /* Die Züge im Streifen sind 26 bis 33 px breit und 21 px hoch gemessen —
     zu flach für einen Daumen, und sie stehen dicht an dicht, sodass der
     Fehlgriff einen anderen Zug spielt und die Stellung wechselt. Die
     Polsterung wächst nach oben und unten, der negative Außenabstand nimmt
     sie der Zeile wieder weg: Der Streifen bricht sonst früher um und die
     Notation liest sich nicht mehr als Notation. */
  .boardPage .moveBtn {
    min-height: 24px;
    padding-block: 4px;
    margin-block: -3px;
  }
}
