/* =============================================================================
   ÜBERNOMMEN aus design-system/traveto/base.css — NICHT VON HAND ÄNDERN.
   Quelle ist das Design-System; hier liegt nur ein Spiegel, damit das Theme
   ohne den Nachbarordner deploybar ist. Ändern heißt: dort ändern, dann
   »bash deploy/sync-design-system.sh« und committen.
   ============================================================================= */
/* =============================================================================
   TRAVETO — Base Layer
   Schriftimport, Reset, Element-Defaults, Typo-Rollen, Layout-Primitiven.
   Setzt tokens.css voraus.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   Schrift — drei variable Familien, drei getrennte Aufgaben.

   Bricolage Grotesque  Display und Ueberschriften. Grotesk mit sichtbaren
                        Tintenfallen, gemischten Strichstaerken und echter
                        opsz-Achse: bei 88px eine andere Zeichnung als bei 30px.
                        Laut genug fuer eine Schlagzeile, ohne Zierschrift zu sein.
   Archivo              Fliesstext und Bedienoberflaeche. Gothic-Werkschrift aus
                        der Linie amerikanischer Wegweiserschriften — grosse
                        x-Hoehe, offene Punzen, bei 12px noch lesbar. Die
                        wdth-Achse traegt das kleine Versalien-Label.
   JetBrains Mono       Daten und deklarierte Werte: Koordinaten, Distanzen,
                        Zeiten, IDs, Hexwerte, Tokennamen, CSS-Werte und
                        Messzahlen. Nie Fliesstext, nie Ueberschrift, nie ein
                        Wort ohne Zahl oder Kennung daneben.
   ----------------------------------------------------------------------------- */
/* DER SCHRIFTIMPORT STEHT NICHT MEHR HIER, sondern in schriften-cdn.css,
   und die laden nur die BELEGBLAETTER. Grund: base.css wird ausgeliefert —
   das Marketing-Theme spiegelt es, die Anwendung importiert es direkt —,
   und ein @import auf fonts.googleapis.com uebertraegt die IP jedes
   Nutzers an Google (LG Muenchen I, 3 O 17493/20). Das Theme hat den
   Import beim Spiegeln entfernt, also die Kopie repariert statt der
   Quelle; die Anwendung bekam ihn dadurch ungefiltert, mit 21 zusaetzlichen
   @font-face-Regeln auf fonts.gstatic.com im fertigen Build.
   Wer base.css ausliefert, bringt seine Schriften selbst mit. */

/* -----------------------------------------------------------------------------
   Reset
   ----------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Graustufen-Antialiasing angefordert. Ob der Browser es liefert, entscheidet
   er selbst: unter Windows zeichnet Chrome weiterhin Subpixel, und im Rendering
   sind farbige Saeume messbar. Die Zeile ist eine Bitte, keine Zusage. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-text);
  font-weight: var(--weight-regular);
  font-size: var(--text-body-size);
  line-height: var(--text-body-lh);
  letter-spacing: normal;
  font-synthesis-weight: none;
  font-variation-settings: "wdth" 100;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }

/* Ueberschriften laufen in der Displayschrift. Bis Stueck 2, Runde 5 stand das
   NUR in den Klassen .t-display/.t-h1/.t-h2/.t-h3 — und die benutzt kein einziges
   Belegblatt. Alle H1 bis H3 erbten damit --font-text (Archivo), und genau das
   Merkmal, mit dem PALETTE.md die Abgrenzung gegen Going begruendet (schmale
   Grotesk mit Tintenfallen gegen normalbreite geometrische), war nirgends
   gezeichnet. Die Schrift war geladen, sie wurde nur nie angefordert. */
/* Die ELEMENTE tragen ihre Stufe, nicht nur die .t-*-Klassen. Bis Runde 5b
   setzte base.css hier keine einzige Groesse — jedes Blatt hat seine
   Ueberschriften deshalb selbst deklariert, und genau dabei sind sie
   auseinandergelaufen (25 statt 30, 1.05 statt 1.12). Eine Stufe, die nur
   ueber eine Hilfsklasse erreichbar ist, wird auf Dauer nicht benutzt. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-variation-settings: "opsz" var(--opsz-h2), "wdth" var(--wdth-display);
}
/* Jede Stufe traegt ihr DEKLARIERTES Gewicht (PALETTE.md Paragraph 7:
   Display 800, H1 700, H2 600, H3 600). Bis Runde 6 gaben die ELEMENTE allen
   dreien 700, waehrend die gleichnamigen KLASSEN .t-h2/.t-h3 600 setzten —
   derselbe Rang in zwei Gewichten, je nachdem ob man das Element oder die
   Hilfsklasse benutzt, und das mitten in der Datei, die beide definiert. */
h1 { font-size: var(--text-h1-size); line-height: var(--text-h1-lh);
     font-weight: var(--weight-bold);
     font-variation-settings: "opsz" var(--opsz-h1), "wdth" var(--wdth-display); }
h2 { font-size: var(--text-h2-size); line-height: var(--text-h2-lh);
     font-weight: var(--weight-semibold);
     font-variation-settings: "opsz" var(--opsz-h2), "wdth" var(--wdth-heading); }
h3 { font-size: var(--text-h3-size); line-height: var(--text-h3-lh);
     font-weight: var(--weight-semibold);
     font-variation-settings: "opsz" var(--opsz-h3), "wdth" var(--wdth-heading); }
/* UEBER EINER UEBERSCHRIFT STEHT LUFT — und zwar EIN Wert, nicht der jeweilige
   Restrand des Blocks davor. Bis Runde 10 gehoerte dieser Abstand jedem
   vorangehenden Bauteil einzeln, also niemandem: dieselbe Beziehung mass ueber
   die sechs Blaetter 34,0 / 36,0 / 39,4 / 41,4 / 52,0 px — und auf
   fotografie.html 0,0, weil "Und danach ansehen — vergroessert" auf der letzten
   Zeile der Liste darueber sass.
   Es ist eine UNTERGRENZE, kein Zuschlag: im normalen Fluss faellt margin-top
   mit dem margin-bottom des Vorgaengers zusammen, der groessere gewinnt. Wo ein
   Blatt mehr Luft will, behaelt es sie. */
:is(h2, h3):not(:first-child) { margin-top: var(--kopf-luft); }

/* ALLE DREI ACHSEN, nicht nur das Gewicht. In Runde 6 stand hier der Kommentar,
   dass Element und Hilfsklasse denselben Rang in zwei GEWICHTEN setzten — das
   wurde repariert. Breite und optische Groesse blieben stehen: <h2> erbte
   "wdth" 78 aus der Gruppenregel, .t-h2 setzte 88. Gemessen an identischem
   Text: 223,03 px gegen 253,83 px, ein Unterschied von 13,8 %. Fuenf Blaetter
   zeichneten ihre H2 als Element, foundation.html als Klasse — dasselbe Wort
   in zwei Schriftbildern. Eine Achse zu pruefen und die anderen stehen zu
   lassen ist dieselbe Sorte Fehler wie eine Fundstelle zu pruefen und die
   anderen stehen zu lassen. */

/* Optische Kante. Grosse Grade tragen eine Vorbreite, die sie sichtbar rechts
   der Fliesstextkante absetzt. Der negative Erstzeileneinzug holt sie zurueck.

   Er ist ein KOMPROMISS und kein exakter Ausgleich: die Vorbreite haengt am
   Anfangsbuchstaben. Bei -0,055em ueberschoss die Korrektur bei Diagonalen
   (A, V) um bis zu 3 px nach links und unterschoss bei Staemmen (H, n) —
   gemessene Spanne 177..182 gegen eine Satzkante von 180.

   WAS DAS MITTEL KANN UND WAS NICHT: text-indent greift ausschliesslich auf
   die ERSTE Zeile. Eine dreizeilige Ueberschrift behaelt darunter ihre volle
   Spanne — auf dem Blatt gemessen 179,50 / 182,00 / 180,50, also 2,50 px.
   Hier stand bis Runde 5 "bei -0,03em bleibt die Spanne unter 2 px"; das war
   fuer die erste Zeile gemeint und als Zusage fuer die Ueberschrift
   hingeschrieben. Es korrigiert einen Fehler pro Block, den es pro Zeile gibt.
   Exakt geht es in CSS nur pro Buchstabe, und das waere teurer als der Fehler.

   Nicht auf zentrierten Satz: dort gibt es keine linke Satzkante, an der eine
   Rundung haengen koennte, und die Einrueckung verschoebe nur die Mitte. */
h1, h2 { text-indent: -0.03em; }
:is(h1, h2)[style*="center"], .satz--mitte, [align="center"] :is(h1, h2),
.b--tinte .satz { text-indent: 0; }

/* Umbruch. `pretty` verhindert die EINZELWORTZEILE am Absatzende — mehr nicht:
   eine letzte Zeile mit einem Fuenftel der Satzbreite bleibt zulaessig.
   Hier stand dazu "kommt auf dem Blatt dreimal vor (21 / 20 / 24 %)". Die Reihe
   reproduzierte auf keinem der sechs Blaetter: gemessen sind es 0 / 4 / 2 / 3 /
   3 / 10 Faelle, und auf foundation.html geht einer bis 12 %. Eine von Hand
   nachgezaehlte Reihe in einer geteilten Datei — dieselbe Sorte wie die
   Reisskanten-Reihe, die Runde 17 aus startseite.html genommen hat. Was zaehlt,
   ist die Untergrenze, und die misst blatt-pruefung.js Pruefung (9).
   Hier stand "haelt die letzte Zeile eines Absatzes gefuellt". Das kann die
   Eigenschaft nicht und tut sie nicht.
   `balance` gleicht Ueberschriftzeilen aus — aber nur innerhalb eines
   Zeilenkastens: ein von Hand gesetztes <br> zerlegt die Ueberschrift in zwei
   Kontexte, und in keinem davon kann balance noch etwas retten. Deshalb hat
   dieses Blatt seit Runde 5b KEINE Handumbrueche mehr in h1 und h2. */
p, li { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
/* DIE SPERRUNG WIRD UEBER DIE SIGNETKANTE BEMASST, NIE UEBER DIE BREITE.
   MARKE.md nennt eine Mindest-Signetkante (64 px), keine Mindestbreite; die
   Signetkante ist die Hoehe der Datei (sperrung.svg: viewBox 269 x 96). Das
   Blatt gibt deshalb nur die Kante an, die Breite folgt aus der Datei.

   Bis Runde 10 stand hier eine feste Hoehe von 64 px — repariert an der einen
   Fundstelle, an der der Fehler gefunden worden war. Die vier Auftritte auf
   marke.html trugen die Klasse gar nicht und deklarierten 207 x 72 und
   276 x 96; gerendert wurden 207 x 73,86 und 276 x 98,48, weil 207/72 nicht das
   Seitenverhaeltnis der Datei ist. Eine davon war die Schutzraumfigur, deren
   Polster "halbe Signethoehe" heisst: 48 px gezeichnet, 49,24 px verlangt.
   Wer die Breite angibt, gibt die falsche Groesse an. */
img.sperrung { width: auto; height: var(--sperrung-kante, 64px); }

button, input, select, textarea { font: inherit; letter-spacing: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
table { border-collapse: collapse; width: 100%; }
/* Kein eigener Grad: 0,94em ergab 15,04 px und 13,16 px und machte aus drei
   laufenden Groessen fuenf. Mono laeuft auf dem Grad seiner Umgebung. */
code, kbd, samp, pre { font-family: var(--font-mono); font-size: 1em; }

/* Platzhalter benutzt die Sekundaerfarbe, nie --text-disabled:
   Platzhaltertext ist Text und faellt unter WCAG 1.4.3. */
::placeholder { color: var(--text-muted); opacity: 1; }

hr {
  border: 0;
  border-top: var(--border-hairline) solid var(--line);
  margin: var(--tv-space-4) 0;
}

a { color: var(--action-text); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--action-hover); }
/* DER DRITTE ZUSTAND FEHLTE IM GANZEN SYSTEM. Deklariert waren a und a:hover;
   ein a:active gab es auf keinem der sieben Blaetter. Gemessen mit gehaltener
   Maustaste ueber alle Verweise: Hover und Gedrueckt waren ueberall dieselbe
   Zeichnung. Was das System an seine Knoepfe anlegt — Ruhe, Hover, Gedrueckt
   als drei Stufen —, gilt auch fuer einen Verweis. */
a:active { color: var(--action-press); }

/* -----------------------------------------------------------------------------
   Fokus — Bluete, immer sichtbar. Der Ring folgt der Form des Elements;
   er fuehrt keinen eigenen Radius ein.
   ----------------------------------------------------------------------------- */
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }
/* Auf dem dunklen Band die helle Fassung — sonst steht der Ring bei 1,25 : 1. */
.b--tinte :focus-visible, [data-grund="tinte"] :focus-visible { outline-color: var(--focus-ring-hell); }

/* DIE UMKEHRFLAECHE SETZT IHRE EIGENEN ROLLEN — EINMAL, FUER ALLES DARIN.
   Vorher trug .b--tinte nur den hellen Fokusring. Jedes Bauteil darin behielt
   die Farben der HELLEN Flaeche, und jedes einzelne fiel dort durch:
     --text-muted #473B35 auf --bg-inverse #382E29 . . . 1,22 : 1
     --action-text #7E0938 auf --bg-inverse . . . . . . . 1,25 : 1
     --line-strong #584F49 als Kontur  . . . . . . . . . . 1,65 : 1
   Gemessen an der Marketing-Startseite: acht Textknoten unter der Schranke,
   alle auf den beiden dunklen Baendern, und der konturierte Knopf im
   Schlussband war schlicht unsichtbar.
   Das an jedem Bauteil einzeln zu reparieren waere die Fundstelle statt der
   Regel. Die Flaeche belegt deshalb die SEMANTISCHEN Token fuer ihren Teilbaum
   neu — danach stimmt jedes Bauteil darin von selbst, auch jedes kuenftige. */
.b--tinte, [data-grund="tinte"] {
  --text:        var(--text-inverse);
  --text-muted:  var(--text-inverse-muted);
  --line:        var(--line-inverse);
  --line-strong: var(--text-inverse-muted);
  /* Die Bluete als SCHRIFT traegt auf dunklem Grund nicht (1,25 : 1); der
     Hauch schon (6,48 : 1). Die gefuellte Aktionsflaeche bleibt, wie sie ist —
     --text-on-action darauf ist von der Flaeche her hell. */
  --action-text: var(--action-wash);
}

/* WER AUF DER UMKEHRFLAECHE SEINE EIGENE HELLE FLAECHE MITBRINGT, HOLT SICH
   DIE HELLEN ROLLEN ZURUECK.
   Die Neubelegung oben gilt fuer den ganzen Teilbaum — auch fuer Bauteile, die
   darin einen eigenen hellen Grund malen. Der helle Knopf im Tintenband hat
   das sofort gezeigt: seine Beschriftung nahm --action-text, das dort auf den
   Hauch zeigt, und stand mit 2,01 : 1 auf seiner eigenen lichten Flaeche.
   Ein Kasten, der die Flaeche wechselt, wechselt auch die Rollen zurueck. */
.b--tinte :is(.t-knopf--hell, .t-tafel, .mapcard, .karte),
[data-grund="tinte"] :is(.t-knopf--hell, .t-tafel, .mapcard, .karte) {
  --text:        var(--tv-kastanie);
  --text-muted:  var(--tv-kastanie-soft);
  --line:        var(--tv-linen-400);
  --line-strong: var(--tv-linen-500);
  --action-text: var(--tv-bluete-text);
}

/* DER KONTURIERTE KNOPF AUF DER UMKEHRFLAECHE.
   Es gab ihn nicht. .t-knopf--kontur traegt --text und --line-strong — beide
   dunkel, beide fuer einen hellen Grund gedacht. Auf --bg-inverse (L* 19,9)
   ergibt das eine unsichtbare Kontur mit unsichtbarer Schrift; die Marketing-
   Site hat im Schlussband genau diesen Fall, und die Fusszeile der App ebenso.
   Die Umkehrflaeche hat ihre eigenen Token: --text-inverse fuer die Schrift,
   --line-inverse fuer die Linie. Die drei Stufen laufen hier nach OBEN, weil
   nach unten kein Platz mehr ist: Ruhe durchsichtig, Hover eine helle Spur,
   Gedrueckt eine Spur mehr plus der bewegungsfreie Schatten. */
.b--tinte .t-knopf--kontur, [data-grund="tinte"] .t-knopf--kontur {
  background: transparent; color: var(--text);
  border-color: var(--line);
}
.b--tinte .t-knopf--kontur:hover, [data-grund="tinte"] .t-knopf--kontur:hover {
  background: color-mix(in srgb, var(--text-inverse) 10%, transparent);
  border-color: var(--text-inverse);
}
.b--tinte .t-knopf--kontur:active, [data-grund="tinte"] .t-knopf--kontur:active {
  background: color-mix(in srgb, var(--text-inverse) 18%, transparent);
  border-color: var(--text-inverse);
  box-shadow: var(--press-inset); transform: translateY(1px);
}
@media (prefers-reduced-motion: reduce) {
  .b--tinte .t-knopf--kontur:active,
  [data-grund="tinte"] .t-knopf--kontur:active { transform: none; }
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--action-wash); color: var(--text); }

/* Die Markierung hinter Text ist eine kleine gefuellte Flaeche — die einzige
   in --action-wash. Sie traegt den Pillenradius, weil sie die Form eines
   Bedienelements hat. Scharfe Ecken gibt es im System gar nicht mehr: die
   Sonderform des Fremdmaterials ist in PALETTE.md 4 und 8 zurueckgenommen. */
mark {
  background: var(--action-wash);
  color: var(--text);
  border-radius: var(--radius-control);
  padding: 0.08em 0.4em;
  margin-inline: -0.1em;
}

/* -----------------------------------------------------------------------------
   Typografie — Rollen

   Eine einzige Regel traegt die ganze Ebene: letter-spacing bleibt `normal`.
   Weder gesperrt noch gestaucht, in keiner Groesse. Die einzige Ausnahme ist
   .t-over, das kleine Versalien-Label.

   Display 88px steht direkt neben Fliesstext 16px — Faktor 5,5.
   Laufende Groessen — nach bar.md "setzt ganze Saetze in Absaetzen", nicht nach
   der Groesse: VIER (25 / 16 / 14 / 12). Das ist M1s Obergrenze; das Referenzmaß
   sind drei. Hier stand bis Runde 7 "genau drei (16 / 14 / 12)" mit der
   Begruendung, .t-lead liege ueber 24px — eine Definition, die der Prueflings
   selbst liefert, misst nichts.
   .t-lead ist der EINLEITUNGSABSATZ und NUR das. Der Bauteiltitel (Kartentitel,
   Dialogtitel, Zeilentitel) gehoert NICHT hierher, er steht auf der h3-Stufe;
   die Aufzaehlung "h3, Kartentitel, Dialogtitel" stand bis Runde 5b
   faelschlich in dieser Zeile und war der Grund, warum 25 px auf fuenf
   Blaettern drei Behandlungen trug.
   Der zweite Teil fehlte hier, obwohl tokens.css und
   PALETTE.md ihn seit Stueck 2 fuehren — die Datei, die .t-lead definiert,
   war die letzte, die es nicht wusste. Die frueher hier
   stehende Zusage "hoechstens zweimal pro Seite" ist gestrichen — siehe
   tokens.css: eine Zwischenueberschrift darf so oft vorkommen wie es
   Abschnitte gibt.
   ----------------------------------------------------------------------------- */
/* Die Hilfsklasse setzt, was das gleichnamige Element setzt — sonst tragen
   .t-display und h1 (Display 88px) verschiedene Gewichte und opsz. */
.t-display, .t-h1, .t-h2, .t-h3 {
  font-family: var(--font-display);
  letter-spacing: normal;
  text-wrap: balance;
}

/* -----------------------------------------------------------------------------
   EIN GRAD, EIN DURCHSCHUSS.
   tokens.css paart jede Lesegroesse mit ihrem Durchschuss (25/1,44 · 16/1,60 ·
   14/1,50 · 12/1,42). Auf dem Blatt lief 12 px an sieben Stellen mit 1,65 und
   14 px mit 1,50, 1,60 und 1,65 — von den drei 14er-Werten war einer der
   deklarierte. Wer eine Groesse setzt, bekommt ihren Durchschuss dazu; wer
   einen anderen will, deklariert ihn und begruendet ihn.
   ----------------------------------------------------------------------------- */
[style*="font-size:12px"], [style*="font-size: 12px"] { line-height: var(--text-caption-lh); }

/* -----------------------------------------------------------------------------
   AVATARSTAPEL — eine Initiale je Person, ueberlappend.
   Stand bis Runde 14 zweimal lokal, in zwei Massen: 32 px mit --radius-circle
   auf der Startseite, 30 px mit rohem 50 % auf app-aufnahmen. ANWENDUNG.md
   nannte den Mangel und verwies ihn auf eine Liste, die ihn nicht fuehrte.
   Der Traegergrund bleibt lokal: der Ring stellt den Kreis gegen die Flaeche
   frei, auf der er liegt, und die ist nicht auf jedem Blatt dieselbe.
   ----------------------------------------------------------------------------- */
.faces { display: flex; }
.faces > * {
  width: 32px; height: 32px; border-radius: var(--radius-circle);
  border: 2px solid var(--bg-float); background: var(--bg-sunken);
  display: grid; place-items: center;
  font-size: var(--text-caption-size); line-height: 1; font-weight: var(--weight-semibold);
  color: var(--text-muted);
}
.faces > * + * { margin-left: -10px; }
/* DIE INITIALE STEHT IN DER SICHTBAREN SICHEL, NICHT IN DER GANZEN SCHEIBE.
   Jede Scheibe ausser der letzten ist rechts um 10 px verdeckt; die Glyphe war
   trotzdem auf die volle Breite von 32 px zentriert und stand damit in einer
   22 px breiten Sichel um 5 px zu weit rechts. Gemessen: das "M" hatte links
   9,9 px Luft und rechts 1,9 px und stiess bei 1:1 an die Schnittkante,
   waehrend die letzte, unbeschnittene Scheibe als einzige mittig sass.
   Das Polster verschiebt die Inhaltsbox um genau die Verdeckung. */
.faces > *:not(:last-child) { padding-right: 10px; }

/* -----------------------------------------------------------------------------
   KARTENFLAECHE — Bild und Zug liegen deckungsgleich uebereinander.
   Stand bis Runde 16 ZWEIMAL lokal und byteidentisch (startseite.html,
   karte.html) — und in karte.html unmittelbar ueber drei Kommentaren, die
   fuer .t-tafel, .t-over und .pill protokollieren, dass genau das nicht mehr
   vorkommt. Jedes andere geteilte Bauteil ist zwischen Runde 5b und 14
   hierhergewandert; die Flaeche, die ein eigenes Dokument hat (KARTE.md) und
   der Gegenstand des ganzen Stuecks ist, war die letzte, die es nicht war.
   Lokal bleibt allein die GEOMETRIE (aspect-ratio gegen feste Hoehe): sie ist
   der Ausschnitt, gegen den der Routenzug gerechnet ist, und der ist je Blatt
   ein anderer. Was hier steht, ist Zeichnung, nicht Platzierung.
   ----------------------------------------------------------------------------- */
/* z-index: 0 SCHLIESST LEAFLETS EBENEN EIN. Ohne eigenen Stapelkontext
   konkurrieren die Kartenebenen (Leaflet vergibt bis 700) im Stapel des
   Elternteils — die Tafel stand mit z-index auto DARUNTER und war nicht zu
   sehen, obwohl sie im Baum stand und an der richtigen Stelle gemessen wurde. */
.mapcard { position: relative; border-radius: var(--radius-surface);
           overflow: hidden; border: 1px solid var(--line); z-index: 0;
/* EINE FLAECHE MIT AUFLAGE BRAUCHT HOEHE FUER DIE AUFLAGE — aber nicht
              ueber min-height. Auf einer Flaeche mit aspect-ratio rechnet der
              Browser aus einer Mindesthoehe eine MINDESTBREITE zurueck: mit
              min-height 420 und 1080/520 wurde das Belegblatt 962 px breit und
              lief bei 944 px Fenster um 18 px waagerecht ueber. Die Hoehe
              kommt deshalb aus dem Seitenverhaeltnis selbst, das die Blaetter
              bei schmalen Breiten aendern. */ }
/* 800, nicht 1: die Tafel liegt INNERHALB der Kartenflaeche und konkurriert
   dort mit Leaflets eigenen Ebenen, die bis 700 gehen (markerPane 600,
   tooltipPane 650, popupPane 700). Mit z-index 1 lag sie unter den Kacheln —
   auf dem Belegblatt und der Startseite war sie nicht zu sehen, und die
   Zustandspruefung meldete dieselben Marken als "hinter der Tafel", weil sie
   rechnerisch dort lagen. In anwendung.html steht die Tafel NEBEN der Karte;
   dort genuegte 1, und genau das hat mich hier in die Irre gefuehrt. */
.mapcard .t-tafel { z-index: var(--z-karte-auflage); }
/* Die 800 stand hier als Zahl. Sie steht jetzt als Stufe in tokens.css —
   die Anwendung braucht dieselbe Leiter fuer Dialoge und Leisten, und zwei
   Stellen, die dieselbe Reihenfolge von Hand fuehren, laufen auseinander. */
/* HIER STANDEN ZWEI REGELN DER GEZEICHNETEN KARTE:
     .mapcard img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover }
     .mapcard svg { position:absolute; inset:0; width:100%; height:100% }
   Sie zwangen das Kartenbild und die Zeichnung darueber auf denselben
   Ausschnitt — genau richtig, solange beides von Hand gemacht war.
   Seit die Flaechen echtes Leaflet sind, treffen sie etwas anderes: JEDE
   Kachel ist ein <img>, und die Overlay-Ebene ist ein <svg>. Beide wurden
   damit auf die volle Flaeche der Karte gedehnt; der Routenzug lag nicht mehr
   dort, wo seine Koordinaten hinzeigen, und war praktisch unsichtbar.
   Eine Regel, die auf einen Bauteiltyp zielt und dabei jedes Element mit
   diesem Tag erwischt, ist eine Regel ohne Gegenstand. */

/* ---------- Die Kacheln ------------------------------------------------------
   DIE BEHANDLUNG STEHT EINMAL, FUER JEDE KARTE DES SYSTEMS. Sie stand zuerst
   inline in anwendung.html, an .karte gebunden — die anderen drei Flaechen
   heissen .mapcard und bekamen deshalb rohe OSM-Kacheln: bunt, laut, und neben
   der Palette. Der Filter selbst steht in tokens.css, weil er auch fuer das
   Bauteil im Produkt gilt.
   -------------------------------------------------------------------------- */
.leaflet-tile-pane { filter: var(--map-kachel-filter); }
/* Der Grund unter den Kacheln ist ein Token, kein Fremdwert. Leaflet setzt
   #ddd — exakt unbunt (a* 0,00 / b* 0,00) und damit die einzige neutrale
   Flaeche des Systems, ausgerechnet dort, wo W2 Waerme verlangt. Sichtbar ist
   sie, solange Kacheln fehlen oder nachladen. */
.leaflet-container { background: var(--map-paper); }
/* Die Herkunftsangabe ist Pflicht (ODbL) und Teil des Entwurfs, keine Zutat.
   Deckend, nicht durchscheinend: mit 82 Prozent Deckung wurde die Textschranke
   gegen die Kachel darunter gemessen und riss bei 1,93 : 1. */
/* -----------------------------------------------------------------------------
   DIE ZOOMSTEUERUNG.

   Sie stand bisher in KEINER Regel dieses Systems — und zwar aus einem Grund,
   der nur fuer die Belegblaetter gilt: karte.js schaltet sie ab
   (zoomControl: false), weil ein Blatt einen festen Ausschnitt zeigt. Die
   ANWENDUNG zeigt sie. Gemessen an /public/map liefen ihre beiden Knoepfe
   deshalb in Leaflets Vorgabe — `font: bold 18px 'Lucida Console', Monaco,
   monospace`, eine vierte Familie ausserhalb der drei des Systems, und ein
   Grad und eine Form, die keine Leiter kennt.

   Dass ein Bauteil auf allen Blaettern abgeschaltet ist, heisst nicht, dass
   es das Bauteil nicht gibt. Es heisst, dass niemand hinsieht.

   Kein eigener Rang: das ist ein Bedienelement in der dichten Stufe.
   ----------------------------------------------------------------------------- */
.leaflet-bar {
  border: var(--border-hairline) solid var(--line);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow-float);
  overflow: hidden;
}
.leaflet-bar a,
.leaflet-control-zoom a {
  width: var(--knopf-hoehe-klein); height: var(--knopf-hoehe-klein);
  line-height: var(--knopf-hoehe-klein);
  background: var(--bg-float); color: var(--text);
  font-family: var(--font-text);
  font-size: var(--text-body-size); font-weight: var(--weight-semibold);
  border-bottom: var(--border-hairline) solid var(--line);
}
.leaflet-bar a:last-child { border-bottom: 0; }
.leaflet-bar a:hover  { background: var(--bg-sunken); color: var(--text); }
.leaflet-bar a:active { background: var(--bg-sunken); box-shadow: var(--press-inset); }
/* Leaflet setzt fuer den gesperrten Knopf eine eigene Klasse. Deaktiviert
   verliert die Farbe ganz (ANWENDUNG.md §4). */
.leaflet-bar a.leaflet-disabled {
  background: var(--bg-sunken); color: var(--text-disabled); cursor: not-allowed;
}

/* Der Abstand ist kein Zierrat: die Angabe sass buendig in der Ecke, und der
   Fokusring ihres Verweises lag damit in fuenf von fuenf geprueften Groessen
   teilweise ausserhalb des Fensters. Ein Ring, den man nicht ganz sieht, ist
   kein Fokusmerkmal. */
.leaflet-control-attribution {
  background: var(--bg-float); color: var(--text-muted);
  font-size: 10px; padding: 2px 6px; margin: 0 4px 4px 0;
  border-radius: var(--radius-control);
}
.leaflet-control-attribution a:focus-visible { outline-offset: 1px; }
/* Auch der Link in der Herkunftsangabe ist ein Bedienelement — er kam mit der
   Bibliothek und hatte deshalb keinen der drei Zustaende. */
.leaflet-control-attribution a { color: var(--action-text); text-decoration: none; }
.leaflet-control-attribution a:hover { color: var(--action-hover); text-decoration: underline; }
.leaflet-control-attribution a:active { color: var(--action-press); text-decoration: underline; }
/* Der Fokusring liegt INNEN: Leaflet macht den Behaelter tastaturbedienbar,
   und eine randlose Flaeche kann keinen aussenliegenden Ring zeigen. */
.leaflet-container:focus-visible { outline-offset: -3px; }
.leaflet-container { font: inherit; }

/* -----------------------------------------------------------------------------
   KARTENPUNKT — die Rollen, die KARTE.md deklariert.
   Kern 18 (ausgewaehlt 22, Pausenplatz 12) plus 2 px Hoefchen in --bg-float;
   box-sizing: border-box, die BREITE ist also Kern + 2 x Ring.
   Stand bis Runde 13 zweimal lokal, in zwei Fassungen (einmal absolut ueber der
   Karte mit --radius-circle, einmal inline mit 50 % und eigenem box-sizing) —
   und das ausgerechnet bei dem Bauteil, dessen Uneinheitlichkeit das Projekt in
   Runde 10 und 12 zweimal als Befund gefuehrt hat ("ein Zustand in drei
   Massen"). Was lokal bleibt, ist nur die PLATZIERUNG: absolut auf der Karte,
   inline in der Legende.
   ----------------------------------------------------------------------------- */
.pin {
  width: 22px; height: 22px; box-sizing: border-box;
  border-radius: var(--radius-circle);
  border: 2px solid var(--bg-float);
  background: var(--map-pin);
  /* Dieselbe zweite, dunkle Haarlinie wie die Marke auf der Karte. Ohne sie
     zeigt die Legende ein anderes Bauteil als das, was daneben liegt. */
  box-shadow: 0 0 0 1px var(--line); }
/* Der Ortspunkt traegt die Grundfassung und deklariert nichts weiter — die
   Klasse steht trotzdem, damit jede Rolle auf dem Blatt einen Namen hat. */
.pin--ort      { }
.pin--gewaehlt { width: 26px; height: 26px; background: var(--map-pin-selected); }
.pin--pause    { width: 16px; height: 16px; }
.pin--pruefen  { background: var(--map-pin-pruefen); }
/* Die Luecke ist HOHL, nicht randlos: Kontur innen, Aussenmass bleibt 22, das
   Hoefchen bleibt — sonst steht dieser eine Pin ohne Freistellung auf der Karte. */
.pin--luecke   { background: var(--bg-float); box-shadow: inset 0 0 0 3px var(--danger); }

/* -----------------------------------------------------------------------------
   ZUSTANDSMARKE — die Pille, die sagt, woran eine Zeile ist.
   bar.md M5 fuehrt sie ausdruecklich als Bedienelementform (Pillenradius, auch
   wenn sie nicht klickbar ist). Sie stand bis Runde 12 ZWEIMAL lokal und
   nirgends geteilt — und die beiden Fassungen setzten die Schrift verschieden
   in die Pille: startseite ueber Flexzentrierung (Tinte 4,09 px unter der
   Oberkante), app-aufnahmen ueber line-height: 22px (5,00 px). Gleiche Rolle,
   gleiches Mass, zwei Zeichnungen, 0,9 px Versatz.
   .t-knopf (Runde 6), .t-titel (5b), .t-tafel (8) und .t-over (11) sind aus
   genau diesem Grund hierher gewandert.
   Die FARBE bleibt lokal: sie ist der Zustand, nicht das Bauteil.
   ----------------------------------------------------------------------------- */
/* DIE PILLE TRAEGT IHREN EIGENEN GRUND.
   Ohne ihn haengt ihr Kontrast an der Flaeche, auf der sie gerade liegt: auf der
   ausgewaehlten Zeile (--action-wash) fiel Bernstein auf 3,39 : 1, waehrend
   dieselbe Pille auf --bg bei 5,20 : 1 liegt. Ein Statusmerkmal, dessen
   Lesbarkeit vom Zustand der Zeile abhaengt, sagt genau dann am wenigsten, wenn
   die Zeile ausgewaehlt ist. */
.pill {
  display: inline-flex; align-items: center; justify-content: center;
  height: 24px; padding-inline: 11px; background: var(--bg-float);
  border-radius: var(--radius-control); border: var(--border-hairline) solid currentColor;
  font-size: var(--text-over-size); letter-spacing: var(--text-over-ls);
  text-transform: uppercase; font-weight: var(--weight-semibold);
  font-variation-settings: "wdth" 110;
  line-height: 1; white-space: nowrap; color: var(--text-muted);
}

/* DIE ZUSTAENDE DER PILLE ALS VARIANTEN, NICHT ALS style-ATTRIBUT.
   startseite.html setzte sie dreimal inline (style="color:var(--success)").
   Ein Zustand ist eine Rolle des Bauteils und gehoert deshalb hierher — sonst
   traegt jedes Blatt seine eigene Fassung, und wer die Rolle verschiebt, muss
   sie in jedem Blatt suchen. Der Rand ist currentColor: Farbe UND Kontur
   folgen der Rolle aus einer Deklaration.
   Die Rollen-Token, nicht die Primitive: keine Komponente greift durch. */
.pill--gebucht { color: var(--success); }
.pill--pruefen { color: var(--warning); }
.pill--luecke  { color: var(--danger); }

/* -----------------------------------------------------------------------------
   BREITES EINZELGUT ROLLT IN SEINEM EIGENEN KASTEN.
   Eine Tabelle hat eine Mindestbreite, die aus ihrem Inhalt folgt; ein Fenster
   von 320 px hat sie nicht. Bis Stueck 4, Runde 7 lief deshalb die SEITE ueber
   — auf sechs von sieben Blaettern, gemessen bis 301 px Ueberstand. Die Seite
   darf das nicht; das einzelne breite Ding darf es.
   ----------------------------------------------------------------------------- */
table { display: block; max-width: 100%; overflow-x: auto; }

/* -----------------------------------------------------------------------------
   RANDBESCHRIFTUNG — das Leitmotiv des Systems.
   Messwerte am Rand einer Flaeche, in der Datenschrift, auf der leisen
   Textfarbe: Position, Abschnitt, Stand. Dasselbe, was am Rand einer Karte
   steht. Sie stand bis Runde 11 lokal auf EINEM Blatt und war damit keine
   Marginalie, sondern eine Beschriftung — ein Motiv, das nur dort auftritt, wo
   es woertlich zutrifft, ist keins. Ausgerechnet karte.html trug null.
   Kein neuer Grad: 12 px ist die Etikettenstufe, die das System schon fuehrt.
   ----------------------------------------------------------------------------- */
.marginalie {
  display: flex; flex-wrap: wrap; gap: 4px var(--tv-space-4);
  margin: var(--tv-space-2) 0 0;
  /* KEIN Prosamass. Auf drei Blaettern erbte die Zeile .head p { max-width:
     66ch } — ein Satzmass, das auf 12 px Mono zu 453,8 px rechnet statt zu den
     ~600, fuer die es gedacht ist. Die dreifeldrige Zeile brach dadurch um, das
     dritte Feld stand allein auf Zeile 2, und ueber ihm lagen 100 px leere
     Zeile. Genau das Bauteil, dessen Kommentar sagt, es sei "eine
     Messwertzeile, kein Satz". */
  max-width: none;
  font-size: var(--text-caption-size); line-height: var(--text-caption-lh);
  color: var(--text-muted);
}
/* DAS WORT STEHT IN ARCHIVO, DER WERT IN MONO — und zwar auf allen fuenf
   Blaettern gleich.
   Bis Runde 12 trug das dritte Feld auf drei von fuenf Blaettern Archivo und
   auf zweien Mono: dieselbe Sorte Aussage in zwei Schnitten. Die Antwort darauf
   war "JEDES Feld laeuft in der Datenschrift" — und die geriet in Widerspruch
   zur Satzregel des Systems (ANWENDUNG.md Abschnitt 7: "Alles, was BENENNT,
   laeuft in Archivo"). Denn ein Feld benennt oft: "Mast 3,5 Einheiten",
   "Farben aus den Token", "geaendert vor 3 Std." — letzteres woertlich das
   Gegenbeispiel des eigenen Registers, gesetzt in JetBrains Mono.
   Zwei Regeln, die einander widersprechen, sind keine Regel. Die Randzeile
   traegt jetzt dieselbe Fuegung, die Teil B von foundation.html seit jeher
   fuehrt: die Beschriftung in der Textschrift, der Wert in .v. Der Befund von
   Runde 12 bleibt behoben, weil das fuer JEDES Feld JEDES Blattes gilt — nicht
   weil alles gleich aussieht, sondern weil dieselbe Unterscheidung ueberall
   dieselbe ist. */
.marginalie > * { font-variant-numeric: tabular-nums; }

/* -----------------------------------------------------------------------------
   DER WERT — die Klasse, mit der ein Blatt sagt "das hier ist ganz ein Wert".
   Sie ist NICHT die einzige Stelle, an der --font-mono steht: das tun auch
   .t-data (die Datenzeile, 59-mal auf foundation.html), code/kbd/samp/pre und
   fuenf lokale Regeln in Belegblaettern (.mono, td.n, .card__m,
   .streifen span). Hier stand "die einzige Klasse, die die Datenschrift
   traegt" — 270 Zeilen ueber .t-data in derselben Datei. Was .v einmalig
   macht, ist die AUSSAGE, nicht die Schrift; geprueft wird ohnehin die
   berechnete Schriftfamilie, nicht die Klasse.
   Sie stand bis Stueck 4, Runde 6 FUENFMAL lokal — anwendung.html,
   startseite.html, app-aufnahmen.html, karte.html, marke.html — und einmal
   unter anderem Namen (.mono in app-aufnahmen.html). Runde 6 hat zwei davon
   eingesammelt und hier "zweimal" geschrieben; der Brief-Kritiker hat die drei
   uebrigen gezaehlt. Ein Kommentar, der eine Zusammenfuehrung behauptet, muss
   die Fundstellen zaehlen, nicht die erledigten. Wer .v setzt, sagt "das hier ist ganz ein Wert" — und
   zustand-pruefung.js prueft genau das an der berechneten Schriftfamilie.
   ----------------------------------------------------------------------------- */
.v { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* -----------------------------------------------------------------------------
   SCHWEBENDE TAFEL — die Karte, die auf einer Kartenflaeche liegt.
   Bis Runde 8 stand sie zweimal lokal und war dabei zu zwei Bauteilen geworden:
   startseite 300 x 259,5 px bei 24/24 Einzug oben links ohne Knopf, karte
   330 x 245,9 px bei 28/28 unten links mit Knopf. Gleicher Name, zwei Anker,
   zwei Einzuege, zwei Breiten. Jetzt eine Deklaration; der Anker ist der
   einzige erlaubte Unterschied und heisst .t-tafel--unten.
   Die Aliasse .float sind in Runde 9 ENTFERNT; .t-tafel ist der einzige Name.
   ----------------------------------------------------------------------------- */
.t-tafel {
  position: absolute; left: var(--tafel-einzug); top: var(--tafel-einzug);
  width: var(--tafel-breite);
  background: var(--bg-float); border-radius: var(--radius-surface);
  padding: 20px 22px 22px; box-shadow: var(--shadow-float);
}
.t-tafel--unten { top: auto; bottom: var(--tafel-einzug); }

/* EINE AUFLAGE, DIE BREITER IST ALS IHRE FLAECHE, IST KEINE AUFLAGE MEHR.
   --tafel-breite ist ein fester Wert. Bei 320 px Fensterbreite mass die Tafel
   auf karte.html 300 px in einer 272 px breiten Karte und war 265 von 363 px
   hoch — 73 Prozent der Flaeche. Der Ausschnitt konnte daraus nichts mehr
   freihalten: zwei Marken lagen dahinter, und overflow: hidden verbarg, dass
   die Tafel seitlich hinauslief.
   Schmal traegt sie deshalb nur, was sie tragen muss: welche Etappe und was zu
   tun ist. Die Masszahl steht auf denselben Blaettern in der Randbeschriftung
   oder der Etappenzeile — sie ist dort nicht knapper, sondern an ihrem Platz.
   Dieselbe Regel wie in anwendung.html unter 420 px Fensterhoehe, nur an der
   Breite gemessen statt an der Hoehe. */
@media (max-width: 700px) {
  .mapcard .t-tafel {
    left: var(--tv-space-2); right: var(--tv-space-2); width: auto;
    padding: var(--tv-space-2) var(--tv-space-3);
  }
  .mapcard .t-tafel > p:not([class]),
  .mapcard .t-tafel > p[data-tafel] { display: none; }
}
/* DIE TAFEL MISST GEGEN IHRE KARTE, NICHT GEGEN DAS FENSTER.
   --tafel-breite ist 300 px fest; die Kartenflaeche schrumpft mit dem Fenster.
   Wird sie zu klein, deckt die Tafel die Marken zu, von denen sie spricht —
   dann steht sie UNTER der Flaeche statt auf ihr: eine Beschriftung, die ihren
   Gegenstand verdeckt, ist keine.
   Bis Stueck 4, Runde 5 hing die Umschaltung an der FENSTERBREITE (unter
   600 px), weil der Fall bei 375 px gefunden worden war. Das ist der Fehler
   dieses Projekts in Reinform: repariert am gefundenen Ort statt an der
   gefundenen Regel. Bei einem 900 px breiten Fenster ist die Hero-Karte der
   Startseite naemlich nur 381,8 x 286,3 px gross — die Tafel (300 x 280,7 zzgl.
   zweimal Einzug) liegt dann auf der ganzen Flaeche, und alle fuenf Marken
   verschwanden dahinter, waehrend das Fenster weit ueber der Schranke lag.
   DER UNTERSCHIED IST DER BAUM, NICHT DIE ROLLE.

   Hier stand "zwei Rollen": die Randbeschriftung NEBEN der Karte und die
   aufliegende Tafel IN ihr. Der System-Kritiker hat nachgemessen, dass das nicht
   traegt — auch die Tafel der Startseite LIEGT auf ihrer Karte (bei 1440 px mit
   32,4 % ihrer Flaeche, position: absolute), und ihre Marken sind genauso um
   sie herum gesetzt wie auf den anderen Blaettern. Der Unterschied ist kein
   Rollenunterschied, sondern ein STAPELPROBLEM, und der stand schon damals vier
   Zeilen weiter unten richtig da:

   (a) Die Tafel ist ein GESCHWISTER der Kartenflaeche (startseite.html, in
       .kartenblock). Wird sie statisch, faellt sie im normalen Fluss UNTER die
       Flaeche — genau das Gewuenschte.
   (b) Die Tafel ist ein KIND der Kartenflaeche (karte.html, app-aufnahmen.html).
       Wird sie dort statisch, landet sie IM Kartenkasten, und Bild und SVG
       stehen absolut positioniert und davor im DOM. Fuer sie ist "flach" keine
       Loesung, sondern der Schaden:
       eine statische Tafel im Kartenkasten wird von Bild und SVG (beide absolut
       und davor im DOM) ueberdeckt oder deckt selbst die Karte von oben zu.
       Genau das ist in Runde 6 passiert, als die Container-Anfrage ohne
       Unterschied auf beide Rollen lief: auf app-aufnahmen.html verschwand die
       Tafel samt Knopf unter der Karte, waehrend die Bildunterschrift darunter
       sie beschrieb. Diese Flaechen bekommen stattdessen ein MINDESTMASS und
       rollen in ihrem eigenen Kasten — sie duerfen nicht unter die Groesse
       schrumpfen, bei der ihre Komposition aufgeht.

   Die Schwelle fuer (a) ist gemessen, nicht gegriffen: Sweep ueber 320 bis
   2560 px Fensterbreite, groesste Kartenbreite, bei der noch eine Marke unter
   der Tafel lag — 465,17 px auf startseite#karte-hero. Aufgerundet 466 px.
   Runde 6 hatte 460 px gesetzt und die Zahl aus der GROESSE DER TAFEL
   hergeleitet statt aus der LAGE DER MARKEN; dadurch blieb ein Fenster von
   1037 bis 1045 px, in dem die Tafel wieder schwebte und bis zu 24,7 % der
   Marke --map-pin-selected verdeckte — ausgerechnet der, die sie benennt.
   In der Bedingung einer Container-Anfrage sind keine Custom Properties
   erlaubt; die Zahl steht deshalb hier und nirgends sonst.
   zustand-pruefung.js faehrt 320 bis 2560 px auf JEDER Flaeche ab und
   entscheidet, dass keine Marke unter der Tafel liegt — bis Runde 6 lief diese
   Entscheidung nur auf Blaettern mit <main>, also auf zweien von sieben, und
   karte.html hat sie deshalb nie gesehen. */
.mapcard, .kartenblock { container-type: inline-size; }
@container (max-width: 466px) {
  .t-tafel--eng466 {
    position: static; width: auto; margin-top: var(--tv-space-2);
    box-shadow: none; border: var(--border-hairline) solid var(--line);
  }
}


/* ZWEITE FORM: das Bodenblatt auf einem Telefonbildschirm. Es spannt ueber die
   volle Breite und sitzt unten — dieselbe Idee, andere Flaeche.
   Es setzt JEDE Eigenschaft zurueck, die es aendert (top UND width): in Runde 8
   erbte die lokale Fassung auf app-aufnahmen.html top und width aus der
   geteilten Regel und wuchs auf 300 x 509 px — die Tafel deckte den ganzen
   Kartenbildschirm zu, Karte, Zug und alle vier Pins waren unsichtbar,
   waehrend die Bildunterschrift darunter sie beschrieb.
   Wer eine Variante schreibt, setzt zurueck, was er aendert. */
.t-tafel--telefon {
  /* position gehoert dazu: die Variante traegt sie jetzt selbst, damit keine
     spaetere Regel sie ihr wegnehmen kann. Genau das ist in Runde 6 passiert. */
  position: absolute;
  top: auto; bottom: 12px; left: 12px; right: 12px; width: auto;
  padding: 14px 16px 16px;
}

/* -----------------------------------------------------------------------------
   KNOPF — eine Deklaration, zwei benannte Hoehen.
   Bis Runde 6 stand der Knopf fuenfmal lokal in den Blaettern, in zwei Hoehen
   (52 und 44 px) und zwei Innenmassen (30 und 28 px). Dieselbe Beschriftung
   "Kostenlos starten" war auf zwei Blaettern 4 px verschieden breit, und die
   44er Hoehe existierte nur als Inline-Attribut — in keinem Token, in keinem
   Dokument. base.css enthielt gar keinen Knopf.

   Die zwei Hoehen sind ein RANG, kein Zufall:
   - .t-knopf            52px — die eine primaere Handlung einer Ansicht
   - .t-knopf--klein     44px — jede weitere Handlung (Navigation, Bauteil)
   Wer eine primaere Handlung auf 44 setzt, hebt den Rang auf; genau das war auf
   der Startseite passiert (Portal-Handlung 44 = Navigation 44).
   ----------------------------------------------------------------------------- */
/* WARNUNG AUS RUNDE 7: hier stand kurz auch ".b" in der Aliasliste. Auf
   startseite.html ist .b die BANDSEKTION — jedes Band wurde damit zum Knopf
   (gemessen 176 px hoch). Ein generischer Name gehoert nie in eine geteilte
   Regel; app-aufnahmen.html heisst seither .knopf statt .b. */
/* DER KNOPF IST EIN BEDIENELEMENT, KEIN ANGEMALTES <span>.
   Bis Runde 18 waren alle vier Handlungsflaechen der Startseite blanke
   <span>/<div> ohne href, role oder tabindex — auf dem einen Blatt, das laut
   bar.md KEIN Belegblatt ist, und dessen Register dieselben Flaechen als
   "Handlungen" zaehlt. Das Register benannte die drei toten href="#", nicht die
   vier nicht existierenden Bedienelemente.
   Sie sind jetzt <button type="button">; font/cursor/text-align setzen zurueck,
   was der Browser einem Knopf sonst mitgibt. */
.t-knopf {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--knopf-hoehe); padding-inline: var(--knopf-polster);
  border-radius: var(--radius-control); border: 0;
  font-family: inherit; font-size: var(--text-body-size);
  font-weight: var(--weight-semibold); font-variation-settings: inherit;
  line-height: 1; letter-spacing: normal; white-space: nowrap;
  text-align: center; cursor: pointer; -webkit-appearance: none; appearance: none;
  background: var(--action); color: var(--text-on-action);
}
.t-knopf--klein {
  height: var(--knopf-hoehe-klein); padding-inline: var(--knopf-polster-klein); }
/* DER ZEIGERZUSTAND GEHOERT ZUM BAUTEIL, nicht auf ein Blatt.
   ANWENDUNG.md Abschnitt 4 deklariert ihn seit Stueck 2 („ohne Hover, Fokus,
   Gedrueckt und Deaktiviert kann niemand ein Bedienelement bauen"); gebaut war
   bis Stueck 4 nur der Fokus. Ein Zustand, der beschrieben und nicht gebaut ist,
   ist keiner — und er gehoert hierher, weil ihn sonst jedes Blatt neu erfindet. */
.t-knopf:hover { background: var(--action-hover); }
/* Der konturierte Knopf steigt jetzt in derselben Richtung wie jede andere
   Flaeche des Systems: Ruhe hell, Hover eine Sprosse tiefer, Gedrueckt zwei.
   Vorher war Hover --bg-sunken (L* 79,7) und Gedrueckt --bg-band (84,4) —
   die Flaeche wurde beim Druecken HELLER als beim Ueberfahren, gegen jede
   Erwartung und gegen den gefuellten Knopf daneben, der dunkler wird. */
.t-knopf--kontur:hover { background: var(--bg-band); }
/* Der AUSGEWAEHLTE Knopf steht schon in der Mulde (--bg-sunken). Mit derselben
   Hover-Regel wie der konturierte wurde er beim Ueberfahren HELLER
   (79,7 -> 84,4 L*) und beim Druecken wieder genau wie in Ruhe — die Leiter
   lief rueckwaerts und schloss sich zum Kreis. Er geht deshalb nach unten
   weiter: Ruhe 79,7 -> Hover 54,0 waere zu viel, also traegt der Hover die
   Kontur staerker und der Druck den Schatten. */
.t-knopf--gewaehlt:hover { background: var(--bg-sunken); border-color: var(--text); }
.t-knopf--gewaehlt:active {
  background: var(--bg-sunken); border-color: var(--text);
  box-shadow: var(--press-inset); transform: translateY(1px);
}
/* GEDRUECKT — deklariert seit Stueck 2, gebaut seit Stueck 4, Runde 9.
   ANWENDUNG.md Abschnitt 4 fuehrt vier Zustaende ("ohne Hover, Fokus, Gedrueckt
   und Deaktiviert kann niemand ein Bedienelement bauen") und nennt fuer
   Gedrueckt --action-press und 1 px nach unten. Gebaut waren drei: :active kam
   in keinem Blatt und keinem Stylesheet vor, und der Craft-Kritiker hat mit
   gedrueckter Maustaste gemessen, dass fuenf von fuenf Bedienelementen sich
   nicht ruehren. Eine Zusage ueber einen Zustand, den es nicht gibt.
   Der Versatz ist ein translate, keine Randaenderung: er verschiebt nichts im
   Fluss und laesst die Bedienhoehe unberuehrt.
   Der Farbschritt vom Hover zum Gedrueckt ist klein — --action-hover zu
   --action-press sind 1,14 : 1, vier Punkte L*. Als Traeger allein reicht das
   nicht, und der Versatz faellt unter prefers-reduced-motion weg: dort waren
   Hover und Gedrueckt nicht mehr zu unterscheiden. Deshalb traegt Gedrueckt
   zusaetzlich --press-inset, den bewegungsfreien Schatten. Er bleibt in JEDER
   Bewegungseinstellung stehen; nur der Versatz wird zurueckgenommen. */
.t-knopf:active {
  background: var(--action-press); box-shadow: var(--press-inset); transform: translateY(1px);
}
.t-knopf--kontur:active, .t-knopf--gewaehlt:active {
  background: var(--bg-sunken); box-shadow: var(--press-inset); transform: translateY(1px);
}
@media (prefers-reduced-motion: reduce) {
  .t-knopf:active, .t-knopf--kontur:active, .t-knopf--gewaehlt:active { transform: none; }
}
/* --text-on-action und --bg-float loesen BEIDE zu --tv-linen-0 (#FFFDFB) auf:
   Ruhe und Hover waren bitgleich, und zwar am Schlussknopf der Startseite.
   Zwei Tokennamen fuer denselben Wert sehen im Quelltext aus wie zwei Stufen. */
.t-knopf--hell:hover { background: var(--bg-sunken); }
.t-knopf--hell:active {
  background: var(--bg-band); box-shadow: var(--press-inset); transform: translateY(1px);
}
.t-knopf--gesperrt:hover, .t-knopf:disabled:hover { background: var(--bg-sunken); }
/* AUSSER IN DER DICHTEN STUFE. [data-density="compact"] (tokens.css) setzt beide
   Raenge auf 44 px und laesst den Rang von der FUELLUNG tragen: genau eine
   gefuellte Handlung je Ansicht. Der Satz oben galt pauschal und widersprach
   damit dem einen gebauten Bildschirm des Systems, der in dieser Stufe laeuft.
   Gemessen wird der Rang deshalb nicht an der Hoehe, sondern an der Zahl der
   gefuellten Handlungen — von werkzeug/viewport-pruefung.js, je Ansicht. */
/* Die Kontur ist 2px (--border-outline), nicht 1px: sie ist dieselbe starke
   Kontur, die das ausgewaehlte Bedienelement traegt. Hier stand --border-hairline,
   waehrend die Blaetter 2px zeichneten — die kanonische Fassung war schon beim
   Aufschreiben falsch. Sonst stehen zwei konturierte Knoepfe nebeneinander in
   zwei Strichstaerken, und auf app-aufnahmen.html war ausgerechnet der
   zerstoerende der leisere. */
.t-knopf--kontur {
  background: transparent; color: var(--text);
  border: var(--border-outline) solid var(--line-strong); }
/* Das AUSGEWAEHLTE Bedienelement: gefuellte Mulde plus dieselbe starke Kontur.
   Stand bis Runde 10 als .chip lokal auf foundation.html. */
/* -----------------------------------------------------------------------------
   DAS EINGABEFELD (ANWENDUNG.md §4, "Suchfeld").

   Der Styleguide beschreibt es genau — 44 px hoch, Pillenradius, Flaeche
   --bg-sunken (die versenkte Feldfuellung), Rand --line, Platzhalter in
   --text-muted, im Fokus Rand in der Aktionsfarbe plus Ring — und base.css
   fuehrte es NICHT. Die Anwendung hatte deshalb ihre eigene Fassung, mit
   eigener Hoehe und drei verschiedenen Eckformen (4, 6 und 8 px), und die
   Belegblaetter zeigten gar keine.

   Ein Bauteil, das ein Register beschreibt und keine Datei baut, ist genau
   der Fehler, den MARKE.md fuer Signet und Wortmarke protokolliert — nur
   andersherum.
   ----------------------------------------------------------------------------- */
.t-feld {
  display: block;
  width: 100%;
  height: var(--knopf-hoehe);
  padding-inline: var(--knopf-polster);
  background: var(--bg-sunken);
  color: var(--text);
  border: var(--border-hairline) solid var(--line);
  border-radius: var(--radius-control);
  font-family: var(--font-text);
  font-size: var(--text-detail-size);
}
.t-feld::placeholder { color: var(--text-muted); opacity: 1; }
.t-feld:hover { border-color: var(--line-strong); }
.t-feld:focus-visible {
  border-color: var(--action);
  outline: var(--border-outline) solid var(--focus-ring);
  outline-offset: 3px;
}
.t-feld:disabled {
  color: var(--text-disabled);
  background: var(--bg-sunken);
  cursor: not-allowed;
}

/* EIN MEHRZEILIGES FELD KANN KEINE PILLE SEIN.
   Der Pillenradius ist auf die Bedienhoehe gerechnet; auf einem Kasten von
   120 px Hoehe rundet er die Schmalseiten zu Halbkreisen und schneidet die
   erste und letzte Zeile an. Ein Feld, in das man schreibt, ist an dieser
   Stelle eine FLAECHE — und traegt deren Radius. Das ist keine dritte
   Eckform, sondern die zweite, hier angewandt. */
.t-feld--mehrzeilig {
  height: auto;
  min-height: calc(var(--knopf-hoehe) * 2);
  padding-block: var(--tv-space-1);
  border-radius: var(--radius-surface);
  resize: vertical;
  line-height: var(--text-detail-lh);
}

/* DIE ZERSTOERENDE HANDLUNG (ANWENDUNG.md §4).
   Sie traegt NIE die Aktionsfarbe, damit sie nicht wie "weiter" aussieht:
   konturiert in Terrakotta. Die zurueckweisende Antwort daneben ist ein
   gewoehnlicher konturierter Knopf.

   Sie stand bis zum Umbau der Anwendung in KEINER Datei: ANWENDUNG.md
   beschrieb sie, app-aufnahmen.html zeigte sie, und base.css — die Datei, die
   die Knoepfe fuehrt — kannte sie nicht. Die Anwendung hatte deshalb ihre
   eigene (.btn-danger, gefuellt in der alten Fehlerfarbe), also genau das,
   was der Absatz oben verbietet: eine zerstoerende Handlung, die aussieht wie
   eine primaere. */
.t-knopf--gefahr {
  background: transparent;
  color: var(--danger);
  /* border-COLOR allein zeichnet nichts: .t-knopf setzt border: 0, und ohne
     Stil und Breite bleibt die Kontur aus. Am Belegblatt der Anwendung stand
     der Loeschknopf deshalb als nackte Schrift — nicht zu unterscheiden von
     einem Textlink. Dieselbe Verwechslung wie border: var(--border-hairline). */
  border: var(--border-outline) solid var(--danger);
}
.t-knopf--gefahr:hover  { background: var(--bg-sunken); color: var(--danger); }
.t-knopf--gefahr:active { background: var(--bg-sunken); box-shadow: var(--press-inset); }

.t-knopf--gewaehlt {
  background: var(--bg-sunken); color: var(--text);
  border: var(--border-outline) solid var(--line-strong); }
/* Das GESPERRTE Bedienelement. Lokal (.pill-disabled) setzte es kein Gewicht
   und fiel damit auf 400 — neben einem ausgewaehlten Knopf in 600 und einem
   Suchfeld in 400 war es nur noch an der Textfarbe zu unterscheiden. Als
   Auspraegung des Knopfes traegt es dessen 600. */
/* DEAKTIVIERT VERLIERT DIE FARBE GANZ (ANWENDUNG.md §4) — und zwar auch dann,
   wenn das Element es ueber das ATTRIBUT sagt statt ueber die Klasse.
   base.css kannte bis hierher nur .t-knopf--gesperrt und die :hover-Zeile
   darunter; ein <button class="t-knopf" disabled> behielt deshalb im
   Ruhezustand die volle Aktionsfarbe und sah aus wie die eine Handlung der
   Ansicht. Gefunden am Belegblatt der Anwendung. */
.t-knopf--gesperrt,
.t-knopf:disabled {
  background: var(--bg-sunken); color: var(--text-disabled);
  border: var(--border-hairline) solid var(--line); cursor: not-allowed; }
/* Der Knopf auf einer gefuellten Akzentflaeche: die Flaeche traegt die Farbe,
   der Knopf traegt die Schrift. Stand lokal als .slab__pill. */
.t-knopf--hell {
  background: var(--text-on-action); color: var(--action-text); }

/* -----------------------------------------------------------------------------
   BAUTEILTITEL — eine Regel fuer alle Blaetter.
   Kartentitel, Dialogtitel, Zeilentitel, Aufnahmenbeschriftung: dieselbe Rolle
   wie eine h3, nur in einem Element, das die h3-Regel nicht erreicht. Sie liefen
   deshalb auf jedem Blatt in Archivo neben gleichrangigen Bricolage-h3, und auf
   der Absatzstufe 25 px statt auf ihrer eigenen (30 px). Das ist der Fall, in
   dem EIN GRAD ZWEI RAENGE TRUG.
   DER KANONISCHE NAME IST .t-titel — seit Runde 9 der einzige: die Blaetter
   sind umgestellt, die Aliasselektoren aus diesem File entfernt. Eine
   Namensliste verfehlt naemlich immer den naechsten Namen: in Runde 5c
   wurden sechs Namen
   zusammengezogen, und .state b sowie .confirm b liefen weiter auf 25 px in
   Archivo, weil sie nackte <b> in lokalen Regeln waren. Wer ein neues Bauteil
   baut, schreibt class="t-titel" — dann ist ein vergessener Titel sofort als
   16px-Fliesstext sichtbar statt still auf der falschen Stufe zu laufen.
   font-variation-settings ERSETZT die geerbte Liste — opsz muss mit. */
.t-titel {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-variation-settings: "opsz" var(--opsz-h3), "wdth" var(--wdth-heading);
  font-size: var(--text-h3-size);
  line-height: var(--text-h3-lh);
  letter-spacing: normal;
}

.t-display {
  font-size: var(--text-display-size);
  line-height: var(--text-display-lh);
  font-weight: var(--weight-black);
  font-variation-settings: "opsz" var(--opsz-display), "wdth" var(--wdth-display);
}
.t-h1 {
  font-size: var(--text-h1-size); line-height: var(--text-h1-lh);
  font-weight: var(--weight-bold);
  font-variation-settings: "opsz" var(--opsz-h1), "wdth" var(--wdth-display);
}
.t-h2 {
  font-size: var(--text-h2-size); line-height: var(--text-h2-lh);
  font-weight: var(--weight-semibold);
  font-variation-settings: "opsz" var(--opsz-h2), "wdth" var(--wdth-heading);
}
.t-h3 {
  font-size: var(--text-h3-size); line-height: var(--text-h3-lh);
  font-weight: var(--weight-semibold);
  font-variation-settings: "opsz" var(--opsz-h3), "wdth" var(--wdth-heading);
}

.t-lead {
  font-family: var(--font-text);
  font-size: var(--text-lead-size);
  line-height: var(--text-lead-lh);
  font-weight: var(--weight-regular);
  letter-spacing: normal;
  text-wrap: pretty;
}
.t-body {
  font-size: var(--text-body-size);
  line-height: var(--text-body-lh);
  letter-spacing: normal;
}
/* Die Stufe zwischen Fliesstext und Metazeile: Tabellenzelle, Hilfszeile
   unter dem Feld, zweite Zeile eines Listeneintrags. */
.t-detail {
  font-size: var(--text-detail-size);
  line-height: var(--text-detail-lh);
  letter-spacing: normal;
}
.t-caption {
  font-size: var(--text-caption-size);
  line-height: var(--text-caption-lh);
  letter-spacing: normal;
  color: var(--text-muted);
}

/* Die EINZIGE gesperrte Stelle im System: kleines Versalien-Label.
   Leicht geweitet ueber die wdth-Achse — die Sprache der Wegweiser.

   DIE ROLLE STEHT HIER, NICHT AUF DEN BLAETTERN. In Runde 11 waren es elf
   lokale Neudeklarationen derselben Rolle mit dem ROHEN Wert .09em statt
   var(--text-over-ls) — und dabei nicht derselbe Schnitt: die kanonische Klasse
   laeuft "wdth" 110 / 600, die lokalen Fassungen liefen "wdth" 100 und teils
   400. Dasselbe Etikett trug auf fuenf von sechs Blaettern einen anderen
   Schnitt als dort, wo es deklariert ist; auf fotografie.html kam die
   kanonische Klasse gar nicht vor. Das ist derselbe Fehler, den karte.html
   weiter unten schon einmal als gefunden protokolliert.

   th steht in der Selektorliste, weil eine Tabellenkopfzeile diese Rolle IST —
   auf jedem Blatt, und ohne dass jemand eine Klasse vergeben muss. */
.t-over, th {
  font-family: var(--font-text);
  font-size: var(--text-over-size);
  line-height: 1.3;
  letter-spacing: var(--text-over-ls);
  text-transform: uppercase;
  font-weight: var(--weight-semibold);
  font-variation-settings: "wdth" 110;
  color: var(--text-muted);
}

/* Daten und deklarierte Werte — Koordinaten, Distanzen, Zeiten, Hexwerte,
   Tokennamen, CSS-Werte, Messzahlen. Immer tabellarisch.
   Laeuft auf der Detailstufe; --fein laeuft auf der Captionstufe.
   Beide Groessen sind bereits in der Skala, es kommt keine hinzu. */
.t-data {
  font-family: var(--font-mono);
  font-size: var(--text-data-size);
  line-height: var(--text-data-lh);
  font-weight: var(--weight-regular);
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
}
.t-data--fein { font-size: var(--text-caption-size); line-height: var(--text-caption-lh); }

.t-muted { color: var(--text-muted); }
.t-prose { max-width: var(--prose-max); text-wrap: pretty; }

/* Display-Emphase: genau EINE Phrase pro Ueberschrift traegt die Bluete. */
.em-signal { color: var(--action-text); }

/* -----------------------------------------------------------------------------
   Layout-Primitiven
   ----------------------------------------------------------------------------- */
.page {
  width: 100%;
  margin-inline: auto;
  max-width: var(--page-max);
  padding-inline: var(--page-rand);
}

.section { padding-block: var(--section-gap); }

/* Baender — die Sektionstrennung dieses Systems. Keine Linien, keine Divider,
   nur der Farbwechsel auf der Leinenleiter. Benachbarte Stufen liegen 4,6 bis
   5,9 L*-Punkte auseinander (gemessen 5,85 / 4,57 / 4,62 / 4,68; mindestens
   1,128 : 1); das genuegt, um ein Band ohne Trennlinie vom Grund zu
   unterscheiden. Der groesste Abstand ist der oberste.
   Hier stand bis Runde 5 "4,6 bis 5,3" — eine Spanne, die kein Paar erreicht
   und die das oberste Paar ausschliesst. */
.band         { background: var(--bg-band); }
.band--paper  { background: var(--bg); }
.band--raised { background: var(--bg-raised); }
.band--float  { background: var(--bg-float); }
.band--kastanie {
  background: var(--bg-inverse);
  color: var(--text-inverse);
  --line: var(--line-inverse);
  --text-muted: var(--text-inverse-muted);
}

.stack { display: flex; flex-direction: column; gap: var(--element-gap); }
.row   { display: flex; align-items: center; gap: var(--element-gap); }
.row--wrap { flex-wrap: wrap; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: var(--element-gap); }

.grid-3 { display: grid; gap: var(--tv-space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid-2 { display: grid; gap: var(--tv-space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Die Marken auf der Karte ----------------------------------------
   Eine Marke ist ein L.divIcon, kein Bild: sie traegt damit dieselben Token wie
   der Rest des Systems und skaliert mit der Dichtestufe. Sie stand bis zur
   Kurskorrektur inline in anwendung.html — als die Startseite, das Belegblatt
   und die Aufnahmen dieselben Marken bekamen, waere das die vierte Fundstelle
   derselben Regel gewesen.

   Die Leiter steht in KARTE.md: Kern 14 fuer eine Pause, 18 fuer einen Halt,
   22 fuer einen zu pruefenden, 26 fuer den gewaehlten. Das Hoefchen ist der
   Rand — er haelt die Marke von der Kachel darunter frei, damit sie auf jedem
   Untergrund traegt.
   -------------------------------------------------------------------------- */
/* DER RING LIEGT AUSSEN, DAMIT DIE ZAHL DER KERN IST.
   Er stand als border auf einem border-box-Element: die gesetzte Breite war
   damit das AUSSENMASS, und derselbe Wert bedeutete in karte.js etwas anderes
   als in KARTE.md. Als box-shadow waechst der Ring nach aussen, ohne den Kern
   anzutasten.

   UND ER MUSS TRAGEN. Ein Ring in --bg-float allein hob sich von den
   behandelten Kacheln kaum ab: gemessen 1,7 bis 2,0, ueber hellem Land 1,1
   (Kacheltoene, keine deklarierten Systemfarben) — auf 99,1 Prozent der
   Kartenflaeche unter der Schranke von >= 3 : 1, die SC 1.4.11 fuer ein
   Zustandsmerkmal verlangt. Der Kommentar daneben sagte, er halte die
   Marke "auf jedem Untergrund" frei; gemessen hielt er sie nirgends frei.
   Der zweite Ring aussen traegt das: --line ist die Haarlinie des Systems und
   ausdruecklich als ">= 3:1 auf ALLEN fuenf hellen Flaechen" deklariert
   (tokens.css). Nachgerechnet gegen die sechs Toene der behandelten Kacheln:
   3,93 bis 5,95 : 1, und 6,19 : 1 gegen das helle Hoefchen davor.
   KEIN ALPHA. Eine erste Fassung nahm --tv-kastanie bei 35 Prozent und kam auf
   2,06 : 1 — zu wenig, und tokens.css sagt daneben: "Alpha kommt
   ausschliesslich in Schatten vor". Ein deklariertes Token, das genau fuer
   diesen Zweck gemacht ist, war die ganze Zeit da. */
.marke {
  box-sizing: border-box; border-radius: var(--radius-circle);
  background: var(--map-pin); border: 0;
  box-shadow: 0 0 0 2px var(--bg-float),
              0 0 0 3px var(--line),
              var(--shadow-float);
}
.marke--pruefen { background: var(--map-pin-pruefen); }
/* Die Luecke ist HOHL: an ihr fehlt etwas, und das sagt die Marke, indem sie
   nichts fuellt. Die Kontur liegt INNEN, der Ring bleibt aussen. */
.marke--luecke {
  background: var(--bg-float);
  border: 3px solid var(--danger);
}
.marke--gewaehlt { background: var(--map-pin-selected); }
