/* Wiederverwendbare UI-Bausteine (Buttons, Formulare, Fehler-Banner). Farben/
   Radien/Font ausschliesslich aus tokens.css, hier nicht duplizieren. */

[x-cloak] {
  display: none !important;
}

.fb-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--fb-space-2);
  padding: 10px var(--fb-space-4);
  border-radius: var(--fb-radius);
  border: 1px solid transparent;
  font-family: var(--fb-font);
  font-size: var(--fb-text-l);
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, opacity 120ms ease;
}

/* Rueckmeldung auf Druck und Warten. Beides fehlte komplett: Der Knopf sprang
   beim Zeigen ohne Uebergang um, und `hx-disabled-elt` in der Erfassung sperrte
   ihn zwar - sichtbar war davon nichts, weil es keine :disabled-Regel gab. Die
   Sperre war also genau so lange unsichtbar, wie das Speichern dauert. */
.fb-btn:active:not(:disabled):not(.htmx-request) {
  transform: translateY(1px);
}

.fb-btn:disabled,
.fb-btn.htmx-request {
  opacity: 0.55;
  cursor: progress;
}

.fb-btn--primary {
  background: var(--fb-accent);
  color: #fff;
}

.fb-btn--primary:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-accent-dark);
}

.fb-btn--secondary {
  background: #fff;
  color: var(--fb-gray-800);
  border-color: var(--fb-gray-200);
}

.fb-btn--secondary:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-gray-50);
}

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

.fb-btn--danger:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-danger-tint);
}

/* Loeschen **in einer Listenzeile**: Ein Zeilen-Loeschen in der Schnellerfassung
   hat nicht das Gewicht, mit dem "Fahrschueler loeschen" unten in der Akte
   steht - dort ist Rot richtig, hier standen vier laute Rahmen untereinander
   und waren das Auffaelligste auf dem Bildschirm. Die Farbe kommt erst beim
   Zeigen, die Sicherheit steckt ohnehin im Bestaetigungsdialog dahinter. */
/* 4px statt 6: Der Knopf ist in der Erfassung das hoechste Element der Zeile
   und bestimmte damit allein ihre Hoehe. */
.fb-btn--zeile,
.fb-btn--zeile-stumm {
  padding: var(--fb-space-1);
  background: transparent;
  color: var(--fb-gray-600);
  border-color: transparent;
}

/* Wie fb-btn--zeile, aber ohne den roten Anflug beim Zeigen: fuer
   Zeilen-Aktionen, die **nichts** zerstoeren (Preisliste: "Neue Version",
   "Duplizieren"). Rot bleibt echten Fehlern und destruktiven Aktionen
   vorbehalten - auch im Hover. */
.fb-btn--zeile-stumm:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-gray-100);
  color: var(--fb-gray-800);
}

.fb-btn--zeile:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-danger-tint);
  color: var(--fb-danger);
}

/* Bestaetigungs-Dialog vor destruktiven Aktionen (aktuell: Loeschen, siehe
   partials/loeschen_dialog.html) - eigenes Overlay statt des nativen
   window.confirm(), damit die Bestaetigung wie ein Teil der App aussieht statt
   eines Browser-Popups. */

.fb-dialog-overlay {
  position: fixed;
  inset: 0;
  background: var(--fb-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--fb-space-5);
  z-index: var(--fb-ebene-dialog);
}

.fb-dialog {
  width: 100%;
  max-width: 420px;
  background: #fff;
  border-radius: var(--fb-radius-lg);
  box-shadow: var(--fb-shadow-lg);
  padding: var(--fb-space-5);
  /* Der Dialog wird dort im DOM erzeugt, wo der Knopf steht - in Tabellen also
     in einer Zelle mit `white-space: nowrap`. Das wird vererbt, und die Frage
     lief als eine lange Zeile aus dem Kasten heraus. Bei kurzen Fragen fiel es
     nie auf. Hier zurueckgesetzt statt die Texte kurz zu halten: Ein Baustein
     darf nicht davon abhaengen, wo er eingesetzt wird. */
  white-space: normal;
  text-align: left;
}

.fb-dialog__frage {
  margin: 0 0 20px;
  color: var(--fb-gray-800);
  font-size: var(--fb-text-l);
  line-height: 1.5;
}

.fb-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--fb-space-3);
}

/* Fehler-Banner */

.fb-banner {
  border-radius: var(--fb-radius);
  border: 1px solid var(--fb-danger);
  background: var(--fb-danger-tint);
  color: var(--fb-danger);
  padding: var(--fb-space-3) var(--fb-space-4);
  margin-bottom: var(--fb-space-5);
}

.fb-banner__title {
  font-weight: 600;
  margin: 0 0 var(--fb-space-1);
}

/* <strong> ohne eigenen Schnitt haette der Browser synthetisch gefettet. */
strong {
  font-weight: 600;
}

.fb-banner__liste {
  margin: 0;
  padding-left: 20px;
}

/* Formulare */

/* Breite kommt von aussen (.fb-formularseite bzw. der Profil-Spalte, siehe
   layout.css) - nicht mehr aus dem Baustein selbst, sonst kann dasselbe Panel
   nicht einmal ein schmales Formular und einmal eine breite Tabelle tragen. */
.fb-form {
  background: var(--fb-flaeche);
  border: 1px solid var(--fb-flaeche-rand);
  border-radius: var(--fb-radius-lg);
  box-shadow: var(--fb-flaeche-schatten);
  padding: var(--fb-space-5);
}

/* **Der Abschnitt ist eine Beschriftung ueber Daten** (Sauberkeitscheck,
   03.09.2026) - dieselbe Form wie der Gruppentitel im Steckbrief der Akte:
   12px versal, Linie darunter, 24px Abstand nach oben. Die Maske ist der
   Steckbrief mit Feldern, also sieht die Gruppierung gleich aus.

   Vorher war er Kopf-Rolle (17/600) mit Linie darueber, 28px Abstand oben und
   20px Polster: rund 90px je Abschnitt, in der Fahrschueler-Maske sechs davon
   - 540px, so viel wie alle Felder zusammen (47 % Feldanteil, gemessen).
   Der Rang war richtig begruendet (27.08.: "echte Ueberschrift"), die Hoehe
   nicht. Ein Abstandstoken fuer alle Masken, damit die naechste nicht wieder
   ihren eigenen bekommt. */
.fb-form__abschnitt {
  margin: var(--fb-abschnitt-abstand) 0 var(--fb-space-3);
  padding-bottom: var(--fb-space-2);
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  /* **Teal markiert** (Sven am Bild, 03.09.2026, Fassung B von dreien): ein
     3px-Balken in der Marke vor der Beschriftung, die Linie darunter in der
     Marken-Tint, der Text im Marken-Text (6,2:1 auf Weiss). Das ist die
     Aufgabe, fuer die das Teal in der Farbrichtung reserviert ist - und es
     macht die Gruppen kenntlich, ohne eine Flaeche einzufuehren: Eine
     Toenung je Gruppe (probiert) machte aus dem Markierungston eine
     Grundfarbe und aus der Maske einen Stapel tuerkiser Kaesten. */
  padding-left: var(--fb-space-3);
  border-left: 3px solid var(--fb-marke);
  border-bottom: 1px solid var(--fb-marke-tint);
  color: var(--fb-marke-text);
}

/* Der erste Abschnitt eines Formulars haengt nicht in der Luft: kein Abstand
   nach oben (bei Gruppen: der der ersten Gruppe). Die Legende steht nicht mehr davor (sie ist
   in die Aktionsleiste gewandert), also ist das erste Kind nach den Bannern
   wirklich der Abschnitt - `:first-child` scheitert weiter am CSRF-Feld,
   deshalb ueber die erste Gruppe und ueber den Banner-Nachbarn. */
.fb-form > input[type="hidden"] + .fb-form__gruppe > .fb-form__abschnitt,
.fb-form > .fb-banner + .fb-form__gruppe > .fb-form__abschnitt,
.fb-form > input[type="hidden"] + .fb-form__abschnitt,
.fb-form > .fb-banner + .fb-form__abschnitt {
  margin-top: 0;
}

/* **Gruppen untereinander, Felder nebeneinander** (Sven am Bild,
   03.09.2026): "die Kategorien eher von oben nach unten, aber so, dass der
   Platz effizient genutzt wird und nicht schmal und lang". Die Spalten-Fassung
   vom selben Tag stellte die drei Gruppen nebeneinander - das las sich als
   drei Listen, nicht als eine Maske, und die Gruppe mit den meisten Feldern
   bestimmte die Hoehe. Jetzt ist jede Gruppe ein eigenes Raster: Beschriftung
   ueber alle Spalten, darunter die Felder in Kacheln von mindestens 14rem,
   so viele nebeneinander, wie die Breite traegt (vier bei 1440px). Banner,
   Erziehungsberechtigte und Aktionsleiste stehen ausserhalb der Gruppen. */
.fb-form__gruppe {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0 var(--fb-space-5);
  align-items: start;
}

.fb-form__gruppe > .fb-form__abschnitt {
  grid-column: 1 / -1;
}

/* Eine Reihe (PLZ + Ort, Steuernummer + USt-IdNr.), eine Auswahlgruppe
   (Geschlecht) und ein **Block** - ein Feld samt Erklaerung oder Merkliste,
   das in einer 14rem-Zelle vier Zeilen brauchte - sind doppelt so breit wie
   ein Feld; auf schmalen Fenstern faellt das auf eine Spalte zurueck. Ein
   nackter <div> als Wrapper waere dagegen eine einzelne Zelle mit allem
   darin gestapelt - so sah die Fahrschule-Maske im ersten Wurf aus. */
.fb-form__gruppe > .fb-form__row,
.fb-form__gruppe > .fb-form__fieldset,
.fb-form__gruppe > .fb-form__block {
  grid-column: span 2;
}

@media (max-width: 40rem) {
  .fb-form__gruppe > .fb-form__row,
  .fb-form__gruppe > .fb-form__fieldset,
  .fb-form__gruppe > .fb-form__block {
    grid-column: 1 / -1;
  }
}

/* Ein Block ueber die ganze Breite: die Klassen-Kaestchen (Fahrlehrer,
   Fahrzeug), die als Gruppe von Gruppen keine Zelle fuellen, sondern eine
   Reihe. */
.fb-form__gruppe > .fb-form__block--voll,
.fb-form__gruppe > .fb-form__hinweis,
.fb-form__gruppe > .fb-merkliste,
.fb-form__gruppe > .fb-hinweis-banner,
.fb-form__gruppe > .fb-banner {
  grid-column: 1 / -1;
}

/* Ein Hinweis oder eine Merkliste, die frei in der Gruppe stehen (nicht in
   einem Feld), sind eine Fussnote unter der Reihe - nicht eine Zelle neben
   den Feldern, in der sie vierzeilig umbrechen (Zahlung: "Fuer Barzahlungen
   braucht der Fahrschueler eine Quittung" stand rechts neben der
   Zahlungsart). */
.fb-form__gruppe > .fb-form__hinweis {
  margin: calc(-1 * var(--fb-space-1)) 0 var(--fb-space-3);
}

/* Ein Feld direkt nach einer Gruppe (Erziehungsberechtigte: "Zweite Person
   erfassen"): Abstand wie zwischen Feldern - die Raender im Raster reichen
   nicht ueber die Gruppe hinaus (gemessen 0px, 03.09.2026). */
.fb-form__gruppe + .fb-form__group {
  margin-top: var(--fb-space-3);
}

/* Im Block gilt derselbe Abstand nach unten wie fuer ein Feld. */
.fb-form__gruppe > .fb-form__block {
  margin-bottom: var(--fb-space-3);
}

.fb-form__block > .fb-form__group:last-child,
.fb-form__block > .fb-form__row:last-child,
.fb-form__block > .fb-merkliste:last-child,
.fb-form__block > .fb-form__hinweis:last-child {
  margin-bottom: 0;
}

/* Innerhalb einer Gruppe stehen die Felder dichter (12 statt 16px): Der
   Zwischenraum trennt Felder derselben Gruppe, den Gruppenabstand traegt die
   Beschriftung. */
.fb-form__gruppe > .fb-form__group,
.fb-form__gruppe > .fb-form__row {
  margin-bottom: var(--fb-space-3);
}

/* Die Seite dazu: volle Inhaltsbreite, nicht 900px - drei Spalten brauchen
   sie. Die haftende Aktionsleiste haengt an `.fb-formularseite`, deshalb ein
   Modifikator und kein fehlender Wrapper. */

/* Hier stand eine Regel `.fb-form__abschnitt:first-of-type`, die die Linie
   ueber dem **ersten** Abschnitt entfernen sollte. Sie hat nie gegriffen:
   `:first-of-type` meint das erste Element seiner Tag-Art, und vor dem ersten
   <p class="fb-form__abschnitt"> steht immer die <p class="fb-form__legende">.

   Ein zweiter Anlauf mit `.fb-form > .fb-form__abschnitt:first-child` war
   ebenso tot - das erste Kind eines Formulars ist stets das versteckte
   CSRF-Feld (Pflicht, siehe CLAUDE.md). Ein Abschnitt kann dort nie stehen.

   Ersatzlos entfernt: Die Linie unter der Legende ist richtig so, und eine
   Regel, die nur aussieht, als wuerde sie etwas absichern, ist schlechter als
   keine. Wer je ein Formular ohne Legende baut, entscheidet dann neu. */

/* **Zweispaltiges Formularraster** (B12/P2). `.fb-form__row` stellt zwei Felder
   nebeneinander, die zusammengehoeren - das Raster stellt *alle* nebeneinander,
   die kurz genug sind. Der Unterschied ist wichtig: Wer nur `__row` benutzt,
   muss Paare bilden, und ein Feld, das mal sichtbar ist und mal nicht (Alpine),
   reisst sein Paar mit. Im Raster rutscht die Reihe einfach zusammen.

   **Standard ist volle Breite**, halb ist die Ausnahme - andersherum landeten
   Fehlerbanner, Legende und Knopfzeile in einer halben Spalte. */
.fb-form--raster {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--fb-space-5);
  align-items: start;
}

.fb-form--raster > * {
  grid-column: 1 / -1;
}

.fb-form--raster > .fb-form__group--halb {
  grid-column: auto;
}

@media (max-width: 700px) {
  .fb-form--raster {
    grid-template-columns: minmax(0, 1fr);
  }
}

.fb-form__row {
  display: flex;
  gap: var(--fb-space-4);
}

.fb-form__row .fb-form__group {
  flex: 1;
}

/* **Ein einzelnes Feld in einer Reihe belegt eine Spalte, nicht zwei**
   (03.09.2026). `flex: 1` darueber zog es sonst auf die volle Breite - in der
   Fahrschueler-Maske stand dadurch ein 850px breites Auswahlfeld fuer
   "Dingolfing", in der Fahrzeug-Maske eines fuer "Schaltung". Das ist genau
   die Form, die Sven "zu lang und schlank" genannt hat: Ein Feld, dessen
   Breite nichts ueber seinen Inhalt sagt.

   `max-width` statt `flex-basis`: Die Reihe soll weiter schrumpfen duerfen,
   wenn das Fenster schmal wird. */
.fb-form__row .fb-form__group:only-child {
  max-width: calc(50% - var(--fb-space-2));
}

.fb-form__group {
  margin-bottom: var(--fb-space-4);
}

/* Feldbreiten signalisieren die erwartete Eingabelaenge. --schmal ist fuer
   wirklich kurze Werte (Kuerzel, Stueckzahl), --mittel fuer alles, was zwar
   kurz ist, aber trotzdem lesbar bleiben muss (Kennzeichen, Geldbetrag,
   Prozentsatz) - dort war --schmal mit 110px abzueglich 36px Icon-Reserve zu
   eng zum Lesen. */
.fb-form__group--schmal {
  max-width: 110px;
}

.fb-form__group--mittel {
  max-width: 175px;
}

/* **Beschriftung neben Wert** (Schriftrolle, 03.09.2026): 13px, halbfett,
   Grau 600 - dasselbe Rezept wie Legende, Steckbrief-dt, Fakt-Marke und
   Balkenbeschriftung. Vorher trug jede der vier eine eigene Fassung. */
.fb-form__label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--fb-text-s);
  font-weight: 500;
  color: var(--fb-gray-600);
}

.fb-form__input,
.fb-form__select {
  /* block statt des Vorgabewerts inline-block: als Inline-Element steht das
     Feld auf der Grundlinie und laesst darunter Platz fuer Unterlaengen. Der
     umgebende .fb-form__feld wurde dadurch ein paar Pixel hoeher als das Feld
     selbst - genug, dass die per top: 50% zentrierten Overlays (Warn-Icon,
     Zaehler) sichtbar zu tief sassen. */
  display: block;
  width: 100%;
  padding: var(--fb-space-2) var(--fb-space-3);
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius);
  font-family: var(--fb-font);
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
  background: #fff;
  transition: border-color 0.2s ease;
}

/* Eigene Optik statt der des Betriebssystems - dieselbe Begruendung wie bei
   Checkbox und Radio ein Stueck weiter unten: Die native Variante bringt
   eigenen Pfeil, eigene Hoehe und eigene Schrift mit und sieht dadurch aus,
   als gehoerte sie nicht zur Anwendung. Bei drei Auswahlfeldern nebeneinander
   (Erfassungsmaske) faellt das am staerksten auf.

   Der Pfeil ist ein Tabler-`chevron-down` als data-URI, weil ein
   Hintergrundbild kein `currentColor` kennt - das ist die eine Stelle, an der
   ein Farbwert ausserhalb von tokens.css steht (--fb-gray-600, #4b5563).
   Aendert sich der Ton dort, gehoert er hier nachgezogen. */
.fb-form__select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234b5563' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6l6 -6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  /* Platz fuer den Pfeil, damit ein langer Eintrag nicht darunter laeuft. */
  padding-right: 36px;
  cursor: pointer;
}

/* Der Pfeil weicht dem Overlay-Icon - aber **nur solange es wirklich da ist**.
   Zuerst stand hier `.fb-form__feld .fb-form__select`, also immer, sobald das
   Feld einen Icon-Platz hat; damit standen Klassen-, Quellen- und
   Vorbesitz-Auswahl ohne jedes Zeichen da, weil das Warn-Icon erst nach einem
   leeren Blur erscheint. Das sah kaputter aus als der Zustand davor. Dieselbe
   Loesung wie bei der Combobox, die Chevron und Warn-Icon per x-if tauscht. */
.fb-form__feld--warning .fb-form__select,
.fb-form__feld--success .fb-form__select {
  background-image: none;
}

.fb-form__input:focus,
.fb-form__select:focus {
  outline: 2px solid var(--fb-accent);
  outline-offset: -1px;
}

/* Ein Hinweis unter einer Reihe braucht den Abstand, den eine Feldgruppe
   mitbringt - sonst klebt die naechste Beschriftung an ihm (Fahrschule:
   "IBAN" stand direkt unter dem Steuer-Hinweis). */
.fb-form__row + .fb-form__hinweis--unter {
  margin-bottom: var(--fb-space-4);
}

/* Die Legende "* Pflichtfeld" steht in der Aktionsleiste, rechts - nicht mehr
   als eigene Zeile mit Linie ueber dem Formular (60px fuer vier Zeichen,
   Sauberkeitscheck 03.09.2026). `order` schiebt sie hinter die Knoepfe, egal
   wo sie im Markup steht. */
.fb-form__legende {
  margin: 0 0 0 auto;
  order: 1;
  align-self: center;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

.fb-form__pflicht {
  color: var(--fb-danger);
}

.fb-form__radiogroup {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-4);
}

.fb-form__radio {
  display: flex;
  align-items: center;
  gap: var(--fb-space-2);
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
}

/* Eigene Checkbox-/Radio-Optik statt der Betriebssystem-Variante: die
   macOS-Standardelemente bringen ihre eigene Farbe und Groesse mit und sahen
   dadurch aus, als gehoerten sie nicht zur App. Bewusst nur Form und Farbe
   nachgebaut, keine Animationen - Haken und Punkt kommen als Pseudoelement,
   also ohne externe Bilddatei. */

.fb-form__checkbox input[type="checkbox"],
.fb-form__radio input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  position: relative;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1px solid var(--fb-gray-400);
  background: #fff;
  cursor: pointer;
  transition:
    border-color 0.15s ease,
    background-color 0.15s ease;
}

.fb-form__checkbox input[type="checkbox"] {
  border-radius: var(--fb-radius-sm);
}

.fb-form__radio input[type="radio"] {
  border-radius: 50%;
}

.fb-form__checkbox input[type="checkbox"]:hover,
.fb-form__radio input[type="radio"]:hover {
  border-color: var(--fb-accent);
}

.fb-form__checkbox input[type="checkbox"]:checked,
.fb-form__radio input[type="radio"]:checked {
  background: var(--fb-accent);
  border-color: var(--fb-accent);
}

.fb-form__checkbox input[type="checkbox"]:focus-visible,
.fb-form__radio input[type="radio"]:focus-visible {
  outline: 2px solid var(--fb-accent);
  outline-offset: 2px;
}

/* Haken: zwei Kanten eines gedrehten Rechtecks. */
.fb-form__checkbox input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.fb-form__radio input[type="radio"]:checked::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
  transform: translate(-50%, -50%);
}

/* Dezentes Feld-Feedback: Zaehler bei Fokus, Amber/Gruen-Rahmen + Icon nach
   Blur. Rot (--fb-danger, bewusst dezenter als reines Warnrot) markiert nur
   Pflichtfelder (Sternchen) und den Fehler-Banner - nie den Rahmen eines
   einzelnen Feldes, siehe CLAUDE.md „Formular-Prinzipien". */

.fb-form__feld {
  position: relative;
}

.fb-form__feld .fb-form__input,
.fb-form__feld .fb-form__select {
  padding-right: 36px;
}

.fb-form__feld--warning .fb-form__input,
.fb-form__feld--warning .fb-form__select {
  border-color: var(--fb-warning);
}

.fb-form__feld--success .fb-form__input,
.fb-form__feld--success .fb-form__select {
  border-color: var(--fb-success);
}

.fb-form__icon {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: flex;
  pointer-events: none;
}

.fb-form__icon--warning {
  color: var(--fb-warning);
}

.fb-form__icon--success {
  color: var(--fb-success);
}

/* Zeichenzaehler steht RECHTS NEBEN dem Feld, nicht darin und nicht darunter:
   im Feld lag er auf derselben Position wie das Warn-Icon (beide right: 10px)
   und ueberlappte; unter dem Feld vergroesserte er den Container, wodurch das
   per top: 50% zentrierte Warn-Icon nach unten rutschte. Absolut positioniert
   ausserhalb der Box loest beides auf einmal. */
.fb-form__zaehler {
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--fb-text-xs);
  color: var(--fb-gray-600);
  white-space: nowrap;
  pointer-events: none;
}

/* Das fruehere `margin: 0` hat die 16px Bodenabstand von .fb-form__group
   ueberschrieben. Zusammen mit dem Innenpolster der Optionsgruppe stand die
   Legende dadurch weiter von ihren eigenen Optionen entfernt (15px) als vom
   naechsten Feld darunter (9px) - genau verkehrt herum. Die 8px hier plus das
   Innenpolster ergeben wieder rund 16px zwischen zwei Feldgruppen. */
.fb-form__fieldset {
  margin: 0 0 var(--fb-space-2);
  padding: 0;
  border: none;
  position: relative;
}

.fb-form__fieldset legend {
  padding: 0;
  margin-bottom: 0;
  font-size: var(--fb-text-s);
  font-weight: 500;
  color: var(--fb-gray-600);
}

/* Gleiche Metrik fuer Radio- und Checkbox-Gruppen im Fieldset, damit z. B.
   "Getriebeart" und die Status-Checkbox daneben auf einer Linie sitzen. */
.fb-form__fieldset .fb-form__radiogroup,
.fb-form__fieldset .fb-form__checkboxgroup {
  /* Negativer Rand hebt das Innenpolster wieder auf, damit die erste Option
     buendig unter ihrer Beschriftung steht statt um 10px eingerueckt. Das
     Polster selbst bleibt, damit der Amber-Rahmen im Fehlerfall nicht am Text
     klebt. */
  margin-left: -10px;
  padding: var(--fb-space-2) 10px;
  border: 1px solid transparent;
  border-radius: var(--fb-radius);
  transition: border-color 0.2s ease;
}

.fb-form__fieldset--warning .fb-form__radiogroup {
  border-color: var(--fb-warning);
}

.fb-form__fieldset .fb-form__icon {
  top: 8px;
  right: 10px;
  transform: none;
}

.fb-form__actions {
  display: flex;
  gap: var(--fb-space-3);
  margin-top: var(--fb-space-5);
}

/* Auf Formularseiten haftet die Aktionsleiste am unteren Rand. Nachgemessen:
   "Speichern" begann beim Fahrschueler bei 1155px, bei den Fahrschul-
   Stammdaten bei 1527 - bei rund 960px Fensterhoehe musste man zum Speichern
   erst scrollen. Beim Fahrlehrer war es umgekehrt schief: Der Knopf stand
   mittendrin, **darunter** kam noch das Dokumente-Panel.

   `sticky` statt `fixed`: Es greift nur, solange das Formular hoeher ist als
   das Fenster - kurze Masken (Preislistenposition: Speichern bei 401px) sehen
   unveraendert aus, und am Ende der Karte setzt sich die Leiste von selbst ab.

   Der Knopf bleibt damit **im Formular**. Ihn stattdessen in die Topbar zu
   heben haette `<button form="...">` ausserhalb des Formulars verlangt - und
   `formular-validierung.js` sucht ihn mit
   `formular.querySelector('button[type="submit"]')`. Der Schutz gegen
   Doppelklicks (der schon einmal denselben Datensatz zweimal angelegt hat)
   waere dabei **lautlos** ausgefallen.

   Der Geltungsbereich ist bewusst eng: `.fb-form__actions` steckt in 17
   Templates, auch im Upload-Panel und auf der Rechnung. Nur die direkte
   Aktionszeile eines Formulars auf einer `.fb-formularseite` haftet. */
.fb-formularseite .fb-form > .fb-form__actions {
  position: sticky;
  bottom: 0;
  /* Die Karte hat 24px Polster - der negative Rand zieht die Leiste bis an
     ihre Kanten, sonst endet die Trennlinie 24px vor dem Rahmen. */
  margin: var(--fb-space-5) calc(-1 * var(--fb-space-5)) calc(-1 * var(--fb-space-5));
  padding: var(--fb-space-4) var(--fb-space-5);
  border-top: 1px solid var(--fb-gray-100);
  border-radius: 0 0 var(--fb-radius-lg) var(--fb-radius-lg);
  background: #fff;
}

.fb-form__checkbox {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
}

.fb-form__checkboxgroup {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-4);
}

/* **Nebeneinander statt untereinander** (03.09.2026). Fuenf Gruppen à 69px
   standen gestapelt: 393px fuer zwanzig Kontrollkaestchen, jede Gruppe zu zwei
   Dritteln leer. Als Raster passen zwei bis drei nebeneinander, und die Hoehe
   faellt auf rund ein Drittel. `auto-fill` statt fester Spalten, damit die
   Gruppen im 640px-Formular nicht gequetscht werden. */
.fb-form__klassen-gruppen {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--fb-space-3);
  align-items: start;
}

.fb-form__klassen-gruppe {
  margin: 0;
  padding: var(--fb-space-3) 14px;
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius);
  background: var(--fb-flaeche-innen);
}

/* Gruppentitel ist bewusst ein <span> in einem <div role="group"> statt
   <legend> in einem <fieldset>: eine <legend> sitzt nativ IN der Rahmenlinie
   und schnitt den oberen Rand an (sah aus wie ein Renderfehler). Die
   ueblichen CSS-Tricks dagegen (float, position) brechen entweder das
   Flex-Layout der Checkboxen oder die Zugaenglichkeit. */
.fb-form__klassen-titel {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  margin-bottom: var(--fb-space-2);
  font-size: var(--fb-text-s);
  font-weight: 500;
  color: var(--fb-gray-600);
}

.fb-form__klassen-titel .fb-form__icon-static {
  display: flex;
  color: var(--fb-gray-400);
}

.fb-form__hinweis {
  margin: 0 0 6px;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Hinweis, der zu einem darueberliegenden (ggf. schmalen) Feld gehoert, aber
   die volle Formularbreite nutzen darf. */
/* Zwei Hinweis-Varianten, die man leicht verwechselt - und dann sitzt der Text
   hinter dem Eingabefeld:

   --feld  steht NACH einer geschlossenen .fb-form__group und zieht sich um
           deren Bodenabstand wieder nach oben (negativer Rand).
   --unter steht INNERHALB der Gruppe, direkt unter dem Feld, und braucht
           deshalb Abstand nach oben statt Zug. */
.fb-form__hinweis--feld {
  margin: -10px 0 var(--fb-space-4);
}

.fb-form__hinweis--unter {
  margin: 6px 0 0;
}

/* Sanfte, nicht blockierende Hinweise (z. B. Ersterwerb-Warnung im
   Ausbildungsvorgang-Formular) - bewusst amber statt rot, da kein Fehler:
   Rot bleibt fb-banner/Pflichtfeld-Sternchen vorbehalten (siehe CLAUDE.md
   "Formulare & Validierung"). */

.fb-hinweis-banner {
  display: flex;
  align-items: center;
  gap: var(--fb-space-2);
  border-radius: var(--fb-radius);
  border: 1px solid var(--fb-warning);
  background: var(--fb-warning-tint);
  color: var(--fb-warning-text);
  padding: 10px 14px;
  margin-bottom: var(--fb-space-4);
  font-size: var(--fb-text-l);
}

/* Hinweis bei abgeschaltetem JavaScript (base.html). Bewusst amber wie die
   uebrigen nicht blockierenden Hinweise und nicht rot: Es ist nichts kaputt,
   der Anwendung fehlt nur eine Voraussetzung. */
.fb-noscript {
  border-radius: var(--fb-radius);
  border: 1px solid var(--fb-warning);
  background: var(--fb-warning-tint);
  color: var(--fb-warning-text);
  padding: var(--fb-space-3) var(--fb-space-4);
  margin-bottom: 20px;
  font-size: var(--fb-text-l);
  line-height: 1.5;
}

.fb-hinweis-banner__icon {
  display: flex;
  flex-shrink: 0;
}

/* Erfolgs-Variante (z. B. "zuletzt gespeichert"-Bestaetigung beim
   Schnell-Erfassen mehrerer Preisliste-Positionen hintereinander, siehe
   preisliste_positionen_form.html) - gleiche Struktur, gruener statt
   amberfarbener Ton. */
.fb-hinweis-banner--erfolg {
  border-color: var(--fb-success);
  background: var(--fb-success-tint);
  color: var(--fb-success-text);
}

/* Angebots-Variante: kein blosser Hinweis, sondern ein Vorschlag mit Knopf
   ("Meinten Sie eine neue Version?"). Bewusst kein roter Fehlerbanner - es ist
   nichts falsch eingegeben, nur anders gemeint. */
.fb-hinweis-banner--angebot {
  align-items: flex-start;
}

.fb-angebot__text {
  margin: 0;
  line-height: 1.5;
}

.fb-angebot__aktion {
  margin-top: var(--fb-space-3);
}

/* Versionshistorie auf der Bearbeiten-Seite */
.fb-versionen__marker {
  margin-left: var(--fb-space-2);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Vorbesitz-Vorschlag im Ausbildungsvorgang-Formular (Erwerbstyp
   "Erweiterung") - anklickbare Chips statt Automatik, siehe CLAUDE.md-
   Ergaenzung "Externer Vorbesitz & Vorschlagsfunktion". */

.fb-vorschlag-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-2);
  margin-bottom: 10px;
}

.fb-vorschlag-chip {
  padding: var(--fb-space-1) var(--fb-space-3);
  border: 1px solid var(--fb-accent-tint);
  border-radius: 999px;
  background: var(--fb-accent-tint);
  color: var(--fb-accent-dark);
  font-family: var(--fb-font);
  font-size: var(--fb-text-s);
  font-weight: 500;
  cursor: pointer;
}

.fb-vorschlag-chip:hover {
  background: var(--fb-accent);
  color: #fff;
}

/* Zusaetzliche Bereiche unterhalb eines Formulars (aktuell: Ausbildungsvorgaenge
   im Schuelerprofil, Task 3.3) - gleicher Look wie .fb-form, aber eigenstaendige
   Box statt <form>, da eine Liste/Tabelle statt Eingabefeldern zeigt. */

.fb-panel {
  margin-top: var(--fb-space-5);
  background: var(--fb-flaeche);
  border: 1px solid var(--fb-flaeche-rand);
  border-radius: var(--fb-radius-lg);
  box-shadow: var(--fb-flaeche-schatten);
  padding: var(--fb-space-5);
  /* Damit eine randlose Tabelle (.fb-panel__tabelle) an den abgerundeten
     Panelecken sauber abgeschnitten wird. */
  overflow: hidden;
}

/* In der Profil-Spalte kommt der Abstand vom Grid-gap, sonst summiert er sich. */
.fb-profil__spalte > .fb-panel {
  margin-top: 0;
}

.fb-panel__kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fb-space-4);
  margin-bottom: var(--fb-space-4);
}

/* Zwei Knoepfe rechts im Panelkopf. Der Kopf ist ein `space-between`-Flex - mit
   drei Kindern (Titel, Ansehen, Als PDF) verteilte er sie ueber die ganze
   Breite, und der erste Knopf stand mitten im Panel. Sie gehoeren zusammen,
   also brauchen sie eine gemeinsame Huelle. Seit #60 an der ausgestellten
   Rechnung. */
.fb-panel__aktionen {
  display: flex;
  align-items: center;
  gap: var(--fb-space-2);
}

/* Anzahl direkt am Panel-Titel statt als eigene Zeile - im Panel ist der Platz
   neben der Ueberschrift ohnehin frei. */
/* Beisatz **nach** dem Panel-Titel (aktuell: "- bereits erfasst an diesem Tag"
   hinter dem Datum). Deutlich leiser und leichter, damit die Ueberschrift der
   Tag bleibt und nicht die Erlaeuterung dazu.
   Der Titel selbst behaelt seine normale Groesse: Ein einzelnes aufgeblasenes
   Panel faellt gegen alle anderen auf, und der Abstand entsteht ohnehin durch
   den Beisatz. */
.fb-panel__beisatz {
  margin-left: var(--fb-space-1);
  font-size: var(--fb-text-s);
  font-weight: 400;
  color: var(--fb-gray-600);
}

.fb-panel__anzahl {
  margin-left: 6px;
  font-size: var(--fb-text-s);
  font-weight: 400;
  color: var(--fb-gray-600);
}

.fb-panel__titel {
  margin: 0;
  font-size: var(--fb-text-xl);
  font-weight: 600;
  color: var(--fb-gray-800);
}

/* Tabelle randlos bis an die Panelkante ziehen: vorher hatten Panel und
   Tabelle je einen eigenen Rahmen (sichtbarer Doppelrahmen). overflow-x haelt
   breite Tabellen im Kasten, statt sie darueber hinauslaufen zu lassen. */
.fb-panel__tabelle {
  /* **Der negative Rand haengt am Panel-Polster.** Als feste -24px war er eine
     stille Kopplung: Wer das Polster aendert, verschiebt die Tabelle aus dem
     Panel heraus, ohne dass etwas rot wird. */
  margin: 0 calc(-1 * var(--fb-space-5));
  overflow-x: auto;
}

/* Untere Panelkante nur schliessen, wenn die Tabelle wirklich das letzte
   Element ist - sonst zieht der negative Rand nachfolgende Inhalte hoch
   (z. B. den Speichern-Button unter der Sonderfahrten-Tabelle). */
.fb-panel__tabelle:last-child {
  margin-bottom: calc(-1 * var(--fb-space-5));
}

.fb-panel__tabelle .fb-table {
  border: none;
  border-radius: 0;
}

/* **Die Zelle fluchtet mit dem Titel** (Abstandspruefung, 03.09.2026): Die
   Tabelle reicht bis an die Panelkante, ihre Zellen haben 12px Polster, der
   Titel steht bei 24 - der Text der ersten Spalte begann 12px links vom
   Titel, auf jeder Seite mit Tabelle im Panel (Uebersicht, Verlauf,
   Finanzen, Preisliste). Randzellen bekommen das Panelpolster. */
.fb-panel__tabelle .fb-table th:first-child,
.fb-panel__tabelle .fb-table td:first-child {
  padding-left: var(--fb-space-5);
}

.fb-panel__tabelle .fb-table th:last-child,
.fb-panel__tabelle .fb-table td:last-child {
  padding-right: var(--fb-space-5);
}

/* Fussbereich eines Panels unterhalb einer randlosen Tabelle (aktuell:
   Speichern-Button der Sonderfahrten-Tabelle). */
.fb-panel__fuss {
  margin-top: 20px;
}

/* **Unten so viel Polster wie oben** (Abstandspruefung, 03.09.2026): Neun
   Panels endeten mit einem Absatz, einer Merkliste oder einem Hinweis, dessen
   eigener Rand nach unten zum Polster dazukam - 31, 33, 41, 45px statt 25.
   Das letzte Kind gibt seinen Rand ab; die randlose Tabelle behaelt ihren
   negativen. */
.fb-panel > :last-child:not(.fb-panel__tabelle),
.fb-panel > form:last-child > :last-child {
  margin-bottom: 0;
}

/* Ein Panelkopf, dem nur noch ein ausgeblendeter Aufklapper folgt (Rechnung:
   "Stornieren..."), ist optisch das letzte Kind - `:last-child` sieht das
   nicht, Alpine setzt `display: none` als Inline-Stil. Klappt er auf, kommt
   der Rand zurueck. */
.fb-panel > .fb-panel__kopf:has(+ [style*="display: none"]:last-child) {
  margin-bottom: 0;
}

/* Und die beiden anderen Faelle, in denen `:last-child` am falschen Element
   haengt: der Fussabsatz im Panelfuss (Preisliste, Mein Konto) und eine
   Feldgruppe, hinter der nur noch ein <noscript> steht (Rechnung anlegen). */
.fb-panel__fuss > :last-child,
.fb-panel > form:last-child > .fb-form__group:has(+ noscript:last-child) {
  margin-bottom: 0;
}

/* Stand des gewaehlten Fahrschuelers, rechts in der Label-Zeile (B3, Wunsch
   Alex). Ruhig gehalten: Es ist eine Auskunft, keine Warnung. Der Platz war
   ohnehin leer, und so aendert der Hinweis die Zeilenhoehe nicht - unter dem
   Feld haette er mit dem Notiz-Label kollidiert. */
/* Das × zum Zurücknehmen der Auswahl. Sitzt auf demselben Platz wie der
   Chevron und übernimmt dessen Position aus .fb-form__icon - hier nur der
   Knopf-Charakter, den ein <span> nicht mitbringt. */
.fb-combobox__leeren {
  padding: 0;
  border: none;
  background: none;
  color: var(--fb-gray-600);
  cursor: pointer;
  /* `.fb-form__icon` traegt `pointer-events: none` - die Overlays waren bisher
     alle rein dekorativ (Warn-Icon, Haken, Zaehler). Dieses hier ist das erste,
     das man anklicken koennen muss; ohne die Zeile faengt das darunter liegende
     Eingabefeld den Klick ab. */
  pointer-events: auto;
}

.fb-combobox__leeren:hover {
  color: var(--fb-gray-800);
}

.fb-combobox__kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fb-space-3);
}

.fb-combobox__stand {
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
  white-space: nowrap;
}

/* Laender-Auswahl (Geburtsland, Staatsangehoerigkeit) */

.fb-combobox {
  position: relative;
}

.fb-combobox__zeile {
  position: relative;
}

.fb-combobox__liste {
  position: absolute;
  z-index: var(--fb-ebene-schwebend);
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  margin: 0;
  padding: var(--fb-space-1);
  list-style: none;
  background: #fff;
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius);
  box-shadow: var(--fb-shadow-lg);
}

.fb-combobox__option {
  padding: 6px 10px;
  border-radius: var(--fb-radius);
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
  cursor: pointer;
}

/* Markierung fuer Maus UND Tastatur: aktiverIndex wandert mit den Pfeiltasten
   und folgt der Maus, damit beide Bedienarten dieselbe Zeile hervorheben. */
.fb-combobox__option--aktiv {
  background: var(--fb-accent-tint);
}

.fb-combobox__option--sonstiges {
  margin-top: var(--fb-space-1);
  padding-top: var(--fb-space-2);
  border-top: 1px solid var(--fb-gray-200);
  color: var(--fb-gray-600);
}

/* Zeigt an, dass hinter dem Feld eine Auswahlliste steckt - ohne den Pfeil
   sah die Combobox aus wie ein gewoehnliches Textfeld. */
.fb-combobox__chevron {
  color: var(--fb-gray-600);
  transition: transform 0.15s ease;
}

.fb-combobox__zeile:focus-within .fb-combobox__chevron {
  transform: translateY(-50%) rotate(180deg);
}

.fb-combobox__freitext {
  margin-top: var(--fb-space-2);
}

/* Fahrschueler-Liste (Task 3.2) */

.fb-listenkopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fb-space-4);
  margin-bottom: 20px;
}

/* Fuer Listen ohne Such-/Filterleiste (z. B. Fahrlehrer, Task 4.2): nur der
   "+ Neu"-Button, rechtsbuendig statt per space-between ans linke Ende
   gedrueckt. */
.fb-listenkopf--rechts {
  justify-content: flex-end;
}

.fb-listenkopf__filter {
  display: flex;
  align-items: center;
  gap: var(--fb-space-3);
}

.fb-listenkopf__status {
  width: auto;
}

.fb-suchfeld {
  position: relative;
  display: flex;
  align-items: center;
}

.fb-suchfeld__icon {
  position: absolute;
  left: 10px;
  display: flex;
  color: var(--fb-gray-600);
  pointer-events: none;
}

.fb-suchfeld__input {
  width: 260px;
  padding: var(--fb-space-2) var(--fb-space-3) var(--fb-space-2) 34px;
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius);
  font-family: var(--fb-font);
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
  background: #fff;
}

.fb-suchfeld__input:focus {
  outline: 2px solid var(--fb-accent);
  outline-offset: -1px;
}

.fb-table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius-lg);
  overflow: hidden;
}

/* **Die Geschichte der Zeilenhoehe, weil sie zweimal gemessen wurde:** 12px
   senkrecht ergaben 47px Zeilenhoehe, am 27.08.2026 auf 8px und damit 39px
   gebracht. Am 03.09.2026 dann auf 4px und 31px - siehe darunter. */
/* **Eine Dichte, keine Variante** (B12, dritte Runde, P3). Bis zum 03.09.2026
   gab es `.fb-table--dicht` fuer engere *waagerechte* Polster - und die
   "Ausnahme" stand in acht von neun Tabellen. Was fast ueberall gilt, ist keine
   Variante, sondern die Regel; die Klasse ist ersatzlos entfallen.

   **Senkrecht 4px statt 8** (Zeile 39 -> 31 px, nachgemessen an drei Fassungen
   auf einer Wegwerfseite). Der Boden ist damit erreicht: Das Status-Badge ist
   22px hoch, mehr Enge saehe die Zeile nicht, sie wuerde nur das Badge an die
   Trennlinie druecken. Fahrschuelerliste 2205 -> rund 1850 px, Preisliste
   2720 -> rund 2350.

   **Die Schriftgroesse bleibt 15px.** Sie zu verkleinern braechte nochmal acht
   Prozent und kostete Lesbarkeit fuer jemanden, der den ganzen Tag darauf
   schaut - derselbe Tausch wurde am 27.08.2026 schon einmal abgelehnt. */
/* **Die Zeilenhoehe haengt nicht an der Schrift** (03.09.2026): Ohne eigene
   Zeilenhoehe nimmt eine Zelle `normal`, und das sind die Metriken der
   Familie - beim Wechsel auf Plex wuchs jede Zeile um ein Pixel (31 -> 32),
   ohne dass jemand eine Zahl geaendert hatte. `--fb-leading-tight` legt sie
   fest; dasselbe am Badge, dem hoechsten Element der Zeile. */
.fb-table th,
.fb-table td {
  padding: var(--fb-space-1) var(--fb-space-3);
  /* **Eine Zeilenhoehe: 31px** (Abstandspruefung, 03.09.2026). Gemessen
     waren es 28 (nur Text), 31 (mit Badge) und 35 (mit Zeilenknopf) - die
     Erfassung, die Fahrstunden und die Lektionen stachen heraus. Sven nannte
     die Fahrschuelerliste (31) "sehr sauber"; die ist jetzt das Mass
     (`--fb-tabellenzeile`, Regel an `.fb-table td` unten). */
  text-align: left;
  font-size: var(--fb-text-l);
  line-height: var(--fb-leading-tight);
}

/* **Tabellarische Ziffern in der ganzen Tabelle**, nicht nur in der
   Betragsspalte. Datumsangaben stehen untereinander und fluchteten nicht:
   "03.08.2026" und "28.08.2026" waren verschieden breit, weil die 1 schmaler
   ist als die 8. In einer Spalte, die man von oben nach unten ueberfliegt, ist
   das der Unterschied zwischen Lesen und Suchen. */
.fb-table td {
  /* Die Hoehe wirkt in einer Tabellenzelle als Mindesthoehe der Zeile: Eine
     Textzeile (28) und ein Badge (30) wachsen auf 31, ein Zeilenknopf (26 +
     Polster = 34) gibt seinen Ueberhang unten ab. */
  height: var(--fb-tabellenzeile);
  font-variant-numeric: tabular-nums;
}

.fb-table td .fb-btn--zeile,
.fb-table td .fb-btn--zeile-stumm {
  margin-top: calc(-1 * var(--fb-space-1));
  margin-bottom: calc(-1 * var(--fb-space-1));
}

/* **Die erste Spalte fuehrt.** In einer Tabelle sucht man ueber eine Spalte -
   den Namen, die Bezeichnung, die Klasse - und liest die uebrigen erst, wenn
   man die Zeile gefunden hat. Vorher waren alle Zellen gleich gewichtet, also
   fuehrte keine. Ein halber Schnitt mehr reicht; fett waere zu viel fuer etwas,
   das in jeder Zeile steht. */
/* **Der Leitwert ist 450** (Sauberkeitscheck, entschieden am 03.09.2026):
   Plex "Text", der Schnitt zwischen Regular und Medium. Mit 500 war die
   Suchspalte in Plex fetter als in Inter bei gleicher Zahl. */
.fb-table tbody td:first-child:not(.fb-table__zahl) {
  font-weight: 450;
  color: var(--fb-gray-800);
}

/* **Uebersicht gegen Datentabelle** (03.09.2026, Sven am Bild): In einer
   Uebersicht fuehrt eine Spalte, die anderen begleiten - Grau 600. In einer
   Datentabelle (Positionen, Preise, Stunden) traegt jede Spalte und bleibt
   Grau 800. Badges und Links behalten ihre Farbe, sie setzen sie selbst. */
.fb-table--uebersicht tbody td:not(:first-child) {
  color: var(--fb-gray-600);
}

/* **Das Wort "Guthaben" ist gruen** (Sven, 03.09.2026: "Guthaben koennte man
   doch wieder gruen markieren") - das Wort, nicht der Betrag: Der Betrag
   bleibt eine Zahl in Textfarbe (Geld-Regel), die Richtung traegt das Wort,
   und ein Guthaben ist die eine Saldo-Lage, die im Sinn der Farbregel
   "erfuellt" heisst: bezahlt, und mehr. Am Vormittag noch andersherum
   entschieden ("Guthaben in Listen ohne Gruen"), am Bild zurueckgenommen. */
/* Beide Klassen im Selektor: Das Wort ist auch ein Nebenwert, und dessen
   Grau stand spaeter in der Datei - das Gruen kam nie an (03.09.2026,
   gemessen: rgb(91, 101, 112)). */
.fb-table__nebenwert.fb-table__guthaben {
  color: var(--fb-success-text);
  font-weight: 500;
}

/* **Eine Zahl fuehrt nie.** Auf der Rechnung stand die Positionsnummer als
   einziges halbfettes Element der Zeile - die Regel traf die erste Spalte,
   nicht die Suchspalte. Und ein Nebenwert *in* der Leitspalte (der Code hinter
   der Bezeichnung in der Preisliste) erbte den halben Schnitt und las sich wie
   ein zweiter Leitwert. Beides am 03.09.2026 nachgemessen: `:not(.fb-table__zahl)`
   oben, und der Nebenwert setzt seinen Schnitt selbst zurueck. */
.fb-table td:first-child .fb-table__nebenwert {
  font-weight: 400;
}

/* **Der Spaltenkopf sieht nicht mehr aus wie eine Datenzeile** (03.09.2026).
   Vorher: 13px, gemischte Schreibung, dieselbe Anmutung wie der Inhalt darunter
   - getrennt nur durch eine Linie und einen Grauton. Jetzt 12px versal und
   gesperrt: Das trennt Kopf von Daten, ohne eine zweite Linie zu ziehen, und
   ist der staerkste Einzeleffekt der typografischen Runde (am Bild verglichen,
   `/stil/typo`).

   **Versalien nur hier und an den Kachelmarken** - beides sind Beschriftungen
   von zwei bis drei Woertern. Ein ganzer Satz in Versalien liest sich schlecht;
   das ist keine Stilfrage, sondern messbar langsamer. */
.fb-table th {
  background: var(--fb-flaeche-innen);
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-gray-600);
  border-bottom: 1px solid var(--fb-gray-200);
}

.fb-table tbody tr:not(:last-child) td {
  border-bottom: 1px solid var(--fb-gray-100);
}

/* Summenzeile (aktuell: Leistungen im Schuelerprofil) */
.fb-table tfoot td {
  border-top: 1px solid var(--fb-gray-200);
  background: var(--fb-flaeche-innen);
  font-weight: 500;
}

.fb-table__row {
  position: relative;
}

.fb-table__row:hover {
  background: var(--fb-gray-50);
}

/* Ein Textlink, der wie Text aussieht: dunkel, halbfett, ohne Unterstrich, bis
   man ihn anfasst. `.fb-table__link` ist derselbe Look **plus** der gedehnte
   Deckel - wer den Deckel nicht will, nimmt `.fb-link`. Bis zum 03.09.2026 gab
   es die Trennung nicht, und an drei Stellen stand `.fb-table__link` ausserhalb
   einer Tabellenzeile, nur um den Look zu bekommen (siehe unten). */
.fb-link,
.fb-table__link {
  color: var(--fb-gray-800);
  text-decoration: none;
  font-weight: 450;
}

.fb-link:hover {
  text-decoration: underline;
}

/* **Der Deckel haengt an der Zeile, nicht am Link.** `inset: 0` bezieht sich auf
   den naechsten *positionierten* Vorfahren; ohne ihn ist das die ganze Seite.
   Deshalb steht `.fb-table__row` im Selektor: Die Regel greift nur dort, wo die
   Voraussetzung (`position: relative`) nachweislich erfuellt ist.

   **Warum das die Regel und nicht nur ein Test ist:** Ein unscoped
   `.fb-table__link::after` wirkt ueberall, wo jemand die Klasse hinschreibt -
   und wer sie hinschreibt, will meistens nur den Look. Am 02.09.2026 machte so
   ein Vorkommen die halbe Fahrschuelerakte klickbar, am 03.09.2026 fanden sich
   drei weitere (Rechnung, Vorgang-Ansicht, Startseite): Auf `/rechnungen/{id}`
   spannte der Link zum Fahrschueler eine unsichtbare Flaeche von 1440x1033 px
   ueber die Seite, und "Ansehen" oeffnete die Fahrschuelerakte statt der
   Rechnung (von Sven gefunden). Scoped ist ein verirrtes `.fb-table__link`
   wirkungslos statt gefaehrlich - der Fehler faellt beim Benutzen auf, nicht
   beim Danebenklicken. Dieselbe Vorsichtsmassnahme bei `.fb-kachel__ziel` und
   `.fb-anmeldung__ziel`. */
.fb-table__row .fb-table__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Geld-, Datums- und Aktionszellen nie umbrechen lassen - "100,00 €" auf zwei
   Zeilen war der auffaelligste Schoenheitsfehler der Preisliste. Bei zu
   schmalem Panel scrollt stattdessen .fb-panel__tabelle horizontal. */
/* Mit .fb-table davor, sonst schlaegt die Grundregel `.fb-table th, .fb-table td`
   die Ausrichtung per Spezifitaet wieder tot. */
.fb-table .fb-table__nowrap {
  white-space: nowrap;
}

.fb-table .fb-table__zahl {
  white-space: nowrap;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Zwischenueberschrift in einer Tabelle (aktuell: Kategorie in der
   Preisliste). Ruhiger als eine Kopfzeile, aber deutlich genug, um eine
   Gruppe zu oeffnen - sie ersetzt ein Badge in jeder einzelnen Zeile. */
/* Als getoentes Band, nicht als grauer Text: In Grau-600 und 13px war die
   Ueberschrift zwischen 34 Zeilen kaum als solche zu erkennen. Probiert wurden
   vier Fassungen nebeneinander im Browser - dunkler Flattersatz las sich wie
   eine weitere Datenzeile, blosse Akzentfarbe war lesbar, aber leise. Das Band
   gewinnt, weil es die Gruppe **oeffnet**, statt sie nur zu beschriften.
   Akzent statt Grau: Der Tabellenkopf ist grau, ein zweites graues Band saehe
   aus wie eine zweite Kopfzeile. **Seit Fassung C (03.09.2026) in der Marke**
   (`--fb-marke-text` auf `--fb-marke-tint`, 6,2 : 1): Das Band oeffnet eine
   Gruppe, es handelt nicht - einer der fuenf Orte, an denen das Teal steht. */
.fb-table .fb-table__gruppe th {
  padding-top: 6px;
  padding-bottom: 6px;
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-marke-text);
  background: var(--fb-marke-tint);
  border-bottom: none;
}

/* Die Trennlinie der Vorzeile wuerde sonst mitten in den Gruppenabstand
   fallen - die Gruppe soll oben offen beginnen. */
.fb-table tbody tr:has(+ .fb-table__gruppe) td {
  border-bottom: none;
}

/* Saldo-Karte ueber dem Zahlungsformular: der offene Betrag, bevor man tippt. */
.fb-saldo-karte {
  margin-bottom: 20px;
}

.fb-saldo-karte__betrag {
  display: block;
  margin: 2px 0 var(--fb-space-2);
  font-size: var(--fb-text-3xl);
  letter-spacing: var(--fb-tracking-eng);
  font-weight: 600;
  color: var(--fb-gray-800);
  font-variant-numeric: tabular-nums;
}

/* Ein Guthaben ist kein Fehler, sondern eine Rueckzahlung - deshalb Gruen wie
   "erfuellt" und nicht Rot. Rot bleibt echten Fehlern vorbehalten. */
.fb-saldo--guthaben {
  color: var(--fb-success-text);
}

/* Kennzahlen ueber einer Liste (aktuell: Finanzen). Bewusst zwei getrennte
   Zahlen statt einer verrechneten - offene Forderungen und Guthaben gehoeren
   verschiedenen Leuten. */
.fb-kennzahlen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-4);
  margin-bottom: 20px;
}

.fb-kennzahl {
  flex: 0 1 auto;
  min-width: 200px;
  padding: 14px 18px;
  border: 1px solid var(--fb-flaeche-rand);
  border-radius: var(--fb-radius-lg);
  background: var(--fb-flaeche);
  box-shadow: var(--fb-flaeche-schatten);
}

/* Beschriftung ueber Daten - dieselbe Rolle wie die Kachelmarke, seit dem
   03.09.2026 auch dieselbe Form (vorher 13px gemischt: Uebersicht gegen
   Akten-Kopf, zwei Rezepte fuer eine Marke ueber einer Zahl). Gilt auch fuer
   die Saldo-Karte ueber dem Zahlungsformular. */
.fb-kennzahl__label,
.fb-saldo-karte__label {
  display: block;
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-gray-600);
}

.fb-kennzahl__wert {
  display: block;
  margin-top: 2px;
  font-size: var(--fb-text-3xl);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-eng);
  color: var(--fb-gray-800);
  font-variant-numeric: tabular-nums;
}

/* Zusatz in einer Spaltenueberschrift (aktuell: "inkl. MwSt." hinter "Preis").
   Ohne ihn liest sich der Steuersatz daneben wie ein Aufschlag - er ist aber
   der enthaltene Anteil. */
.fb-tabellenkopf__zusatz {
  font-weight: 400;
  text-transform: none;
  color: var(--fb-gray-600);
}

/* Zweitwert in derselben Zelle (aktuell: Alter neben dem Geburtsdatum).
   Leiser als der Hauptwert, damit die Spalte weiter auf das Datum liest. */
.fb-table__nebenwert {
  margin-left: 6px;
  color: var(--fb-gray-600);
  font-variant-numeric: tabular-nums;
}

/* **Der Normalfall bekommt keine Pille** (03.09.2026, vierte Durchsicht).
   "Aktiv" stand als gruenes Badge auf 39 von 50 Zeilen der Fahrschuelerliste:
   Die lauteste Farbe der Seite sagte nichts - und sie sagte es in der Farbe,
   die "erfuellt" heisst. Dieselbe Regel wie bei den Kacheln ("Ein Etikett, das
   immer dasteht, sagt nichts"), nur dass eine leere Zelle in einer filterbaren
   Spalte wie ein Fehler aussaehe: Der Normalfall steht als leises Wort, die
   Abweichung (Pausiert, Inaktiv, Abgeschlossen) behaelt ihre Pille. */
.fb-table__normalfall {
  color: var(--fb-gray-600);
}

/* Platzhalter innerhalb einer Tabellenzelle (z. B. "noch nicht in Kraft").
   Bewusst nicht .fb-leer: das ist der grosse, zentrierte Leerzustand einer
   ganzen Liste und blies als Zelle die Tabellenzeile auf. */
/* Kein Kursiv (Schriftrolle, 03.09.2026): Ein Platzhalter ist ein leiser
   Nebenwert, keine dritte Schriftlage. */
.fb-table__leer {
  color: var(--fb-gray-600);
  white-space: nowrap;
}

/* Aktionen-Spalte fuer Tabellen mit mehreren Links je Zeile (z. B.
   Preisliste-Uebersicht: Bearbeiten + Duplizieren) - bewusst ohne
   fb-table__link/::after-Stretched-Link-Technik, da die pro Zeile auf ein
   einzelnes Link-Ziel festlegt. */
/* Bewusst KEIN display:flex auf der Zelle: das nimmt ihr das Tabellenzell-
   Verhalten, wodurch Zeilentrenner an dieser Spalte sichtbar abrissen. Die
   Links liegen inline, der Abstand kommt ueber margin. */
.fb-table .fb-table__aktionen {
  position: relative;
  text-align: right;
  white-space: nowrap;
}

.fb-table__aktionen .fb-table__aktion + .fb-table__aktion {
  margin-left: var(--fb-space-3);
}

/* Text-Aktion und Icon-Knopf in derselben Zelle sassen 3px versetzt: Ein
   inline-flex-Knopf haengt mit seiner Unterkante an der Textgrundlinie, nicht
   mit seiner Mitte. `vertical-align: middle` auf beiden richtet sie an der
   Mitte der Zeilenbox aus.
   **Kein `display: flex` auf der Zelle** - das nimmt ihr das Zell-Verhalten,
   und die Zeilentrenner reissen an dieser Spalte ab (siehe oberflaeche.md). */
.fb-table__aktionen .fb-table__aktion,
.fb-table__aktionen .fb-btn {
  vertical-align: middle;
}

/* Mehrere Aktionen in einer Zelle. Der Bestaetigungsdialog bringt einen
   <div x-data> mit, ein POST-Knopf ein <form> - beides Bloecke, die sich
   untereinander stapelten, sobald neben ihnen noch ein Icon-Knopf stand
   (Zahlungszeile seit #60: ansehen, herunterladen, loeschen).
   **Wieder kein `display: flex` auf der Zelle**, aus demselben Grund wie oben:
   Das nimmt ihr das Zell-Verhalten und reisst die Zeilentrenner ab. */
.fb-table__aktionen > div,
.fb-table__aktionen > form {
  display: inline-block;
  vertical-align: middle;
}

.fb-table__aktionen > .fb-btn + .fb-btn,
.fb-table__aktionen > .fb-btn + div,
.fb-table__aktionen > .fb-btn + form,
.fb-table__aktionen > div + div,
.fb-table__aktionen > form + div {
  margin-left: var(--fb-space-1);
}

/* Engeres Polster fuer Tabellen mit vielen Spalten (aktuell nur die
   Preisliste: acht Spalten, davon eine mit drei Aktionen). Sie war als einzige
   28px zu breit fuer den Panelbereich - genug, um "Duplizieren" abzuschneiden,
   und zwar bei jeder Fensterbreite, weil der Inhaltsbereich ohnehin bei 1280px
   gedeckelt ist. Nachgemessen, nicht geschaetzt: 8px je Seite und Spalte
   bringen 64px zurueck. */
.fb-table__aktion {
  color: var(--fb-gray-600);
  text-decoration: none;
  font-size: var(--fb-text-s);
}

.fb-table__aktion:hover {
  color: var(--fb-accent);
  text-decoration: underline;
}

.fb-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--fb-text-s);
  font-weight: 500;
  line-height: var(--fb-leading-tight);
}

/* Ein Zaehlerstand in der Fahrschuelerakte ("ÜL 4/5"). Bewusst kein fb-badge:
   Badges tragen im Projekt einen Zustand (aktiv, pausiert), hier steht eine
   Zahl. Erfuellte Staende bekommen denselben gruenen Ton wie ein aktives
   Badge - das ist die Farbe, die im Projekt "fertig" bedeutet. */
.fb-stand {
  display: inline-block;
  margin-right: var(--fb-space-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--fb-gray-600);
}

/* Fortschrittsbild fuer Pflichtzahlen (B12). Ein Segment je Pflichteinheit -
   die Zahl bleibt danebenstehen, der Balken ist die Zugabe, nicht der Ersatz.
   `1fr` je Segment statt einer festen Breite: Die groesste vorkommende
   Pflichtzahl ist 18 (klassenspezifische Doppelstunden), die kleinste 1 -
   beide muessen in dieselbe Spalte passen. */
/* **Neu gefasst mit B12/P1 (02.09.2026).** Die Segmente streckten sich vorher
   ueber die volle Spaltenbreite (`grid-auto-columns: 1fr`) - in einer schmalen
   Kachel wurden daraus Balken, die je nach Pflichtzahl mal fingerbreit und mal
   fadenduenn waren. Jetzt haben sie eine **feste Breite** und stehen
   linksbuendig: Fuenf Segmente sehen immer gleich aus, egal wie breit die
   Kachel ist, und man kann abzaehlen, was fehlt. */
.fb-fortschritt {
  font-variant-numeric: tabular-nums;
}

.fb-fortschritt + .fb-fortschritt {
  margin-top: var(--fb-space-3);
}

.fb-fortschritt__kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fb-space-3);
  margin-bottom: var(--fb-space-1);
  font-size: var(--fb-text-s);
  font-weight: 500;
  color: var(--fb-gray-600);
  white-space: nowrap;
}

/* Die Zahl am Balken ist ein Leitwert (15, halbfett), die Beschriftung
   davor eine Beschriftung neben Wert (13) - zwei Rollen in einer Zeile. */
.fb-fortschritt__zahl {
  font-size: var(--fb-text-l);
  font-weight: 450;
  color: var(--fb-gray-800);
}

.fb-fortschritt__balken {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
}

/* 18px breit, 8px hoch: schmal genug, dass die zwoelf Grundstoff-Doppelstunden
   - der haeufigste lange Balken - in **eine** Zeile einer Kachel passen, und
   breit genug, dass ein einzelnes Segment als Einheit abzaehlbar bleibt. Die
   groesste vorkommende Pflichtzahl (18 klassenspezifische Doppelstunden) bricht
   um, dafuer `flex-wrap`. Die Rechnung steht als Test in
   `tests/test_gestaltung.py` - eine Zahl im Kommentar veraltet, ein Test nicht. */
.fb-fortschritt__segment {
  width: 18px;
  height: 8px;
  border-radius: var(--fb-radius-sm);
  background: var(--fb-gray-200);
  /* Von links wachsen, nicht aus der Mitte - sonst laeuft die Reihe beim Laden
     auseinander statt sich aufzubauen. */
  transform-origin: left center;
  /* Die Fuellung waechst beim Laden aus dem Nichts - `--fb-ease` hat einen
     langen Auslauf, das liest sich als "wird erreicht" statt als Zappeln. Nur
     die Farbe bewegt sich, nicht das Layout: Ein wachsender Balken wuerde die
     Kachelhoehe waehrend der Animation aendern. */
  animation: fb-fuellen var(--fb-dauer) var(--fb-ease) both;
}

/* Die Segmente laufen leicht versetzt an - von links nach rechts, wie man sie
   liest. **Der Versatz kommt aus dem Baustein**, nicht aus `nth-child`: Eine
   Regel alle sechs Segmente lief bei elf Segmenten zweimal los, der zweite
   Lauf begann in der Mitte des Balkens. Genau das war zu sehen (Sven,
   02.09.2026). Der Baustein deckelt bei 300ms - sonst braeuchte ein Balken mit
   achtzehn Doppelstunden eine halbe Sekunde, bis er fertig ist. */
.fb-fortschritt__segment {
  animation-delay: var(--fb-verzoegerung, 0ms);
}

@keyframes fb-fuellen {
  from {
    opacity: 0;
    transform: scaleX(0.4);
  }
}

/* Wer Bewegung abbestellt hat, bekommt sie nicht - die Anzeige ist ohne sie
   vollstaendig. */
.fb-fortschritt__segment--voll {
  background: var(--fb-accent);
}

/* Die angefangene Einheit wird anteilig gefuellt, nicht amber eingefaerbt:
   Amber heisst in Fahrbase "Hinweis" (siehe Arbeitsprinzip 3), und eine halb
   gefahrene Stunde ist keiner. Der Anteil kommt als CSS-Variable aus dem
   Template - so steht dort kein Farbwert. */
.fb-fortschritt__segment--teil {
  background: linear-gradient(
    90deg,
    var(--fb-accent) var(--fb-fortschritt-anteil, 50%),
    var(--fb-gray-200) 0
  );
}

/* Erfuellt: derselbe Gruenton, den `fb-stand--erfuellt` und das Badge "erfüllt"
   schon tragen - kein dritter Ton fuer denselben Sachverhalt. */
.fb-fortschritt--erfuellt .fb-fortschritt__zahl {
  color: var(--fb-success-text);
}

.fb-fortschritt--erfuellt .fb-fortschritt__segment--voll {
  background: var(--fb-success);
}

.fb-stand--erfuellt {
  color: var(--fb-success-text);
  font-weight: 500;
}

/* Steht direkt unter einem Fortschrittsbalken und klebte sonst daran. */
.fb-stand--unter-balken {
  margin-top: 6px;
}

.fb-badge--aktiv {
  background: var(--fb-success-tint);
  color: var(--fb-success-text);
}

.fb-badge--pausiert {
  background: var(--fb-warning-tint);
  color: var(--fb-warning-text);
}

.fb-badge--abgeschlossen,
.fb-badge--abgebrochen,
.fb-badge--inaktiv,
.fb-badge--archiviert,
.fb-badge--neutral {
  background: var(--fb-gray-100);
  color: var(--fb-gray-600);
}

/* Der Stempel: "Ausgestellt" auf der Rechnung selbst (03.09.2026) - Teal
   markiert, wie in der Farbrichtung vorgesehen. Marken-Text auf Marken-Tint:
   6,2 : 1. In Listen kommt der Ton nicht vor (Normalfall ohne Pille). */
.fb-badge--marke {
  background: var(--fb-marke-tint);
  color: var(--fb-marke-text);
}

/* Kategorien der Preisliste: bewusst alle im selben neutralen Ton. Acht
   Kategorien einzeln einzufaerben haette acht neue Bedeutungen erfunden -
   Farbe bleibt hier Status vorbehalten (gruen/amber/grau) bzw. Fehlern (rot),
   siehe CLAUDE.md. Das Badge dient nur der schnelleren Scanbarkeit. */

/* Anzahl-Zeile ueber einer Liste - beantwortet "wie viele sind das
   eigentlich?", ohne die Kopfleiste mit Filter und Anlegen-Knopf zu fuellen. */
.fb-listen-anzahl {
  margin: 0 0 10px;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

.fb-leer {
  padding: var(--fb-space-6);
  text-align: center;
  color: var(--fb-gray-600);
  background: var(--fb-flaeche);
  border: 1px solid var(--fb-flaeche-rand);
  border-radius: var(--fb-radius-lg);
  box-shadow: var(--fb-flaeche-schatten);
}

/* **Der kleine leere Zustand** (02.09.2026, zweite Durchsicht). Der grosse
   gehoert dorthin, wo die *Seite* leer ist: Icon, Titel, Satz, Knopf, rund
   300px. In einem Panel *innerhalb* einer gefuellten Seite war er dreimal
   verkehrt - er nahm den Platz von drei Tabellenzeilen ein, und sein Knopf
   stand ein zweites Mal 200px darueber im Panelkopf. Hier bleibt eine Zeile
   Text; die Aktion hat der Kopf. */
.fb-leer--knapp {
  margin: 0;
  padding: var(--fb-space-4) 0 0;
  text-align: left;
  background: none;
  border: none;
  border-radius: 0;
  font-size: var(--fb-text-s);
}

.fb-leer--knapp strong {
  color: var(--fb-gray-800);
  font-weight: 500;
}

/* Innerhalb eines Panels bringt das Panel schon Rahmen und Hintergrund mit. */
.fb-panel .fb-leer {
  padding: 20px 0 var(--fb-space-1);
  background: transparent;
  border: none;
  text-align: left;
}

/* Gestalteter Platzhalter fuer "hier ist noch nichts" und fuer die
   Fehlerseite - eine nackte Textzeile in einem grossen leeren Kasten sah aus,
   als fehle noch etwas an der Anwendung selbst. Bewusst grau/neutral: ein
   leerer Bereich ist kein Fehler. */

.fb-zustand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--fb-space-1);
  padding: 28px var(--fb-space-5);
  color: var(--fb-gray-600);
}

.fb-panel .fb-zustand {
  /* Oben Rasterabstand, unten nichts - das Panelpolster reicht (vorher 20/8,
     damit lag die Unterkante bei 33 statt 25px). */
  padding: var(--fb-space-4) 0 0;
}

.fb-zustand__icon {
  display: flex;
  margin-bottom: var(--fb-space-2);
  color: var(--fb-gray-400);
}

.fb-zustand__titel {
  margin: 0;
  font-size: var(--fb-text-l);
  font-weight: 450;
  color: var(--fb-gray-800);
}

.fb-zustand__text {
  margin: 0;
  /* Kein einzelnes Wort in der zweiten Zeile ("Führungszeugnis."); Browser
     ohne `pretty` setzen wie bisher. */
  text-wrap: pretty;
  font-size: var(--fb-text-s);
  max-width: 42ch;
}

.fb-zustand__aktion {
  margin-top: 14px;
}

/* Leiser Beisatz *innerhalb* einer Steckbrief-Zeile - Rolle einer
   erziehungsberechtigten Person, "Anschrift wie Fahrschüler". Gleiche Optik
   wie `fb-panel__beisatz`, nur als eigener Block, weil er unter dem Namen
   steht und nicht daneben. */
.fb-steckbrief__beisatz {
  display: block;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Zwei Personen in derselben Zeile brauchen einen Abstand dazwischen - ohne
   ihn lesen sich vier Zeilen wie eine Anschrift. */
.fb-steckbrief__weiterer {
  margin-top: 10px;
}

/* **Der Steckbrief in Gruppen** (dritte GUI-Runde, Vorschlag 4, 03.09.2026).
   Vorher eine zweispaltige Rinne, 132 : 934 px, acht gleichrangige Zeilen -
   ein Datenbankauszug, in dem "Berlin" 86 % der Breite trug. Jetzt drei
   Gruppen nebeneinander (Person, Kontakt, Zuordnung), je eine Spalte aus
   Fakten mit leiser Marke und tragendem Wert - derselbe Baustein wie die
   Faktenzeile der Vorgang-Ansicht (`.fb-fakt`). Drei Rollen, nicht mehr:
   Gruppentitel (Beschriftung ueber Daten), Marke (Beschriftung neben Wert),
   Wert. Unter 1100 px stapeln die Gruppen. */
.fb-steckbrief__gruppen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--fb-space-6);
}

.fb-steckbrief__gruppe {
  display: grid;
  gap: var(--fb-space-4);
  align-content: start;
}

.fb-steckbrief__gruppentitel {
  margin: 0;
  padding-bottom: var(--fb-space-2);
  border-bottom: 1px solid var(--fb-gray-100);
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-gray-600);
}

/* Letzte Feldgruppe in einem abgesetzten Kasten: ihr Bodenabstand wuerde sich
   auf das Innenpolster des Kastens draufsetzen - unten sass dadurch sichtbar
   mehr Luft als oben. */
.fb-form__klassen-gruppe > .fb-form__group:last-child {
  margin-bottom: 0;
}

/* Steht ein Panel VOR dem Formular (Mein Konto), fehlt der Abstand: .fb-panel
   bringt seinen Rand nur nach oben mit, .fb-form gar keinen. */
.fb-panel + .fb-form {
  margin-top: var(--fb-space-5);
}

/* Schnellerfassung der Fahrstunden (B3): oben Fahrlehrer und Tag, darunter
   eine einzelne Erfassungszeile, darunter die Liste des Tages. Frueher stand
   hier ein Tagesblatt mit acht festen Zeilen - siehe app/web/erfassung.py. */

.fb-tagblatt__kopf {
  display: flex;
  align-items: flex-end;
  gap: var(--fb-space-4);
  margin-bottom: 20px;
}

.fb-tagblatt__kopf .fb-form__group {
  margin-bottom: 0;
}

/* Datumsfeld zwischen den Pfeilen, alles auf einer Grundlinie. Die Gruppe soll
   als **ein** Bedienelement lesen, deshalb sitzen die Pfeile dicht am Feld.
   Ihre eigene Breite ist mit 26px ohnehin klein - die Breite kam vom Feld, das
   ohne Vorgabe 158px belegte (Browser-Eigenbreite fuer type=date). */
.fb-tagblatt__blaettern {
  display: flex;
  align-items: center;
  gap: 0;
}

.fb-tagblatt__datum {
  width: 132px;
  margin: 0 2px;
  padding-left: 10px;
  padding-right: var(--fb-space-2);
}

/* Der Fahrlehrer steht als "Nachname, Vorname (KUE)" drin und passte schon
   vorher nicht in die 175px von --mittel; seit das Auswahlfeld rechts Platz
   fuer den eigenen Pfeil reserviert, fehlten weitere 24. Hier reicht die
   Breite, weil der Kopf nur zwei Felder traegt.

   Dieselbe Auswahl steht in der Theorie-Erfassung. Dass sie dort ebenfalls
   abschnitt, war nur nicht zu sehen, solange das Feld unbelegt startete -
   mit der Vorbelegung stand "Fischer, Andreas (" in der Zeile. */
.fb-tagblatt__kopf .fb-form__group--mittel,
.fb-erfassung__fahrlehrer {
  max-width: 260px;
}

/* Reiter zwischen Fahrstunden- und Theorie-Erfassung. Bewusst schlicht: Es sind
   zwei, und sie tragen keine Zaehler oder Symbole. */
.fb-reiter {
  display: flex;
  gap: var(--fb-space-1);
  margin-bottom: 20px;
  border-bottom: 1px solid var(--fb-gray-200);
}

.fb-reiter__link {
  padding: var(--fb-space-2) 14px;
  color: var(--fb-gray-600);
  text-decoration: none;
  font-size: var(--fb-text-l);
  font-weight: 500;
  /* Die Linie sitzt auf der Trennlinie des Containers, deshalb der negative
     Rand - sonst entsteht ein Spalt zwischen Reiter und Kante. */
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
}

.fb-reiter__link:hover {
  color: var(--fb-gray-800);
}

/* Dieselbe Farbe wie die Reiter der Akte (`.fb-akte__knopf--aktiv`) - bis zum
   03.09.2026 hatten die zwei Reiterleisten zwei Rezepte. */
.fb-reiter__link--aktiv {
  color: var(--fb-accent);
  border-bottom-color: var(--fb-accent);
}

/* Theorie: Lektionsauswahl traegt Nummer und Klartext, braucht also Platz. */
.fb-theorie__lektion {
  flex: 1 1 320px;
  min-width: 260px;
}

/* Beschriftung und Filterfeld stehen **nebeneinander**, nicht an den beiden
   Enden der Zeile: Mit `space-between` schob es die Suche ueber die halbe
   Breite von dem weg, worauf sie wirkt. */
.fb-theorie__kopf {
  display: flex;
  align-items: center;
  gap: var(--fb-space-3);
  margin-bottom: var(--fb-space-2);
}

.fb-theorie__suche {
  width: 240px;
}

/* Wie viele Namen gehakt sind - leise neben der Beschriftung, gleiche Optik wie
   der Panel-Beisatz. Die Auskunft ist die Zahl, nicht das Wort davor. */
.fb-theorie__anzahl {
  margin-left: 6px;
  font-size: var(--fb-text-s);
  font-weight: 400;
  color: var(--fb-gray-600);
}


/* Die Teilnehmerliste steht vollstaendig im DOM (der Filter blendet nur aus),
   damit ein gesetzter Haken beim Tippen nicht verlorengeht. Bei 150 Schuelern
   braucht sie deshalb eine eigene Hoehe statt der ganzen Seite. */
/* Mehrspaltig: Ein Theorieabend hat schnell 20 Teilnehmer, einspaltig war
   das eine 320px hohe Rolle in einem Panel, neben dem zwei Drittel der Breite
   leer standen. `auto-fill` statt einer festen Spaltenzahl - so bleibt die
   Liste auf einem schmalen Fenster von selbst einspaltig. Grid statt
   `columns`, weil ein per x-show ausgeblendeter Eintrag (display: none) hier
   sauber herausfaellt, statt eine Luecke in der Spalte zu hinterlassen. */
/* Einspaltig. Mehrspaltig war platzsparend, aber zum Abhaken schlechter: Man
   liest von einem Papierbogen ab, und der ist eine Spalte - bei fuenf Spalten
   springt der Blick, und die Maus laeuft quer. Die Hoehe ist dafuer groesser
   als vorher, damit eine uebliche Klasse ohne Rollen hineinpasst. */
.fb-theorie__liste {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  max-height: 420px;
  overflow-y: auto;
  border: 1px solid var(--fb-gray-200);
  border-radius: var(--fb-radius);
  padding: var(--fb-space-2) var(--fb-space-3);
}

/* Der Hinweis "noch keine Fahrschueler" ist kein Listeneintrag und soll nicht
   in einer 220px-Spalte stehen. */
.fb-theorie__liste > .fb-form__hinweis {
  grid-column: 1 / -1;
}

.fb-theorie__eintrag {
  display: flex;
  padding: var(--fb-space-1) 0;
}

/* Erste Zeile **in** der Liste: ein Haken wie die anderen, nur mit besonderer
   Wirkung - deshalb abgesetzt statt hervorgehoben. */
.fb-theorie__alle {
  margin-bottom: var(--fb-space-1);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--fb-gray-100);
  color: var(--fb-gray-600);
}

/* Deutlich abgesetzt von der Erfassungszeile darueber: Die Teilnehmer sind ein
   eigener Schritt, standen aber fast an den Feldern der Zeile. */
.fb-theorie__teilnehmer {
  margin-top: var(--fb-space-5);
  margin-bottom: 20px;
}

/* Die Erfassungszeile: alle Felder nebeneinander, unten buendig, damit die
   Beschriftungen eine gemeinsame Oberkante haben und die Eingabefelder eine
   gemeinsame Grundlinie. Umbruch auf schmalen Fenstern ist gewollt - die
   Reihenfolge bleibt dabei die des Zettels. */
.fb-erfassung__zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--fb-space-3) var(--fb-space-4);
}

.fb-erfassung__zeile .fb-form__group {
  margin-bottom: 0;
}

/* Waechst als einziges Feld mit: Namen sind unterschiedlich lang, alles
   andere hat eine feste, absehbare Breite. */
.fb-erfassung__schueler {
  flex: 1 1 260px;
  min-width: 240px;
}

.fb-erfassung__art {
  width: 190px;
}

.fb-erfassung__notiz {
  flex: 1 1 150px;
  min-width: 120px;
}

.fb-erfassung__dauer-zeile {
  display: flex;
  align-items: center;
  gap: 6px;
}

.fb-erfassung__minuten {
  width: 72px;
}

.fb-erfassung__einheit {
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Kontrollkaestchen und Knopf haben keine Beschriftung ueber sich und wuerden
   sonst an der Oberkante kleben. */
.fb-erfassung__ne,
.fb-erfassung__aktion {
  padding-bottom: 9px;
}

/* Bricht die Erfassungszeile um, stand der Knopf mitten in der neuen Zeile -
   er gehoert ans Ende, wo ihn das Auge nach dem letzten Feld sucht. */
.fb-erfassung__aktion {
  margin-left: auto;
}

/* Schnellwahl-Knopf (Dauer 45/90): sieht aus wie ein Schalter, nicht wie eine
   Aktion - deshalb kleiner und ruhiger als fb-btn--secondary. */
.fb-btn--wahl {
  padding: var(--fb-space-2) 10px;
  background: #fff;
  color: var(--fb-gray-600);
  border-color: var(--fb-gray-200);
  font-variant-numeric: tabular-nums;
}

.fb-btn--wahl:hover:not(:disabled):not(.htmx-request) {
  background: var(--fb-gray-50);
}

.fb-btn--wahl-aktiv {
  background: var(--fb-accent-tint);
  color: var(--fb-accent-dark);
  border-color: var(--fb-accent);
}

/* Kein Treffer in der Auswahlliste: sichtbar machen, dass gesucht wurde und
   nichts da ist - eine leere Liste sieht sonst aus wie ein Ladefehler. */
.fb-combobox__option--leer {
  color: var(--fb-gray-600);
  cursor: default;
}

/* Amtliches Kuerzel neben der ausgeschriebenen Art in der Tagesliste. Klein und
   grau: Es ist die Zweitinformation - beim Gegenlesen des Nachweises aber genau
   die, auf die es ankommt. */
/* Die Pille - ein Nebenwert, der zum Wert davor gehoert.

   **Sie traegt nicht automatisch die Schreibmaschinenschrift** (Anlauf vom
   03.09.2026, im Bild zurueckgenommen): `.fb-kuerzel` steht auch an Woertern -
   "Schaltung", "Automatik", "§ 12 FahrlG". In Monospace sahen die aus wie
   Quelltext. Wo wirklich eine Kennung drinsteht, kommt `.fb-kennung` dazu. */
.fb-kuerzel {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: var(--fb-radius);
  background: var(--fb-flaeche-innen);
  border: 1px solid var(--fb-flaeche-rand);
  font-size: var(--fb-text-xs);
  color: var(--fb-gray-600);
  white-space: nowrap;
}

/* Eine Kennung **im Fliesstext** - Kennzeichen, Rechnungsnummer, IBAN. Ohne
   Rahmen und Flaeche: In einer Faktenzeile stuenden sonst drei Pillen
   nebeneinander, die Schrift allein reicht als Zeichen. */
/* Kein Groessenausgleich mehr (03.09.2026): `0.95em` glich SF Mono aus, das
   optisch groesser lief als Inter. Plex Mono ist auf Plex Sans abgestimmt. */
.fb-kennung {
  font-family: var(--fb-font-kennung);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* Dateiablage (B10). Dateiname und Groesse stehen als zweite, leisere Zeile
   unter der Bezeichnung - als eigene Spalten liess die Tabelle in der rechten
   Profilspalte keinen Platz mehr fuer die Aktionsspalte. */
/* Einzeilig mit Auslassung (03.09.2026): Der Dateiname brach in der schmalen
   Profilspalte auf drei Zeilen um, und die Zeile wirkte wie eine andere
   Schriftgroesse - sie war es nicht (15/13 wie ueberall), nur hoch. */
.fb-dokument__dateiname {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
  margin-top: 2px;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Das Upload-Formular sitzt im Panel und bekommt deshalb keinen eigenen
   Kasten (.fb-form waere selbst eine Karte), nur einen abgesetzten Grund. */
.fb-dokument-form {
  padding: var(--fb-space-4) 20px;
  border-bottom: 1px solid var(--fb-gray-200);
  background: var(--fb-flaeche-innen);
}

/* Reiter der Fahrschuelerakte (#58). Ersetzt die Sprungleiste: Die aenderte
   nichts an der Seitenlaenge - man sprang, aber es blieb eine Rolle Papier.

   **Heisst `fb-akte` und nicht `fb-reiter`**: Den Namen gibt es oben schon fuer
   die zwei Reiter der Erfassung, und der traegt `display: flex`. Der neue
   Container hat ihn stillschweigend geerbt - im Ergebnis stand die Reiterleiste
   neben statt ueber dem Inhalt. Im Quelltext sah alles richtig aus; gefunden
   erst beim Messen der Positionen im Browser. */
.fb-akte {
  margin-top: var(--fb-space-5);
}

.fb-akte__leiste {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--fb-gray-200);
}

.fb-akte__knopf {
  position: relative;
  padding: 10px var(--fb-space-4);
  border: none;
  background: none;
  font: inherit;
  font-size: var(--fb-text-l);
  /* Halbfett wie `.fb-reiter__link` in der Erfassung: ein Reiter ist ein
     Leitwert, in beiden Leisten. Vorher 400 hier, 500 dort. */
  font-weight: 500;
  color: var(--fb-gray-600);
  cursor: pointer;
  /* Der aktive Reiter bekommt einen Balken; die Reserve haelt die Beschriftung
     ruhig, sonst huepft die Zeile beim Wechseln um zwei Pixel. */
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

/* Anzahl am Reiter - dieselbe Zurueckhaltung wie .fb-panel__anzahl: Sie soll
   die Beschriftung ergaenzen, nicht mit ihr um Aufmerksamkeit ringen. */
.fb-akte__anzahl {
  margin-left: 6px;
  font-size: var(--fb-text-s);
  font-variant-numeric: tabular-nums;
  color: var(--fb-gray-600);
}

.fb-akte__knopf:hover {
  color: var(--fb-gray-800);
}

.fb-akte__knopf--aktiv .fb-akte__anzahl {
  color: var(--fb-accent);
}

.fb-akte__knopf--aktiv {
  color: var(--fb-accent);
  border-bottom-color: var(--fb-accent);
}

.fb-akte__knopf:focus-visible {
  outline: 2px solid var(--fb-accent);
  outline-offset: -2px;
}

/* Panels innerhalb eines Reiters stapeln mit gleichem Abstand wie sonst. */
.fb-akte [role="tabpanel"] > .fb-panel + .fb-panel {
  margin-top: var(--fb-space-5);
}

/* --- Musterseite (B12/P0b) ------------------------------------------------ */

/* Nur fuer `/stil`. Bewusst am Ende und knapp gehalten: Die Seite zeigt die
   Bausteine, sie ist keiner. Wer hier viel CSS braucht, baut gerade eine
   zweite Formsprache. */
.fb-stil__raster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-4);
  align-items: flex-start;
}

.fb-stil__zeile {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr) 12rem;
  gap: var(--fb-space-4);
  align-items: center;
  padding: var(--fb-space-2) 0;
  border-bottom: 1px solid var(--fb-gray-100);
}

.fb-stil__probe {
  display: block;
  width: 100%;
  height: var(--fb-space-6);
  border-radius: var(--fb-radius);
  border: 1px solid var(--fb-gray-200);
}

.fb-stil__farbe {
  width: 9rem;
  display: grid;
  gap: var(--fb-space-1);
  font-size: var(--fb-text-xs);
}

.fb-stil__balken {
  display: block;
  height: var(--fb-space-3);
  background: var(--fb-accent-tint);
  border: 1px solid var(--fb-accent);
  border-radius: var(--fb-radius-sm);
}

.fb-stil__rolle {
  color: var(--fb-gray-600);
  font-size: var(--fb-text-s);
}

.fb-stil__flaeche {
  display: grid;
  place-items: center;
  width: 11rem;
  height: var(--fb-space-8);
  background: #fff;
  border-radius: var(--fb-radius-lg);
  font-size: var(--fb-text-xs);
  color: var(--fb-gray-600);
}

/* --- Faktenzeile einer Ansicht (B12/P2) ----------------------------------- */

/* Die Kopfzeile einer Ansichtsseite: was den Datensatz ausmacht, waagerecht und
   ohne Formularfelder. Dasselbe Muster wie der Akten-Kopf - Trennlinie unten,
   darunter der Inhalt -, damit "das ist der Kopf" nicht zweimal gelernt werden
   muss. **Nur belegte Angaben**: Ein "Getriebe: –" ist keine Auskunft. */
.fb-fakten {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-3) var(--fb-space-6);
  padding: var(--fb-space-2) 0 var(--fb-space-5);
  border-bottom: 1px solid var(--fb-gray-200);
  margin-bottom: var(--fb-space-5);
}

.fb-fakt {
  display: grid;
  gap: var(--fb-space-1);
  align-content: start;
}

.fb-fakt__marke {
  font-size: var(--fb-text-s);
  font-weight: 500;
  color: var(--fb-gray-600);
}

.fb-fakt__wert {
  font-size: var(--fb-text-l);
  color: var(--fb-gray-800);
}

.fb-fakten__nachsatz {
  margin: calc(-1 * var(--fb-space-4)) 0 var(--fb-space-5);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

.fb-fakten__nachsatz b {
  color: var(--fb-gray-800);
  font-weight: 500;
}

/* --- Bewegung folgt der Aussage, nicht dem Baustein (03.09.2026) ------------
   Bis dahin blendeten Kacheln, Fakten und Kennzahlen beim Aufbau versetzt
   ein (`fb-einblenden`, B12/P2) - auf jeder Akte 47 animierte Elemente, im
   Fuhrpark eine Welle ueber fuenf Autos, die nichts ueber die Autos sagt.
   Dritte GUI-Runde, Vorschlag 5, entschieden und gebaut: **Bewegung nur, wo
   sie die Aussage ist.**

   | Datenlage                                  | Bewegung                    |
   | zaehlbare Pflicht oder Grenze (Fortschritt,| Welle ueber die Segmente    |
   |   Pensum)                                  |   (`fb-fuellen`, oben)      |
   | Menge ohne Ziel (Kachelgitter, Fakten,     | keine                       |
   |   Kennzahlen, Tabellen)                    |                             |
   | neu erschienenes Element                   | einmal antoenen (unten)     |
   | Auslastung                                 | Zustandsbild, kein Aufbau   |

   `fb-einblenden` samt Versatzregeln ist ersatzlos entfallen; die Kachel im
   Akten-Kopf bewegt sich weiter - ueber ihre Segmente, nicht als Kasten.
   `tests/browser/test_bewegung.py` misst: Was sich bewegt, ist ein Segment
   oder die eben erfasste Zeile, sonst nichts. */

/* **Die eben erfasste Zeile blendet einmal getoent an** (B12, zweite GUI-Runde).
   Der einzige der drei vorgeschlagenen "Charaktermomente", der einen Ort hat, an
   dem er passieren kann: Die Erfassung tauscht ihren Ausschnitt per HTMX, die
   Zeile erscheint also wirklich neu. Die beiden anderen - ein Balken, der live
   grun durchlaeuft, und ein ausgeglichener Saldo - waren keine Momente, sondern
   Anzeigeregeln auf Seiten, die komplett neu laden.

   **Nur Farbe**, kein Layout: ein wachsender Hintergrund verschoebe die Tabelle.
   Und laenger als eine halbe Sekunde waere es kein Hinweis mehr, sondern eine
   Markierung - beim Uebertragen eines Papierstapels sitzt die naechste Zeile
   schon in der Maske. */
@keyframes fb-angeblendet {
  from {
    background: var(--fb-accent-tint);
  }
  to {
    background: transparent;
  }
}

.fb-angeblendet {
  animation: fb-angeblendet 600ms var(--fb-ease) both;
}

/* --- Tagespensum (B12/P2, #63) -------------------------------------------- */

/* Eine Zeile je Grenze: Marke, Balken, Zahl, Rest. Die Marke hat eine feste
   Breite, damit die Balken untereinander an derselben Kante beginnen - ohne das
   liest man zwei Bilder statt eines. */
.fb-pensum {
  display: grid;
  gap: var(--fb-space-2);
  /* **Gedeckelt, nicht gestreckt** (02.09.2026). Über die volle Panelbreite
     gezogen standen Balken und Rest-Chip 700px auseinander - das Bild zerfiel
     in zwei Hälften, obwohl es eine Aussage ist. */
  max-width: 40rem;
  margin: var(--fb-space-4) 0;
  padding: var(--fb-space-3) var(--fb-space-4);
  background: var(--fb-flaeche-innen);
  border-radius: var(--fb-radius-lg);
}

.fb-pensum__zeile {
  display: flex;
  align-items: center;
  gap: var(--fb-space-3);
  flex-wrap: wrap;
}

.fb-pensum__marke {
  flex: 0 0 4.5rem;
  font-size: var(--fb-text-s);
  /* Beschriftung neben Wert, wie die Balkenbeschriftung in der Kachel
     (`.fb-fortschritt__kopf`) - vorher 400 hier, 500 dort. */
  font-weight: 500;
  color: var(--fb-gray-600);
}

/* Der Balken nimmt die Breite, die Marke, Wert und Rest uebrig lassen -
   mindestens 8rem, sonst sagt eine Skala nichts mehr. */
.fb-pensum__balken {
  flex: 1 1 8rem;
  min-width: 8rem;
}

.fb-pensum__wert {
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
  font-variant-numeric: tabular-nums;
}

.fb-pensum__wert strong {
  color: var(--fb-gray-800);
}

/* Der Rest ist die eigentliche Antwort auf "darf ich heute noch?" - deshalb
   als Chip und nicht als vierter Satzteil. */
.fb-pensum__rest {
  margin-left: var(--fb-space-2);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
  background: #fff;
  border-radius: var(--fb-radius-sm);
  padding: 0 var(--fb-space-2);
  line-height: 1.6;
}

/* --- Die Auslastungsskala: neutral -> amber -> rot (03.09.2026) -----------
   Fuer alles, was eine **Grenze** zaehlt statt einer Pflicht: das Tagesmass
   in der Erfassung, auf der Uebersicht und in der Fahrlehrer-Kachel. Kein
   Gruen am unteren Ende (ein Fahrlehrer bei 20 % hat nichts erfuellt), amber
   ab 80 %, **Rot erst beim Ueberschreiten** - das ist ein Regelverstoss nach
   § 12 FahrlG, und dort ist Rot richtig; die Farbregel bleibt unangetastet.

   **Seit dem 03.09.2026 als Skala, nicht als Segmente** (Sven, am Bild):
   Segmente sagen "zaehle mich" - das passt zur Pflichtzahl. Die Auslastung
   zeigt einen Zustand auf einer Skala mit zwei Schwellen, und genau die
   stehen als Marken im Balken (80 % und das Tagesmass). Ueberschreitung
   laeuft ueber das Ende hinaus. Kein Aufbaueffekt: Ein Zustand hat keinen
   Anlauf (Bewegungsregel). Die Stufe rechnet der Server
   (`auslastungsstufe` in tagesnachweis.py). */
.fb-skala {
  position: relative;
  height: 10px;
  border-radius: 999px;
  background: var(--fb-gray-200);
  /* Platz fuer den Ueberlauf: Bei 585 von 495 Minuten lief das Rot in die
     Zahl daneben (Erfassung, 03.09.2026). Die Bahn endet 32px vor dem Rand,
     der Ueberlauf darf hoechstens so weit - er zeigt "darueber", nicht wie
     weit. */
  margin-right: var(--fb-space-6);
}

.fb-skala__fuellung {
  height: 100%;
  border-radius: 999px;
  background: var(--fb-accent);
  width: var(--fb-skala-anteil, 0%);
  max-width: 100%;
}

.fb-skala--amber .fb-skala__fuellung {
  background: var(--fb-warning);
}

.fb-skala--rot .fb-skala__fuellung {
  background: var(--fb-danger);
}

.fb-skala__marke {
  position: absolute;
  top: -4px;
  width: 2px;
  height: 18px;
  background: var(--fb-gray-400);
}

.fb-skala__marke--ende {
  background: var(--fb-gray-800);
}

/* Was ueber das Tagesmass hinausgeht, laeuft rechts ueber das Ende hinaus -
   halb gedeckt, damit die Marke darunter sichtbar bleibt. */
.fb-skala__ueberlauf {
  position: absolute;
  left: 100%;
  top: 0;
  height: 100%;
  width: var(--fb-skala-ueber, 0%);
  max-width: var(--fb-space-6);
  background: var(--fb-danger);
  border-radius: 0 var(--fb-radius) var(--fb-radius) 0;
  opacity: 0.55;
}

.fb-skala-zeile--amber .fb-pensum__rest,
.fb-skala-zeile--amber .fb-fortschritt__zahl {
  color: var(--fb-warning-text);
}

.fb-skala-zeile--rot .fb-pensum__rest,
.fb-skala-zeile--rot .fb-fortschritt__zahl {
  color: var(--fb-danger);
}

/* Die kompakte Skala in einer Kachel: Marke und Zahl in einer Zeile, der
   Balken darunter - dieselbe Anordnung wie ein Pflichtzahlen-Balken. */
.fb-skala-kompakt .fb-skala {
  margin-top: var(--fb-space-2);
}

.fb-pensum__fuss {
  margin: 0;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* --- Merkliste: Hinweise stichwortartig (B12/P2) -------------------------- */

/* **Ein Hinweis, den niemand liest, hilft niemandem.** Die Erklaerungen unter
   den Feldern waren ausformulierte Absaetze - fachlich richtig, in der Maske
   drei Zeilen Fliesstext. Hier steht je Gedanke eine Zeile, das Stichwort
   vorn und fett, der Rest dahinter. Wer die Regel kennt, ueberspringt sie am
   Stichwort; wer sie nicht kennt, liest eine Zeile statt eines Absatzes. */
.fb-merkliste {
  list-style: none;
  margin: var(--fb-space-2) 0 0;
  padding: 0;
  display: grid;
  gap: var(--fb-space-1);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* **Nach einer Merkliste folgt oft direkt ein Formular.** Die Liste bringt
   keinen Fussabstand mit - sie steht meist als Letztes in einem Panel -, und
   `.fb-form__group` bringt keinen Kopfabstand mit. Zusammen klebten Erklaerung
   und Eingabefeld aneinander (0 px, nachgemessen am Storno der Rechnung).
   `.fb-form__actions` ist ausgenommen: Die Klasse hat ihren Abstand selbst,
   sonst stuenden dort 48 statt 24 px. */
.fb-merkliste + form:not(.fb-form__actions),
.fb-merkliste + [x-data] {
  margin-top: var(--fb-space-5);
}

/* Der Loeschen-Knopf klebte an der Merkliste (Sven, 03.09.2026: "zu nah am
   Text"): `loeschen_dialog` wickelt sein Formular in ein `x-data`-Div, und
   die Regel darueber traf nur das nackte Formular - Archivieren hatte 24px,
   Loeschen 0. Und in der Fahrschule-Maske stand die naechste Feldbeschriftung
   ohne Abstand unter der Merkliste. */
.fb-merkliste + .fb-form__group {
  margin-top: var(--fb-space-4);
}

/* Dasselbe fuer den Loeschen-Dialog hinter einem Hinweis-Absatz (Fahrlehrer,
   Fahrzeug): 6px Absatzrand sind kein Abstand zu einem roten Knopf. */
.fb-form__hinweis + [x-data] {
  margin-top: var(--fb-space-4);
}

/* **Die Marke liegt daneben, nicht davor.** Zwei Anlaeufe kostete das: Als Flex-
   und als Grid-Zeile wurden `<b>` und der Text dahinter zu *getrennten*
   Elementen - im Raster landete der Text sogar in der 3px-Spalte und brach nach
   jedem Wort um. Absolut positioniert bleibt die Zeile eine Zeile Text. */
.fb-merkliste li {
  text-wrap: pretty;
  position: relative;
  padding-left: var(--fb-space-3);
  line-height: var(--fb-leading);
}

/* Der Akzent traegt keine Aussage - er ist die Aufzaehlungsmarke. Deshalb
   dieselbe gedeckte Farbe wie die Fortschrittssegmente und kein Statuston. */
.fb-merkliste li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3em;
  bottom: 0.3em;
  width: 3px;
  /* Pille statt 2px: Auf einem 3px breiten Balken ist das dasselbe Bild und
     spart eine Radius-Stufe, die genau hier ihren einzigen Nutzer haette. */
  border-radius: 999px;
  background: var(--fb-gray-300);
}

.fb-merkliste b {
  color: var(--fb-gray-800);
  font-weight: 500;
}

/* --- Akten-Kopf, Entwurf (B12/P1) ----------------------------------------- */

/* Der Akten-Kopf: Identitaetszeile und Kachelreihe. Die Wahl fiel am
   02.09.2026 auf Fassung B; die Entwurfsseite `/stil/akte`, auf der drei
   Fassungen nebeneinander standen, ist mit der Entscheidung geloescht worden.
   Das Muster gilt seither auch fuer Fahrlehrer, Fahrzeug und Rechnung. */

.fb-akte__kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--fb-space-5);
  padding: var(--fb-space-4) 0 var(--fb-space-5);
  /* Die Kopflinie traegt die Marke (Fassung C) - eine Linie, einmal je Akte. */
  border-bottom: 1px solid var(--fb-marke);
  margin-bottom: var(--fb-space-5);
}

.fb-akte__name {
  display: flex;
  align-items: center;
  gap: var(--fb-space-3);
  margin: 0;
  font-size: var(--fb-text-2xl);
  /* **Ausdruecklich 600, nicht der h1-Vorgabewert 700.** Die Schrift liegt in drei
     Schnitten vor (400/500/600); ohne diese Zeile fettete der Browser den Namen
     synthetisch - dieselbe matschige Fette, die am <strong> schon einmal
     behoben wurde (tokens.css). Auf der Rechnung traf es zusaetzlich die
     Nummer in der Schreibmaschinenschrift. Gefunden in der vierten Durchsicht
     (03.09.2026), seither misst `tests/browser/test_schrift.py` jeden Schnitt
     nach. */
  font-weight: 600;
  letter-spacing: var(--fb-tracking-eng);
  line-height: var(--fb-leading-tight);
}

/* Die Zweitangaben in **einer** Zeile statt als Liste: Wer die Akte oeffnet,
   liest sie nicht, er ueberfliegt sie. Als <dl> brauchten sie sechs Zeilen. */
.fb-akte__fakten {
  margin: var(--fb-space-2) 0 0;
  color: var(--fb-gray-600);
  font-size: var(--fb-text-l);
}

.fb-akte__trenner {
  color: var(--fb-gray-400);
  padding: 0 var(--fb-space-1);
}

/* **`.fb-kennzahl` und `.fb-kennzahl__wert` gab es schon** (Finanzen-Seite) -
   im Entwurf standen sie hier ein zweites Mal und haetten die Kacheln dort
   still umgestellt. Geblieben sind nur die Farbmodifikatoren: Die Farbe traegt
   die Aussage, Rot waere hier falsch - ein offener Saldo ist kein Fehler. */
.fb-kennzahl__wert.fb-kennzahl--offen {
  color: var(--fb-warning);
}

.fb-kennzahl__wert.fb-kennzahl--gut {
  color: var(--fb-success);
}

.fb-kennzahl__wert.fb-kennzahl--leise {
  font-size: var(--fb-text-xl);
  color: var(--fb-gray-600);
}

.fb-kachelreihe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fb-space-4);
  margin-bottom: var(--fb-space-5);
}

/* **Der Deckel gehoert an die Reihe, nicht an die Kachel.** Ohne `max-width`
   zog eine einzelne Klasse ihre Kachel auf die volle Breite - Beschriftung
   links, Zahl ganz rechts, dazwischen nichts; der haeufigste Fall ist eine
   Klasse, nicht drei. Im Gitter unten bestimmt dagegen die Spaltenbreite, und
   ein Deckel liesse dort Luecken. */
.fb-kachelreihe > .fb-kachel {
  max-width: 22rem;
}

/* Kachelgitter fuer Listen (B12/P3): Fahrlehrer und Fuhrpark. Beide haben
   wenige Eintraege mit je einer Handvoll Angaben - eine Tabelle mit sechs
   Spalten fuer acht Zeilen ist dort mehr Geruest als Inhalt. Die
   Fahrschuelerliste bleibt Liste: Sie wird ueberflogen, gefiltert und
   durchsucht, und dafuer sind Spalten das bessere Werkzeug. */
.fb-kachelgitter {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: var(--fb-space-4);
  align-items: start;
}

.fb-kachel__kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fb-space-3);
  margin-bottom: var(--fb-space-2);
}

.fb-kachel__name {
  margin: 0;
  font-size: var(--fb-text-l);
  font-weight: 450;
  color: var(--fb-gray-800);
  line-height: var(--fb-leading-tight);
}

.fb-kachel__zeile {
  margin: var(--fb-space-2) 0 0;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Inaktive stehen mit in der Liste, aber leiser - sie sind der Ausnahmefall,
   nach dem gesucht wird, nicht der, den man ueberfliegt. */
.fb-kachel--leise {
  background: var(--fb-gray-50);
}

.fb-kachel {
  flex: 1 1 14rem;
  background: var(--fb-flaeche);
  border: 1px solid var(--fb-flaeche-rand);
  border-radius: var(--fb-radius-lg);
  box-shadow: var(--fb-flaeche-schatten);
  padding: var(--fb-space-4);
}

.fb-kachel--zahl {
  flex: 0 1 11rem;
  display: grid;
  gap: var(--fb-space-2);
  align-content: start;
}

/* **Zwei Zahlen teilen sich die Hoehe einer Klassenkachel.** Nebeneinander
   waren beide 249px hoch fuer zwei Textzeilen (nachgemessen: 66-70% leer) -
   der Flexbox-Standard `stretch` zieht jede Kachel auf die Hoehe der hoechsten.
   Uebereinander wachsen sie mit dem Inhalt und die Reihe bleibt geschlossen. */
.fb-kachelreihe__zahlen {
  flex: 0 1 11rem;
  display: grid;
  gap: var(--fb-space-4);
  align-content: stretch;
}

.fb-kachelreihe__zahlen .fb-kachel--zahl {
  flex: none;
}

/* **Die ganze Kachel ist der Link.** Die Technik ist der Stretched
   Link aus der Tabelle - entscheidend ist aber das `position: relative` hier:
   Ohne positionierten Vorfahren spannt sich das `::after` ueber die **ganze
   Seite**. Genau so am 02.09.2026 passiert, weil `.fb-table__link` in die
   Kachel uebernommen wurde, ohne die `.fb-table__row` mitzunehmen, auf die es
   sich bezieht: Der Mauszeiger war auf der halben Akte eine Hand, und jeder
   Klick landete im letzten Ausbildungsvorgang. Abgesichert durch
   `tests/browser/test_bedienelemente.py`. */
.fb-kachel--klickbar {
  position: relative;
  transition:
    border-color var(--fb-dauer-schnell) var(--fb-ease),
    box-shadow var(--fb-dauer-schnell) var(--fb-ease);
}

.fb-kachel--klickbar:hover {
  border-color: var(--fb-gray-300);
  box-shadow: var(--fb-shadow-2);
}

/* Die Tastatur sieht sonst nichts: Der Rahmen liegt am Link, sichtbar werden
   soll die Kachel. */
.fb-kachel--klickbar:focus-within {
  outline: 2px solid var(--fb-accent);
  outline-offset: 2px;
}

.fb-kachel__ziel {
  color: inherit;
  text-decoration: none;
}

/* Scoped auf `--klickbar` - dort steht das `position: relative`, siehe oben. */
.fb-kachel--klickbar .fb-kachel__ziel::after {
  content: "";
  position: absolute;
  inset: 0;
}

.fb-kachel--klickbar:hover .fb-kachel__ziel {
  text-decoration: underline;
}

/* Dieselbe Rolle wie ein Spaltenkopf - eine Beschriftung, keine Aussage -
   und deshalb dieselbe Behandlung. */
.fb-kachel__marke {
  display: block;
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-gray-600);
  margin-bottom: var(--fb-space-3);
}

.fb-kachel__inhalt {
  display: grid;
  gap: var(--fb-space-2);
}

.fb-stil__fassung {
  margin: var(--fb-space-7) 0 var(--fb-space-2);
  font-size: var(--fb-text-xl);
}

.fb-kachel__stand {
  margin: 0;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* --- Die Anmeldungs-Karte im Ausbildung-Reiter (B12, zweite GUI-Runde) ------
   Eine Karte je Anmeldung, darin eine Zeile je Klasse. Sie loest vier Panels
   ab - Vertraege, Ausbildungsvorgaenge, "Ausbildungsstand im Einzelnen" und
   den Vorbesitz -, von denen zwei dieselben Klassen trugen.

   **Die Flaeche ist die des Panels**, nicht eine zweite eigene: `.fb-panel`
   bleibt am Element stehen, hier kommt nur die innere Ordnung dazu. Es gibt
   ohnehin schon drei Rezepte fuer dieselbe weisse Flaeche (Befund der zweiten
   Durchsicht) - ein viertes waere die falsche Richtung. */

.fb-anmeldung__kopf {
  display: flex;
  align-items: baseline;
  gap: var(--fb-space-3);
  margin-bottom: var(--fb-space-3);
}

.fb-anmeldung__titel {
  margin: 0;
  font-size: var(--fb-text-xl);
  font-weight: 600;
  color: var(--fb-gray-800);
}

/* Der Beisatz nimmt den Platz zwischen Titel und Stift ein, damit der Knopf
   rechts steht - ohne `margin-left: auto` am Knopf, das den Chip im
   Tagespensum 700px von seinem Balken weggeschoben hat. */
.fb-anmeldung__beisatz {
  flex: 1;
  margin: 0;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Der Trenner gehoert zwischen zwei Beisaetze, nicht vor den ersten. Von Hand
   im Template gesetzt stand er genau dort, sobald der Teil davor entfiel - und
   der entfaellt im Normalfall (Anmeldung und Unterschrift am selben Tag). */
.fb-anmeldung__beisatz > span + span::before {
  content: "\00b7";
  margin: 0 var(--fb-space-2);
  color: var(--fb-gray-400);
}

/* Kein Fehler, sondern etwas zu tun: Alex meldet nach einer WhatsApp-Nachricht
   vorab an, die Unterschrift kommt Tage spaeter. Amber, nie rot. Der
   *-text-Ton, weil das hier 13px-Schrift ist (WCAG AA, siehe tokens.css). */
.fb-anmeldung__offen {
  color: var(--fb-warning-text);
}

/* Der aufgehobene Vertrag bleibt stehen - er war unterschrieben und damit
   rechtlich bindend. Leise statt weg: Gesucht wird er, ueberflogen nicht. */
.fb-anmeldung--leise {
  background: var(--fb-gray-50);
}

/* Der Hintergrund allein traegt zu wenig - er unterscheidet sich um zwei
   Graustufen vom Seitengrund. Die Ueberschrift macht den Unterschied hoerbar,
   ohne ein Etikett dafuer zu brauchen. */
.fb-anmeldung--leise .fb-anmeldung__titel {
  color: var(--fb-gray-600);
  font-weight: 500;
}

.fb-anmeldung__aufgehoben {
  margin: 0 0 var(--fb-space-3);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Die Klassenzeilen ziehen wie eine randlose Tabelle bis an die Panelkante -
   dieselbe Rechnung wie `.fb-panel__tabelle`, damit die Trennlinien die ganze
   Karte queren statt in der Luft zu enden. */
.fb-anmeldung__klassen {
  margin: 0 calc(-1 * var(--fb-space-5)) calc(-1 * var(--fb-space-5));
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--fb-gray-200);
}

/* **Ein gedehnter Link braucht einen positionierten Vorfahren** - hier die
   Zeile selbst. Ohne sie spannt sich das `::after` ueber die ganze Seite
   (genau so am 02.09.2026 passiert, siehe oberflaeche.md). */
.fb-anmeldung__klasse {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--fb-space-3);
  padding: var(--fb-space-3) var(--fb-space-5);
  border-bottom: 1px solid var(--fb-gray-100);
  transition: background-color var(--fb-dauer-schnell) var(--fb-ease);
}

.fb-anmeldung__klasse:last-child {
  border-bottom: none;
}

.fb-anmeldung__klasse:hover {
  background: var(--fb-gray-50);
}

.fb-anmeldung__klasse:focus-within {
  outline: 2px solid var(--fb-accent);
  outline-offset: -2px;
}

/* `min-width` haelt die Fakten aller Zeilen in einer Flucht - ohne sie beginnt
   die Zeile nach "B" 13px weiter links als die nach "B196", und die Karte liest
   sich zackig. Nachgemessen: der breiteste vorkommende Kurzname ist "B196"
   (4 Zeichen), das sind 2,4rem; 3rem laesst Luft fuer eine Klasse mehr. */
.fb-anmeldung__ziel {
  min-width: 3rem;
  color: var(--fb-gray-800);
  font-weight: 450;
  text-decoration: none;
  white-space: nowrap;
}

/* Scoped auf die Zeile - dort steht das `position: relative`, siehe oben. */
.fb-anmeldung__klasse .fb-anmeldung__ziel::after {
  content: "";
  position: absolute;
  inset: 0;
}

.fb-anmeldung__klasse:hover .fb-anmeldung__ziel {
  text-decoration: underline;
}

/* Die Fakten schieben Badge und Pfeil an den rechten Rand und tragen den
   Zeilenumbruch, wenn es eng wird. */
.fb-anmeldung__fakten {
  flex: 1;
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

.fb-anmeldung__pfeil {
  display: flex;
  color: var(--fb-gray-400);
}

/* Kopfzeile eines Reiters ohne umschliessendes Panel: Ueberschrift links,
   Aktionen rechts - dieselbe Aufteilung wie `.fb-panel__kopf`, nur eine Etage
   hoeher. Gebraucht, seit der Ausbildung-Reiter aus mehreren Karten besteht
   statt aus einem Panel. */
.fb-reiterkopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fb-space-4);
  margin-top: var(--fb-space-5);
}

/* **Der Banner klebt sonst am Kopf** - 0px nach oben, 24 nach unten
   (nachgemessen). Genau derselbe Fehler stand schon einmal zwischen zwei
   Panels: `.fb-hinweis-banner` bringt nur einen Fussabstand mit, weil er sonst
   *in* einem Panel sitzt. Hier steht er zwischen zwei Bloecken und braucht
   beides. */
/* Auch hinter dem zugeklappten Anmeldeformular (F7): Es steht zwischen
   Reiterkopf und Banner, und der Banner haette sonst wieder 0 px Abstand. */
.fb-reiterkopf + .fb-hinweis-banner,
.fb-eingebettet + .fb-hinweis-banner {
  margin-top: var(--fb-space-5);
}

.fb-reiterkopf__titel {
  margin: 0;
  font-size: var(--fb-text-xl);
  font-weight: 600;
  color: var(--fb-gray-800);
}

/* --- Weniger Bewegung: eine Stelle statt drei (04.09.2026) ------------------
   Bis dahin standen drei `prefers-reduced-motion`-Bloecke im Stil, je einer
   am Baustein - und der fuer die Kachel griff nicht: Die Versatzregeln
   (`.fb-kachel:nth-child(n)`) stehen dahinter, und im Browser liefen unter
   `reduce` weiterhin fuenf Kacheln je Akte an. Nachgemessen in der vierten
   GUI-Durchsicht, nachdem die zweite den Block als "nicht geprueft" gefuehrt
   hatte. Deshalb jetzt **eine** Regel fuer alles, mit `!important`, weil sie
   gegen jede Spezifitaet gewinnen muss - Bewegung ist in Fahrbase ueberall
   Zugabe, die Anzeige ist ohne sie vollstaendig (Fortschritt, Einblenden,
   Antoenen). `tests/browser/test_bewegung.py` misst es. */
@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation: none !important;
  }
}

/* --- Tastaturfokus (vierte Durchsicht) ---------------------------------------
   Felder zeigen ihren Ring bei jedem Fokus (auch per Maus - dort ist er die
   Eingabemarke). Knoepfe und Links hatten gar keinen und bekamen den des
   Browsers; jetzt einen eigenen, und nur, wenn die Tastatur fokussiert hat -
   wer klickt, braucht keinen Ring um den geklickten Knopf. */
.fb-btn:focus-visible,
a:focus-visible {
  outline: 2px solid var(--fb-accent);
  outline-offset: 2px;
}

/* Eingebettete Masken in der Akte (F7, 03.09.2026): Anmeldung, Vorbesitz und
   Zahlung klappen im Reiter auf statt eine Seite mit 500 px Leere zu oeffnen.
   Das Formular ist selbst eine Karte - deshalb kein Panel darum. */
.fb-eingebettet {
  /* Luft nach oben: Das aufgeklappte Formular klebte am Reiterkopf (Sven,
     03.09.2026: "noch nicht so geschmeidig vom Gefuehl / Abstand"). */
  margin: var(--fb-space-4) 0 var(--fb-space-5);
}

/* In einem Panel oder einer Karte (Anmeldung bearbeiten, Fahrstunde in der
   Akte): kein Kasten im Kasten - das Formular verliert Rahmen und Polster und
   setzt sich mit einer Linie ab. */
.fb-panel > .fb-eingebettet {
  margin: var(--fb-space-3) 0 var(--fb-space-4);
  padding-top: var(--fb-space-4);
  border-top: 1px solid var(--fb-gray-100);
}

.fb-panel > .fb-eingebettet > .fb-form {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  background: transparent;
}

.fb-eingebettet__mehr {
  margin: var(--fb-space-3) 0 0;
}

/* Ein Knopf, der etwas aufgeklappt hat, sieht gedrueckt aus - so erkennt man,
   wohin das Formular gehoert. */
.fb-btn--secondary[aria-expanded="true"],
.fb-btn--zeile-stumm[aria-expanded="true"] {
  background: var(--fb-gray-100);
  border-color: var(--fb-gray-300);
}

/* Die Erfassungszeile in der Akte: Tag und Fahrlehrer stehen als Reihe
   darueber, mit dem Abstand einer Feldgruppe. */
.fb-erfassung--akte .fb-erfassung__rahmen {
  margin-bottom: var(--fb-space-3);
}

/* Gruppen in einer Kachelliste (Fuhrpark: Autos, Motorraeder, Lkw ...):
   Beschriftung ueber Daten, wie im Steckbrief und in den Masken. */
.fb-listengruppe + .fb-listengruppe {
  margin-top: var(--fb-space-6);
}

.fb-listen-anzahl + .fb-listengruppe {
  margin-top: var(--fb-space-4);
}

.fb-listengruppe__titel {
  margin: 0 0 var(--fb-space-3);
  padding-bottom: var(--fb-space-2);
  border-bottom: 1px solid var(--fb-gray-100);
  font-size: var(--fb-text-xs);
  font-weight: 600;
  letter-spacing: var(--fb-tracking-weit);
  text-transform: uppercase;
  color: var(--fb-gray-600);
}

/* Die Fahrzeugauswahl traegt seit dem 03.09.2026 den Namen statt des
   Kennzeichens ("VW Golf VIII · Schaltung (DGF-FS 100)") - 175px (--mittel)
   schnitten ihn ab. */
.fb-erfassung__fahrzeug {
  flex: 1 1 14rem;
  min-width: 14rem;
}

/* Der Satz unter der Frage im Dialog (Verwerfen-Frage): leiser als die Frage. */
.fb-dialog__text {
  margin: calc(-1 * var(--fb-space-2)) 0 var(--fb-space-4);
  font-size: var(--fb-text-s);
  color: var(--fb-gray-600);
}

/* Sortierbare Spaltenkoepfe (03.09.2026): der Kopf bleibt Kopf (versal, Grau
   600), nur der Zeiger und der Pfeil verraten den Link. */
.fb-sortkopf {
  color: inherit;
  text-decoration: none;
}

.fb-sortkopf:hover {
  color: var(--fb-accent);
}

.fb-sortkopf--aktiv {
  color: var(--fb-gray-800);
}

.fb-sortkopf__pfeil {
  display: inline-block;
  width: 1em;
  margin-left: var(--fb-space-1);
  text-align: center;
}
