/* AutoView Web — minimales Stylesheet (Etappe W1, bewusst ohne Framework).
   Nur Grundlayout: Kopfzeile, Inhaltsbereich, schlichte Tabellen. */

:root {
  --farbe-kopf: #1f3a5f;
  --farbe-linie: #d0d4da;
  --farbe-text: #1c1e21;
  /* Trennlinie ZWISCHEN den thematischen Spaltengruppen der BWA
     (Gesamt | Marke 1 | Marke 2 | …): bewusst kraeftig und nahezu
     schwarz — sie muss auch ueber dem hinterlegten Vorjahresstreifen
     und im Sticky-Kopf klar erkennbar bleiben. */
  --farbe-gruppenlinie: #1c1e21;
  /* Abteilungsfarben (Durchgang: Farbkonzept) — EINE Quelle in
     kerndaten/farben.py, hier gespiegelt (test_farben haelt beide
     gleich). Je Abteilung KRAEFTIG (Trennbalken/-linien UND Schrift der
     Abteilungs-Ueberschriften, Durchgang F), PASTELL (Flaechen),
     PASTELL-HELL (Kennzahlen-Zeilen, Durchgang E — heller als das
     normale Pastell) und MITTEL (Abteilungs-Ueberschriftszeilen,
     Durchgang F — dunkler als Pastell, KRAEFTIG-Schrift darauf lesbar).
     ET-Kraeftig auf #8a6000 gesetzt (dunkleres Ocker), damit die
     Ueberschriftschrift lesbar bleibt. Zuordnung ueber Bereichs-Kennung. */
  --abt-NW-kraeftig: #1e5fa8; --abt-NW-pastell: #eaf1f9; --abt-NW-pastell-hell: #f5f9fd; --abt-NW-mittel: #cedcec;
  --abt-GW-kraeftig: #1f7a3d; --abt-GW-pastell: #eaf5ee; --abt-GW-pastell-hell: #f5faf6; --abt-GW-mittel: #cee2d4;
  --abt-KD-kraeftig: #b02a2a; --abt-KD-pastell: #faeceb; --abt-KD-pastell-hell: #fdf6f5; --abt-KD-mittel: #eed0d0;
  --abt-ET-kraeftig: #8a6000; --abt-ET-pastell: #fbf5e2; --abt-ET-pastell-hell: #fdfaf1; --abt-ET-mittel: #ebe1cc;
  --abt-NT-kraeftig: #a8309f; --abt-NT-pastell: #f8ecf7; --abt-NT-pastell-hell: #fcf6fb; --abt-NT-mittel: #ecd1ea;
  --abt-GU-kraeftig: #5b6470; --abt-GU-pastell: #f0f2f4; --abt-GU-pastell-hell: #f8f9fb; --abt-GU-mittel: #dbdde0;
  --objektiv-hintergrund: #cfe6d8;
  --objektiv-linie: #2f7d4f;
  /* Feste Hoehe der App-Kopfzeile: noetig, damit der sticky Tabellenkopf
     der BWA-Liste exakt darunter andockt (top-Offset = diese Hoehe). */
  --hoehe-kopfzeile: 2.8rem;
  /* Aktuelle Hoehe der (sticky) Filterleiste — von bwa.js gemessen und
     gesetzt (variabel, weil zweizeilig und responsiv umbrechend);
     0, solange keine Filterleiste da ist. Der Tabellenkopf dockt unter
     App-Kopfzeile + Filterleiste an (Punkt 3). */
  --hoehe-filter: 0px;
  /* Einheitlicher Sticky-Kopfbereich (Durchgang K): Statuszeile und
     Klapp-/Kennzahlen-Leiste kleben jetzt in ALLEN drei Ansichten mit —
     ihre (variablen, responsiv umbrechenden) Hoehen misst bwa.js. EINE
     Offset-Quelle: jede Leiste dockt unter der Summe der Leisten darueber,
     der Tabellenkopf unter allen (App-Kopfzeile + Filter + Status +
     Klappleiste). 0, solange die jeweilige Leiste fehlt. */
  --hoehe-status: 0px;
  --hoehe-klappleiste: 0px;

  /* ---------------------------------------------------------------
     Durchgang AQ — Gestaltungswerte aus Andreas' Entwurf
     (design/redesign_andreas_2026-08.htm, <style id="kt-redesign-2026">).
     Werte 1:1 uebernommen; Abweichungen sind im Abschlussbericht des
     Durchgangs aufgefuehrt.
     --------------------------------------------------------------- */
  --kt-bg: #f2f3f8;
  --kt-surface: #ffffff;
  --kt-surface-2: #f8f9fc;
  --kt-border: #e6e8f2;
  --kt-border-soft: #eef0f7;
  --kt-text: #1f2333;
  --kt-text-soft: #5c6178;
  --kt-text-faint: #9297ab;
  --kt-radius-sm: 8px;
  --kt-radius: 14px;
  --kt-radius-lg: 20px;
  --kt-shadow-sm: 0 1px 2px rgba(24, 26, 45, .05);
  /* Feinschliff Erweiterung 5 — zwei Stufen fuer BEDIENELEMENTE.
     Eigene Tokens, weil --kt-shadow-sm (Alpha .05) dafuer messbar zu
     schwach ist: gegen die Kachelflaeche kam es auf 0,8 % abweichende
     Pixel bei hoechstens 9 von 255 je Kanal — am Bildschirm nicht
     wahrnehmbar. .09 trifft den abgestimmten Richtwert (0 1px 2px
     rgba(0,0,0,.08)), nur im blauschwarzen Ton der uebrigen Schatten.
     Der Sprung auf --kt-shadow (0 10px 28px) scheidet aus: das ist ein
     KARTEN-Schatten, das Control wuerde abheben statt sich anzuheben. */
  --kt-shadow-control: 0 1px 2px rgba(24, 26, 45, .09);
  --kt-shadow-anheben: 0 2px 5px rgba(24, 26, 45, .14);
  --kt-shadow: 0 10px 28px -10px rgba(24, 26, 45, .14), 0 2px 8px -2px rgba(24, 26, 45, .06);
  --kt-shadow-lg: 0 20px 45px -12px rgba(24, 26, 45, .20);
  --kt-accent: #4c5eea;
  --kt-accent-2: #7c6cf0;
  --kt-accent-soft: #edeffd;
  --kt-pos: #12946b;
  --kt-neg: #d84b5c;
  --kt-font: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --kt-font-display: "Inter Tight", var(--kt-font);

  /* Unternehmensbereiche */
  --kt-nw: #4a63f0; --kt-nw-bg: #eef1ff; --kt-nw-bg-strong: #e2e7ff;
  --kt-gw: #0fa787; --kt-gw-bg: #e7faf4; --kt-gw-bg-strong: #d7f5ea;
  --kt-kd: #9251e0; --kt-kd-bg: #f4eefe; --kt-kd-bg-strong: #ebe0fc;
  --kt-et: #dd8a1f; --kt-et-bg: #fdf3e3; --kt-et-bg-strong: #fbe7c6;
  --kt-nt: #de5590; --kt-nt-bg: #fdeef4; --kt-nt-bg-strong: #fbdfeb;
  --kt-gu: #52525b; --kt-gu-bg: #f1f1f3; --kt-gu-bg-strong: #e4e4e8;

  /* DB-Stufenflaechen je Bereich als FESTE Werte (OnePager-Angleichung).
     Die Web-BWA mischt dieselben Toene zur Laufzeit per color-mix
     (.bwa-zeile.kt-db-N, Bereichsfarbe zu 34/23/14/8 % auf Weiss). Das
     geht im PDF nicht: WeasyPrint kennt color-mix nicht und liesse die
     Flaechen weg — der OnePager-Export braucht deshalb ausgerechnete
     Werte, und Bildschirm und Druck muessen dieselben benutzen.

     Die Werte sind die lineare sRGB-Mischung Bereichsfarbe x Anteil auf
     Weiss, also exakt das, was color-mix liefert (im Browser
     gegengeprueft: NW-1 = color(srgb 0.758667 …) = 193 = 0xc1). Ein Test
     rechnet sie aus den Basisfarben nach — sie koennen nicht stillschweigend
     von der BWA abweichen.

     Die BWA selbst bleibt bei color-mix; sie wird hier nicht angefasst. */
  --kt-db-nw-1: #c1cafa; --kt-db-nw-2: #d5dbfc; --kt-db-nw-3: #e6e9fd; --kt-db-nw-4: #f1f3fe;
  --kt-db-gw-1: #ade1d6; --kt-db-gw-2: #c8ebe3; --kt-db-gw-3: #ddf3ee; --kt-db-gw-4: #ecf8f5;
  --kt-db-kd-1: #dac4f4; --kt-db-kd-2: #e6d7f8; --kt-db-kd-3: #f0e7fb; --kt-db-kd-4: #f6f1fd;
  --kt-db-et-1: #f3d7b3; --kt-db-et-2: #f7e4cb; --kt-db-et-3: #faefe0; --kt-db-et-4: #fcf6ed;
  --kt-db-nt-1: #f4c5d9; --kt-db-nt-2: #f7d8e5; --kt-db-nt-3: #fae7ef; --kt-db-nt-4: #fcf1f6;
  --kt-db-gu-1: #c4c4c7; --kt-db-gu-2: #d7d7d9; --kt-db-gu-3: #e7e7e8; --kt-db-gu-4: #f1f1f2;

  /* Kostenblöcke */
  --kt-fix: #c07208; --kt-fix-bg: #fff6e6; --kt-fix-border: #f2d69f;
  --kt-var: #b08a3f; --kt-var-bg: #fefaf1; --kt-var-border: #f2e6c8;
  /* Nachbesserung AQ (C1) — zwei weitere Kategorien, in der Tonlage an
     Andreas' Tokens angelehnt (gleiche Helligkeit, gleiche Saettigung
     wie fix/variabel, nur andere Farbfamilie). */
  --kt-indirekt: #4a6b8a; --kt-indirekt-bg: #f1f5f9; --kt-indirekt-border: #d3dfe9;
  --kt-kennzahlen: #5c6178; --kt-kennzahlen-bg: var(--kt-kennzahl-bg); --kt-kennzahlen-border: #e6e8f2;

  /* Flaeche der Kennzahlen (Durchgang BA, Design-Review Andreas):
     lightgoldenrodyellow. Sie steht als EIGENER Token da und nicht als
     Literal an den zwei Stellen, die sie brauchen — den Farbton zu
     wechseln (erwogen und verworfen war honeydew #f0fff0, weil Gruen mit
     der Ergebnis-Ampel kollidiert) muss EINE Zeile bleiben.
     Spiegel: farben.KT_KENNZAHL_BG; ein Test haelt beide gleich. */
  --kt-kennzahl-bg: #fafad2;

  /* Schrift auf einer Flaeche im Vollton der Bereichsfarbe. Die
     Bereichs-Ueberschrift traegt sie seit AQ, DB IV seit BA — und beide
     aus DIESEM Token, damit die zweite Stelle nicht eines Tages ein
     anderes Weiss bekommt. Kontrast je Bereich: GU 7,73:1, NW 4,85:1,
     KD 4,69:1, NT 3,62:1, GW 3,04:1, ET 2,72:1 — unter 4,5:1 also bei
     drei Bereichen. Das ist der Bestand der Ueberschrift, nicht neu
     entstanden; ein Abdunkeln der Bereichsfarben ist als eigener Punkt
     vorgemerkt (siehe PROJEKTSTAND, Horizont). */
  --kt-bereich-schrift: #fff;

  /* Ergebnis-Ampel */
  --kt-ergebnis-pos: #0f7a4e; --kt-ergebnis-pos-bg: #e7f7ee; --kt-ergebnis-pos-border: #b9e6cc;
  --kt-ergebnis-neg: #b3261e; --kt-ergebnis-neg-bg: #fdecec; --kt-ergebnis-neg-border: #f3bcb8;

  /* Fehlerbilder des Auflösungspfads (Durchgang AT). Zwei Tonlagen:
     der Zuordnungskonflikt ist ein BEFUND (rot, jemand muss handeln),
     das Aufwärm-Fenster ein ZUSTAND (bernstein, es passiert gerade
     etwas). Vorberechnete Hex-Werte wie im übrigen AQ-Satz — kein
     color-mix(), damit dieselben Töne auch im PDF-Renderer stimmen. */
  --kt-stoerung: #b3261e; --kt-stoerung-bg: #fdecec; --kt-stoerung-border: #f3bcb8;
  --kt-wartet: #8a5a00;   --kt-wartet-bg: #fdf5e4;   --kt-wartet-border: #ecd9a8;
}

/* Selbst gehostete Schriften (V6, Datenschutz): KEIN Aufruf an
   fonts.googleapis.com. Die Dateien liegen unter static/kerndaten/
   schriften/ (Quelle: @fontsource, SIL Open Font License — Lizenztexte
   OFL-Inter.txt und OFL-InterTight.txt liegen daneben).
   font-display: swap — die Seite ist sofort lesbar, die Schrift tauscht
   sich nach; ein unsichtbarer Text waere bei einer Zahlentabelle die
   schlechtere Wahl. */
@font-face {
  font-family: "Inter";
  src: url("schriften/inter-latin-400-normal.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("schriften/inter-latin-600-normal.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("schriften/inter-latin-700-normal.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("schriften/inter-latin-800-normal.woff2") format("woff2");
  font-weight: 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter Tight";
  src: url("schriften/inter-tight-latin-700-normal.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter Tight";
  src: url("schriften/inter-tight-latin-800-normal.woff2") format("woff2");
  font-weight: 800; font-style: normal; font-display: swap;
}

body {
  margin: 0;
  /* Durchgang AQ: Inter mit system-ui als Rueckfall (V6). */
  font-family: var(--kt-font);
  background: var(--kt-bg);
  color: var(--farbe-text);
}

/* Kopfzeile: bleibt beim Scrollen oben am Bildschirm stehen. Feste Hoehe
   (siehe --hoehe-kopfzeile), damit der BWA-Tabellenkopf lueckenlos
   darunter andocken kann. z-index ueber allen Sticky-Elementen der Liste. */
.kopfzeile {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--farbe-kopf);
  color: #fff;
  padding: 0.6rem 1rem;
  box-sizing: border-box;
  height: var(--hoehe-kopfzeile);
  position: sticky;
  top: 0;
  z-index: 10;
}

.anwendungsname {
  font-weight: 700;
  font-size: 1.1rem;
}

.benutzerbereich {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.9rem;
}

.logout-formular {
  display: inline;
  margin: 0;
}

/* Feinschliff Erweiterung 5: volle Pill wie alle uebrigen
   Schaltflaechen. Etwas mehr Seitenpolster, damit die Rundung nicht an
   der Schrift klebt; die Hoehe bleibt, sonst waechst die Kopfzeile. */
.logout-formular button {
  background: transparent;
  border: 1px solid #fff;
  color: #fff;
  border-radius: 999px;
  padding: 0.25rem 0.85rem;
  cursor: pointer;
}

/* Inhalt: volle Fensterbreite, nur etwas Seitenabstand. Schmale Inhalte
   (Login, Haendlerauswahl, Gesamt-BWA) begrenzen sich selbst; die
   Segmentansicht (W4) braucht die volle Breite fuer viele Spalten. */
.inhalt {
  padding: 1rem;
}
/* Durchgang P — die Fixierung der oberen Leisten beim Querscroll steht
   WEITER UNTEN (nach den sticky-Basisregeln der Leisten), damit sie diese
   überschreibt und die statischen Regel-Tests eindeutig bleiben. */

.fehlermeldung {
  color: #a1231b;
}

/* HTMX-Fehlerhinweis (hx_fehler.js): schwebender Balken oben, wenn eine
   HTMX-Anfrage mit Server-/Netzfehler endet — sonst bliebe der Fehler als
   "nichts passiert" unsichtbar. Ueber allen Sticky-Ebenen (Kopfzeile
   z-index 10). */
.hx-fehler {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  max-width: min(40rem, 92vw);
  margin: 0.6rem 0;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  background: #fbeaea;
  color: #8a1c14;
  border: 1px solid #e0a9a3;
  border-radius: 4px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  padding: 0.5rem 0.7rem;
  font-size: 0.9rem;
}

.hx-fehler-zu {
  border: none;
  background: transparent;
  color: #8a1c14;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: pointer;
}

.hx-fehler-zu:hover { color: #000; }

/* ==========================================================================
   Review-Befund R2 (+ Nachbesserung 2, S3/S4): die Zugangsseiten als
   zentrierte Karte — Anmeldung, Abmelde-Bestaetigung, Haendlerauswahl.

   OHNE UMBAU: die Karte ist die .inhalt-Flaeche selbst, erkannt an
   einem Element, das es nur auf der jeweiligen Seite gibt. Bei der
   Anmeldung ist das .login-hilfen — die Auth-Mechanik (Passkey-
   Zeremonie, Fallback-Details, Formular) bleibt damit unangetastet.
   Die Haendlerauswahl traegt ihre Liste (.haendler-auswahl) ohnehin
   schon; die Abmelde-Seite hat als einzige eine Klasse dazubekommen
   (.abmelde-aktion), weil sie kein eigenes Kennzeichen hatte.

   Der vertikale Sitz ist bewusst nicht mittig im Fenster (das haette
   bei aufgeklapptem Passwort-Fallback gesprungen), sondern ein fester
   Abstand unter der Kopfzeile.
   ========================================================================== */
.inhalt:has(> .login-hilfen),
.inhalt:has(> .abmelde-aktion),
.inhalt:has(> .haendler-auswahl) {
  /* min() statt einer festen Deckelung: die Karte wird nie breiter
     als der Bildschirm minus 2rem Rand — auch nicht bei 360 px. */
  max-width: min(28rem, 100% - 2rem);
  box-sizing: border-box;
  margin: 3rem auto;
  padding: 1.8rem 1.8rem 1.5rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-lg);
  box-shadow: var(--kt-shadow);
}
/* Die Haendlerauswahl traegt Firmennamen und braucht mehr Platz als
   ein Anmeldeformular — dieselbe Karte, nur breiter. */
.inhalt:has(> .haendler-auswahl) {
  max-width: min(44rem, 100% - 2rem);
}
.inhalt:has(> .login-hilfen) > h1,
.inhalt:has(> .abmelde-aktion) > h1,
.inhalt:has(> .haendler-auswahl) > h1 {
  margin-top: 0;
  text-align: center;
}
/* Haendlerliste ohne Aufzaehlungszeichen — die Karte ist eng, und die
   Punkte haengen sonst ausserhalb des Innenabstands. */
.inhalt:has(> .haendler-auswahl) .haendler-auswahl {
  list-style: none;
  margin: 0;
  padding: 0;
}
.inhalt:has(> .haendler-auswahl) .haendler-auswahl li + li {
  margin-top: 0.4rem;
}
.inhalt:has(> .haendler-auswahl) .haendler-auswahl a {
  display: block;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-sm);
  background: var(--kt-surface-2);
  color: var(--kt-text);
  text-decoration: none;
}
.inhalt:has(> .haendler-auswahl) .haendler-auswahl a:hover {
  border-color: var(--kt-accent);
  color: var(--kt-accent);
  background: var(--kt-accent-soft);
}
.inhalt:has(> .abmelde-aktion) .abmelde-aktion { margin-bottom: 0; }
.inhalt:has(> .abmelde-aktion) .knopf-primaer { width: 100%; }
/* Anmeldefelder in der Designsprache statt im Browser-Grundzustand. */
.login-formular input[type="text"],
.login-formular input[type="password"] {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  width: 100%;
  box-sizing: border-box;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-sm);
  background: var(--kt-surface-2);
  box-shadow: var(--kt-shadow-control);
}
.login-formular input:focus-visible {
  outline: 2px solid var(--kt-accent);
  outline-offset: 2px;
}
.inhalt:has(> .login-hilfen) .knopf-primaer,
.inhalt:has(> .login-hilfen) .knopf-sekundaer,
.inhalt:has(> .login-hilfen) .passkey-button { width: 100%; }
.inhalt:has(> .login-hilfen) .login-hilfen { margin-bottom: 0; }
/* S5, zweite Haelfte der Ursache: WAS AUCH IMMER in einer Zugangskarte
   steht, bleibt im Innenabstand. Der Knopf war nur der sichtbare Fall;
   dieselbe Falle haetten Eingabefelder, Bilder oder ein langes Wort.

   NUR NACHFAHREN. Erster Versuch hatte die Karte SELBST mit in diese
   Regel genommen — sie hat dieselbe Spezifitaet wie die Kartenregel
   oben und steht spaeter, also gewann hier `max-width: 100%` und die
   Karte lief ueber die volle Bildschirmbreite (Nachbesserung 3,
   Befund 1). Die Karte bringt ihr box-sizing selbst mit. */
.inhalt:has(> .login-hilfen) *,
.inhalt:has(> .abmelde-aktion) *,
.inhalt:has(> .haendler-auswahl) * {
  box-sizing: border-box;
  max-width: 100%;
}
/* Lange Benutzernamen/Fehlertexte brechen um, statt die Karte zu
   sprengen — sichtbar erst bei schmalem Fenster. */
.inhalt:has(> .login-hilfen) p,
.inhalt:has(> .abmelde-aktion) p,
.inhalt:has(> .haendler-auswahl) a { overflow-wrap: anywhere; }

/* Anmeldeformular */
.login-formular label {
  display: block;
  width: auto;
  margin-bottom: 0.25rem;
  font-size: 0.9rem;
  color: var(--kt-text-soft);
}

/* BWA-Liste (Etappe W2): CSS-Grid statt <table>, weil <details> keine
   Tabellenzeilen umschließen darf. Feste Spaltenbreiten halten die
   Spalten über Blockgrenzen hinweg bündig. */
.bwa-liste {
  font-size: 0.9rem;
  max-width: 60rem;
}

/* ==========================================================================
   Review-Befund R1: der Inhalt steht MITTIG, wenn er die Bildschirm-
   breite nicht braucht.

   Bis hierher klebte alles links: Durchgang M hatte das ausdrueckliche
   min-width:100% entfernt, damit auf breiten Monitoren rechts nicht nur
   leere Flaeche steht — die Tabelle nimmt seither ihre Inhaltsbreite
   und stand damit LINKSBUENDIG.

   Zentriert wird die ACHSE, nicht die einzelne Tabelle: #bwa-kopf ist
   der gemeinsame Vorfahr von Titel, Filterleiste, Statuszeile und
   Liste. Damit folgen alle vier derselben Mitte, ohne dass irgendeine
   Innengeometrie angefasst wird (Raster, Spaltenbreiten, Trennlinien
   bleiben, wie sie sind).

   NUR OHNE .bwa-scroll: sobald die Tabelle breiter werden KANN als der
   Viewport, werden die Leisten viewport-fix (Durchgang P) und die
   Liste nimmt ihre Inhaltsbreite. Eine Deckelung von #bwa-kopf wuerde
   die ueberbreite Tabelle dann an der Kachelkante beginnen lassen
   statt am Seitenrand. Fuer diesen Fall zentriert stattdessen die
   Liste selbst — auto-Raender wirken nur, solange Platz da ist, und
   fallen bei Ueberbreite von selbst auf 0. Querscroll-Verhalten also
   unveraendert. */
#bwa-kopf:not(:has(.bwa-scroll)) {
  max-width: 60rem;
  margin-inline: auto;
}

/* Nachbesserung 2 (S1): im Querscroll-Fall folgt der TITEL derselben
   Achse. R1 hatte dort nur die Liste zentriert (margin-inline: auto);
   die Ueberschrift blieb links kleben, weil sie ihre Breite nicht
   kennt.

   Loesung: die Achse nimmt die Breite ihres breitesten Kindes
   (width: max-content) und zentriert sich selbst. Titel, Statuszeile
   und Liste sitzen damit auf derselben linken Kante. Passt die
   Tabelle nicht mehr, fallen die auto-Raender von selbst auf 0 und es
   bleibt beim bisherigen Verhalten — die Leisten sind in diesem Fall
   ohnehin viewport-fix (Durchgang P) und von der Achse unberuehrt. */
#bwa-kopf:has(.bwa-scroll) {
  width: max-content;
  margin-inline: auto;
}
.bwa-liste.bwa-scroll { margin-inline: auto; }

/* Der OnePager hat keinen gemeinsamen Vorfahr fuer Titel und Tabelle
   (beide haengen direkt an .inhalt), und seine Tabelle scrollt in
   einem EIGENEN Container. Dort zentriert die Tabelle selbst — und der
   Titel bekommt dieselbe Mitte, indem sein Kasten nur so breit wird
   wie sein Text und ebenfalls zentriert. Beide stehen damit auf der
   Seitenmitte, also auf derselben Achse. */
table.onepager { margin-inline: auto; }
.inhalt:has(> #onepager-ergebnis) > h1.bwa-titel {
  width: max-content;
  max-width: 100%;
  margin-inline: auto;
}

/* EINE Scroll-Konstruktion für alle drei Ansichten (Durchgang L). Sobald
   die Tabelle breiter werden KANN als der Viewport (Segmentansichten IMMER;
   Gesamtansicht mit Zusatz- oder Vorjahresspalten), trägt die Liste die
   Klasse bwa-scroll: sie nimmt ihre INHALTSBREITE (width max-content) und
   läuft bei Überbreite über den Viewport hinaus — dann scrollt die SEITE
   horizontal (KEIN eigener Scroll-Container, der sonst das vertikale
   Seiten-Scrolling abfinge und den Titel festhielte, Durchgang-K-Fehler).
   Vertikal scrollt in allen Ansichten die Seite; der Titel läuft weg, der
   Leisten-Stapel rastet ein. Ohne bwa-scroll bleibt die Gesamtansicht wie
   gehabt (max-width 60rem, kein Scrollbalken).

   Durchgang M: KEIN min-width:100% mehr an der Gesamtansicht — sie stand
   sich sonst auf breiten Monitoren auf die volle Viewportbreite (mit den
   gedeckelten Spalten blieb rechts nur leere Fläche). Jetzt steht die
   Tabelle LINKSBÜNDIG in ihrer natürlichen (Inhalts-)Breite. Die
   Segmentansicht behält ihr bestehendes Verhalten (füllt mind. die
   Viewportbreite, s. u.) — sie ist unverändert. */
.bwa-liste.bwa-scroll {
  max-width: none;
  width: max-content;
}

.bwa-zeile {
  display: grid;
  /* Erste Spalte: festes Klapp-Symbol — bei JEDER Zeile vorhanden, damit
     die Zeilennummern unabhängig vom Pfeil bündig beginnen.
     Die Spaltendefinition kommt in der Segmentansicht (W4) als
     CSS-Variable vom Listen-Container (dynamische Segmentanzahl);
     ohne Variable gilt das bisherige Gesamt-Layout.
     Wertspalte 7rem: bemessen am breitesten realistisch moeglichen Text
     (fett '+100.000.000' = 105 px, '-1.000.000,00' = 107 px) — siehe
     views.WERTSPALTE, das dieselbe Breite fuer alle uebrigen Spalten-
     definitionen liefert. */
  grid-template-columns: var(--bwa-spalten,
                             1.2rem 5rem minmax(0, 1fr) 7rem 5rem);
  /* Nachbesserung 5 (N4): die Spaltenluecke steht als Variable, weil die
     deckende Sticky-Abdeckung sie ueberspannen MUSS. Beide lasen den Wert
     bisher getrennt als Literal 0.5rem — driften sie auseinander, reisst
     die Abdeckung in genau dieser Luecke auf. Eine Quelle, ein Wert. */
  --bwa-spaltenluecke: 0.5rem;
  column-gap: var(--bwa-spaltenluecke);
  /* Nachbesserung 6 (M1): das seitliche Zeilenpolster steht ebenfalls als
     Variable. Der Bereichsakzent sitzt genau darin — er muss wissen, wie
     breit es ist, um buendig an der Zeilen-AUSSENkante zu liegen. */
  --bwa-zeilenpolster: 0.5rem;
  /* Breite des Bereichsakzents (Andreas' Entwurf: 3px). */
  --kt-akzent-breite: 3px;
  /* Nachbesserung AQ (A1/A3): das VERTIKALE Polster sitzt nicht mehr an
     der Zeile, sondern in den Zellen (--zeilen-polster, s. u.).
     Grund: ein Polster an der Zeile gehoert zur Zeilenbox, aber NICHT zum
     Hintergrund der einzelnen Zellen — der Vorjahresstreifen und die
     vertikalen Marken-Trennlinien endeten deshalb an jeder Zeilengrenze
     und zeigten einen weissen Spalt. Frueher glich das jede Zelle einzeln
     mit negativen Raendern aus; das hielt nur, solange ALLE Zeilen
     dasselbe Polster hatten — die DB-Meilensteine (0,6rem) rissen es auf.
     Jetzt spannt jede Zelle die volle Zeilenhoehe, unabhaengig davon,
     welches Polster die Zeile setzt. */
  --zeilen-polster: 0.15rem;
  padding: 0 var(--bwa-zeilenpolster);
  border-bottom: 1px solid var(--farbe-linie);
  align-items: stretch;
}

/* Jede Zelle traegt das Polster selbst und faerbt damit die volle
   Zeilenhoehe. align-items: stretch (oben) sorgt dafuer, dass die Zellen
   auch tatsaechlich die ganze Hoehe bekommen.

   Nachbesserung AQ (A5): der Zellinhalt wird MITTIG gesetzt statt auf der
   Grundlinie. Damit steht die Zeilennummer auch dann auf halber Hoehe,
   wenn die Bezeichnung daneben zweizeilig umbricht — vorher klebte sie an
   der ersten Grundlinie. Entspricht dem Entwurf (dort .bwa-zeile > span
   mit display:flex, align-items:center). */
.bwa-zeile > span {
  display: flex;
  align-items: center;
  padding-block: var(--zeilen-polster);
}
.bwa-zeile > span.zahl { justify-content: flex-end; }

.bwa-zeile .zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* Die Spaltenbreiten sind knapp bemessen (s. o.): ein Zahlentext darf
     unter keinen Umstaenden umbrechen und damit die Zeilenhoehe sprengen.
     Tabellarische Ziffern halten die Spalten zusaetzlich buendig. */
  white-space: nowrap;
}

/* Prozentwerte dezenter als die Betraege */
.bwa-zeile .prozent {
  font-size: 0.75em;
  color: #6b7280;
}

.bwa-spaltenkopf {
  font-weight: 700;
  border-bottom: 2px solid var(--farbe-kopf);
}

/* Kopfbereich der Liste (Segmentnamen- + Spaltenkopf-Zeile als EIN
   Wrapper): klebt beim vertikalen Scrollen UNTER dem gesamten
   Sticky-Kopfbereich (Durchgang K) — App-Kopfzeile + Filterleiste +
   Statuszeile + Klapp-/Kennzahlen-Leiste. Offset = Summe aller vier
   Hoehen (EINE Offset-Quelle, in allen drei Ansichten gleich; nur der
   Seitentitel scrollt darueber weg). Deckender Hintergrund + Schatten,
   damit durchlaufende Zeilen nicht durchscheinen. In der Segmentansicht
   ueberschreibt .bwa-segmente .bwa-kopfbereich den Offset auf 0 (dort ist
   der scrollende Container der Bezugsrahmen, s. u.). */
.bwa-kopfbereich {
  position: sticky;
  top: calc(var(--hoehe-kopfzeile) + var(--hoehe-filter)
            + var(--hoehe-status) + var(--hoehe-klappleiste));
  z-index: 2;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
}

/* Einrückung: 1,5em je Stufe (CSS-Variable aus dem Template) */
.bwa-zeile .bezeichnung {
  padding-left: calc(var(--einzug, 0) * 1.5em);
}

/* Zeilennummern sind Arbeitsmittel (Formeln/Mapping), fuer den Anwender
   aber Beiwerk: kleiner, normal statt fett, farblich zurueckgenommen.
   Direkt am Span gesetzt, damit es auch das von .fett geerbte
   font-weight ueberschreibt (eine direkt gesetzte Eigenschaft schlaegt
   die vererbte). NUR die BWA-Tabelle — .nummer existiert als Klasse
   ausschliesslich hier (Verwaltung/Mapping/Drilldown/PDF nutzen sie
   nicht). Die vertikale Klickflaeche bleibt ueber das Padding erhalten,
   damit der klappgriff (Etappe A) nicht schrumpft; baseline-Ausrichtung
   der Zeile haelt Nummer und Bezeichnung weiter auf einer Linie. */
.bwa-zeile .nummer {
  font-size: 0.8em;
  font-weight: 400;
  color: #7b828d;
  padding: 0.15rem 0;
}

/* Abteilungsflaechen (Farbkonzept): jede Datenzeile UND die
   Abteilungs-Leerzeile (Sentinel) tragen ihre Bereichs-Kennung als
   Klasse bereich-XX und faerben damit ihre Flaeche pastell.
   --abt-kraeftig steht fuer die Trennbalken/-linien bereit,
   --abt-pastell fuer die deckenden Sticky-Spalten der Zeile (s. u.) und
   fuer die Pastell-Bruecke unter den Trennlinien (s. u.). Ueber die
   KENNUNG (nicht die Reihenfolge): ausgeblendete Abteilungen verschieben
   nichts. Spaltenkopf-/Kopfbereichszeilen tragen keine Kennung und
   bleiben ungefaerbt. */
/* Durchgang AQ (Redesign nach Andreas' Entwurf): die Zeilenflaeche ist
   nicht mehr pastellfarben, sondern RUHIG WEISS — die Bereichszugehoerig-
   keit traegt jetzt der farbige Abteilungskopf plus ein schmaler Akzent
   am linken Rand. Der MECHANISMUS bleibt aber exakt derselbe: jede Zeile
   setzt --abt-pastell auf ihre eigene Flaechenfarbe, und die deckenden
   Sticky-Spalten (Punkt 4/5, s. u.) lesen genau diese Variable. Deshalb
   funktioniert die Abdeckung beim Seitwaertsscrollen unveraendert weiter,
   obwohl sich saemtliche Farbwerte geaendert haben.
   --abt-kraeftig bleibt fuer Trennbalken und Bruecken erhalten. */
.bereich-NW,
.bereich-GW,
.bereich-KD,
.bereich-ET,
.bereich-NT,
.bereich-GU { background: var(--kt-surface); --abt-pastell: var(--kt-surface); }

/* --kt-bereich ist die VOLLTON-Farbe der Abteilung (dieselbe, die der
   Abteilungskopf traegt). Die Abschlussleiste am Abteilungsende liest sie;
   damit klammern Kopf und Leiste die Abteilung in EINER Farbe.
   Nicht zu verwechseln mit --abt-kraeftig: das ist die ALTE Palette
   (z. B. #b02a2a fuer Kundendienst) und faerbt weiterhin die
   Trennbalken innerhalb einer Abteilung. */
.bereich-NW { --abt-kraeftig: var(--abt-NW-kraeftig); --kt-db-base: var(--kt-nw); --kt-akzent-bereich: var(--kt-nw-bg-strong); --kt-bereich: var(--kt-nw); }
.bereich-GW { --abt-kraeftig: var(--abt-GW-kraeftig); --kt-db-base: var(--kt-gw); --kt-akzent-bereich: var(--kt-gw-bg-strong); --kt-bereich: var(--kt-gw); }
.bereich-KD { --abt-kraeftig: var(--abt-KD-kraeftig); --kt-db-base: var(--kt-kd); --kt-akzent-bereich: var(--kt-kd-bg-strong); --kt-bereich: var(--kt-kd); }
.bereich-ET { --abt-kraeftig: var(--abt-ET-kraeftig); --kt-db-base: var(--kt-et); --kt-akzent-bereich: var(--kt-et-bg-strong); --kt-bereich: var(--kt-et); }
.bereich-NT { --abt-kraeftig: var(--abt-NT-kraeftig); --kt-db-base: var(--kt-nt); --kt-akzent-bereich: var(--kt-nt-bg-strong); --kt-bereich: var(--kt-nt); }
.bereich-GU { --abt-kraeftig: var(--abt-GU-kraeftig); --kt-db-base: var(--kt-gu); --kt-akzent-bereich: var(--kt-gu-bg-strong); --kt-bereich: var(--kt-gu); }

/* Bereichs-Akzent (Nachbesserung 4, K2 — REVIDIERT A6): der schmale
   Streifen in der Bereichsfarbe am linken Rand jeder Zeile ist wieder da.
   Die Entfernung in A6 beruhte auf einer Fehldeutung des Review-Befunds:
   beanstandet war eine Linie in den UEBERSCHRIFTSLEISTEN, nicht dieses
   Element aus dem Entwurf.
   Die Regel selbst steht weiter unten bei den Sticky-Spalten — der
   Streifen muss AUF der Sticky-Spalte liegen und darf deren Deckung nicht
   verlieren; er teilt sich daher die box-shadow-Liste mit ihr. */

/* Kennzahlen-Zeilen (Durchgang E): eine Zeile mit gesetzter Kennzahl-Stufe
   hebt sich von den normalen Zeilen ab. Erkennung ausschliesslich ueber
   die Klasse .kennzahl (die aus kennzahl_stufe kommt), nie ueber
   Zeilennummern. Der Vorjahresstreifen (eigene Zellfarbe) und die
   Null-Unterdrueckung bleiben unberuehrt.

   Durchgang AQ: die Unterscheidung laeuft jetzt ueber die ZURUECK-
   GENOMMENE Textfarbe des Entwurfs (.typ-*.kennzahl) plus eine leicht
   getoente Flaeche — nicht mehr ueber eine eigene Pastellfamilie je
   Abteilung. Ein Wert bleibt: --abt-pastell zieht mit, damit die
   Sticky-Spalten denselben Ton tragen.

   Durchgang BA: aus der leicht getoenten Flaeche wird die PRAEGNANTE —
   --kt-kennzahl-bg. Dieselbe Flaeche traegt die Kennzahlen-KARTE (siehe
   .kt-block.kt-kennzahlen); das ist Absicht, denn beides heisst
   „Kennzahl" und darf nicht zwei Farben haben. Im Arbeitsbestand ist
   `kennzahl_stufe` derzeit nirgends gesetzt — sichtbar wird der Ton
   heute also ueber die Karte. Diese Regel bleibt trotzdem, damit eine
   spaeter gepflegte Stufe nicht in einer dritten Farbe landet. */
.bwa-zeile.kennzahl {
  background: var(--kt-kennzahl-bg);
  --abt-pastell: var(--kt-kennzahl-bg);
}

/* Abteilungs-UEBERSCHRIFTEN (Durchgang F): die ERSTE Zeile jeder
   Abteilung (Struktur: Typ TEXT, oberste Ebene — nie ueber Zeilennummern)
   wird als Ueberschrift kenntlich. --abt-pastell wird mitgezogen, damit
   die deckenden Sticky-Spalten und die Bruecken denselben Ton tragen.
   Diese Regeln stehen NACH .kennzahl: faellt eine Zeile mit beidem
   zusammen (kaeme strukturell nicht vor), GEWINNT die Ueberschrift
   (gleiche Spezifitaet, spaetere Regel). Die groessere Schrift und das
   Fettgewicht kommen aus der bereichsunabhaengigen Regel darunter.

   Durchgang AQ: aus der MITTEL-Flaeche wird der farbige Kopf mit weisser
   Schrift.

   Nachbesserung 2 (F2): FLACHE Bereichsfarbe statt des Farbverlaufs aus
   dem Entwurf. Grund ist nicht Geschmack, sondern ein Zusammenspiel:
   ueber dem Verlauf liegen zwangslaeufig eigene Zellflaechen — die drei
   deckenden Sticky-Spalten (sie MUESSEN einen Vollton tragen, sonst
   scheinen quergescrollte Werte durch) und das Vorjahresband. Auf einem
   Verlauf sitzt jede dieser Flaechen auf einem anderen Farbton auf; das
   ergab die gemeldete Flickenoptik. Auf einer flachen Flaeche tragen
   Sticky-Spalten und Zeile exakt denselben Wert (--abt-pastell) und
   verschwinden ineinander; sichtbar bleibt allein das Vorjahresband als
   ein klar begrenzter, konstanter Abschnitt. */
.bereich-NW.abteilungskopf { background: var(--kt-nw); --abt-pastell: var(--kt-nw); }
.bereich-GW.abteilungskopf { background: var(--kt-gw); --abt-pastell: var(--kt-gw); }
.bereich-KD.abteilungskopf { background: var(--kt-kd); --abt-pastell: var(--kt-kd); }
.bereich-ET.abteilungskopf { background: var(--kt-et); --abt-pastell: var(--kt-et); }
.bereich-NT.abteilungskopf { background: var(--kt-nt); --abt-pastell: var(--kt-nt); }
.bereich-GU.abteilungskopf { background: var(--kt-gu); --abt-pastell: var(--kt-gu); }

.bwa-zeile.abteilungskopf,
.bwa-zeile.abteilungskopf .bezeichnung,
.bwa-zeile.abteilungskopf .nummer,
.bwa-zeile.abteilungskopf .zahl { color: var(--kt-bereich-schrift); }
.bwa-zeile.abteilungskopf {
  /* Nachbesserung 3 hatte den Aussenabstand nach oben ganz gestrichen,
     weil er die durchgehenden Marken-Trennlinien vor jedem Bereichskopf
     aufriss.
     Nachbesserung 4 (K1) fuehrt ihn KLEIN wieder ein: der Kopf soll nicht
     an der Vorgaengerzeile kleben. Die Pause in den Linien ist dabei
     bewusst in Kauf genommen — eine Bereichsgrenze ist eine zulaessige
     Pause (dieselbe Abwaegung wie bei den Kachelabstaenden, s. .kt-block).
     Nur vertikal, wie ueberall in dieser Liste. */
  margin-block-start: 0.5rem;
  border-radius: var(--kt-radius);
  border-bottom: none;
  box-shadow: var(--kt-shadow-sm);
  font-family: var(--kt-font-display);
  letter-spacing: -0.01em;
  --zeilen-polster: 0.6rem;
}

/* Nachbesserung AQ (A7): ALLE VIER Ecken rund. Die Rundung der Zeile
   allein genuegt nicht — die deckende Sticky-Abdeckung der ersten Spalte
   liegt DARUEBER (eigener Hintergrund + seitliche Box-Shadows) und malte
   die linke obere Ecke wieder quadratisch zu. Also bekommt die erste
   Zelle dieselbe Rundung links, und ihr linker Schatten entfaellt (er
   ragte ueber die Kante hinaus). */
.bwa-zeile.abteilungskopf > .klapp {
  border-radius: var(--kt-radius) 0 0 var(--kt-radius);
  box-shadow: 0.5rem 0 0 var(--abt-pastell);
}
.bwa-zeile.abteilungskopf > span:last-child {
  border-radius: 0 var(--kt-radius) var(--kt-radius) 0;
}

/* A2/F2: das Vorjahresband liegt auf dem Kopf als DERSELBE
   halbtransparente Dunkelton wie ueberall sonst (--kt-vorjahr). Auf der
   jetzt flachen Bereichsfarbe ist er konstant — der Sonderwert aus der
   ersten Nachbesserung (eigens abgemischter Vollton) wird damit
   ueberfluessig, und das Band bleibt in der ganzen Tabelle EINE Farbe. */

/* Groessere, fette Ueberschriftschrift (bereichsunabhaengig). 1,2em hebt
   die Zeile klar von den normalen Zeilen ab; die Zeilennummer bleibt ueber
   ihre eigene Regel (.nummer) klein und zurueckgenommen. */
.bwa-zeile.abteilungskopf { font-size: 1.2em; }
.bwa-zeile.abteilungskopf .bezeichnung { font-weight: 700; }

/* Anzeige-Flags der Zeile (FA-42-09) */
.bwa-zeile.fett { font-weight: 700; }
.bwa-zeile.kursiv { font-style: italic; }

/* ---------- Schriftgroesse je Zeile (Durchgang AQ, Erweiterung 3) -------
   Sieben Stufen (-3..+3) RELATIV zur jeweils gueltigen Grundgroesse.
   Gedacht fuer wichtige, sonst unformatierte Zeilen, die zwischen
   formatierten Nachbarn untergehen.

   em und nicht pt: es gibt nicht EINE Grundgroesse. Der Bildschirm
   rechnet in rem (BWA 0,9rem, OnePager 0,84rem), das PDF in Punkt — und
   dort waehlt der Benutzer die Basis (6–9 pt). Eine feste Punktangabe
   waere bei 6 pt ein Sprung und bei 9 pt kaum sichtbar. Eine Stufe ist
   deshalb 0,1em; bei den heutigen Grundgroessen ist das ziemlich genau
   der eine Punkt, der die Motivation war (0,84rem ~ 10,1 pt, 0,1em ~
   1,0 pt), bleibt aber bei jeder Basis verhaeltnismaessig.

   Die Klassen gelten fuer BWA-ZEILEN UND OnePager-Zeilen — dieselbe
   Schreibweise, dieselben Faktoren, eine Quelle (models.
   SCHRIFTGROESSE_STUFE_EM; ein Test haelt CSS und Python gleich).

   GEOMETRIE: die Zeile waechst VERTIKAL. Das BWA-Raster steht in
   grid-template-columns mit festen rem-Massen, das PDF nutzt
   table-layout: fixed — eine groessere Schrift verschiebt dort keine
   Spalte. Nur die Zeilenhoehe aendert sich, und die darf das. */
.bwa-zeile.kt-schrift-m3, tr.kt-schrift-m3 > * { font-size: 0.7em; }
.bwa-zeile.kt-schrift-m2, tr.kt-schrift-m2 > * { font-size: 0.8em; }
.bwa-zeile.kt-schrift-m1, tr.kt-schrift-m1 > * { font-size: 0.9em; }
.bwa-zeile.kt-schrift-p1, tr.kt-schrift-p1 > * { font-size: 1.1em; }
.bwa-zeile.kt-schrift-p2, tr.kt-schrift-p2 > * { font-size: 1.2em; }
.bwa-zeile.kt-schrift-p3, tr.kt-schrift-p3 > * { font-size: 1.3em; }

/* Nachbesserung 5 (N2): .blockende zeichnet NICHTS mehr — keine Linie,
   keinen Aussenabstand, keinen Schatten. Die Zeile bleibt durch ihr
   Fettgewicht und die Kartenstruktur als Blockende erkennbar.

   Das war die gemeinsame Wurzel von DREI der sechs Befunde:

   (a) "weisse Schattenlinie unter fetten Summenzeilen". Der 2px-Border
       traf 113 von 135 blockende-Zeilen gar nicht mehr — bei der letzten
       Zeile einer Karte gewinnt :where(.kt-block) .bwa-zeile:last-child
       mit border-bottom:none (gleiche Klassenzahl, spaeter im File).
       --trennbalken blieb aber 2px, und die ::after-Bruecken setzten
       genau dort an: top = 100% + 2px. Unter der Zelle blieb also ein
       2px-Streifen UNGEDECKT, in dem der Zeilenschatten (--abt-pastell,
       in einer Karte die helle Kartenfarbe) quer durchlief — und die
       Bruecke ragte am unteren Ende um dieselben 2px in die Folgezeile.
       Hell oben, dunkel unten: genau die gemeldeten Querbalken.
   (b) Die 22 Zeilen MIT Border trugen ihn in --abt-kraeftig, also aus
       der ALTEN Palette (#1e5fa8 in Neuwagen) — dieselbe Quelle wie die
       Haarlinie aus K5.
   (c) Der 9,6px-Aussenabstand riss ein Loch in die Sticky-Abdeckung.
       Die Abdeckung ist eine Eigenschaft der ZELLE; ein margin liegt
       ausserhalb der Zeilenbox, dort gibt es keine Zelle und damit
       weder Hintergrund noch Deckschatten. Die Bruecken der
       gescrollten Wertzellen malten in diesen Spalt hinein — bei
       scrollX 400 nachgemessen: Marken-Trennlinie bei x 221,58 mitten
       in der Sticky-Zone [0, 387,19], auf 103 Zeilen. Das ist die als
       "Vorjahres-Zellen schieben sich zwischen die Beschriftungen"
       gemeldete Regression, und "zwischen" heisst woertlich: in den
       Zwischenraeumen der Zeilen, nicht der Spalten.

   Merksatz: KEINE Zeile der BWA-Liste darf einen vertikalen
   Aussenabstand erzeugen. Ein Spalt zwischen zwei Zeilen ist immer ein
   Loch in der Sticky-Abdeckung. Bewusste Pausen gehoeren an
   Kachelgrenzen (.kt-block) und an die Abschlussleiste — dort steht
   kein gescrollter Inhalt. */
.bwa-zeile.blockende {
  border-bottom: none;
  margin-bottom: 0;
  box-shadow: none;
}

/* Seitenumbruch = ABSCHLUSS einer Abteilung (Punkt A): die markierte
   Zeile ist die LETZTE der Abteilung (im Bestand die DB-IV-Zeilen
   18000/28000/… ), danach beginnt die nächste. Konsistent mit der
   Print-Semantik `break-after: page` (Umbruch NACH dieser Zeile,
   Lastenheft FA-42-09) sitzt der kräftige, leerzeilenhohe Balken am
   Bildschirm UNTERHALB der Zeile — sofort erkennbar, wo eine Abteilung
   endet und die nächste beginnt. Farbe aus der zentralen Akzent-Variable,
   damit der Balken in der objektiven Ansicht automatisch die Modus-Farbe
   (Blaugrün) annimmt. Balken statt Abteilungs-Hintergründe: kommt ohne
   serverseitige Gruppierungs-Klassen aus und funktioniert mit dem
   bestehenden Pro-Zeilen-Grid unverändert. */
/* Nachbesserung 5 (N2): der Balken bleibt — er ist eine bewusste,
   deckende Trennung innerhalb einer Abteilung, keine Haarlinie. Was
   entfaellt, ist der AUSSENABSTAND darunter samt Pastell-Bruecke: er
   war ein Loch in der Sticky-Abdeckung (Begruendung bei .blockende).
   Der Balken gehoert zur Zeilenbox und scrollt mit ihr; unter der
   Sticky-Zone verschwindet er wie jeder andere Zeileninhalt. */
.bwa-zeile.seitenumbruch {
  border-bottom: 0.85rem solid var(--abt-kraeftig, var(--farbe-kopf));
  margin-bottom: 0;
  box-shadow: none;
  break-after: page;
}

/* ---------- Abteilungs-ABSCHLUSS (Nachbesserung 4, K4) ----------
   Jede Abteilung endet mit einer abgerundeten Leiste in ihrer
   Bereichsfarbe. Die Leiste ist ein EIGENES Element, das die
   Praesentation je Abteilungsende rendert (praesentation.
   mit_abteilungsabstand -> <div class="abteilung-abschluss …">). Sie
   haengt an keinem Zeilentyp, an keinem :last-child und an keiner
   Geschwister-Beziehung.

   WARUM STRUKTURELL — der behobene Fehler:
   Vorher zog die letzte ZEILE der Abteilung den Abschluss ueber
   .bwa-zeile:has(+ .abteilung-abstand). Seit Nachbesserung 1 rendert
   eine Klappgruppe aber als <div class="kt-block">; ist der letzte Block
   einer Abteilung eine Karte, ist der Vorgaenger des Sentinels ein DIV
   und keine .bwa-zeile — der Selektor lief ins Leere. Am Bildschirm sah
   das aus wie "Leiste nur bei Gebrauchtwagen und nur bei ausgeblendeten
   Kennzahlen": mit eingeblendeten Kennzahlen endet jede Abteilung mit
   der Kennzahlen-KARTE (x9990), also mit einem DIV. Im Browser
   nachgezaehlt: 5 Sentinels, 4 davon mit einem DIV davor — genau eine
   Abteilung zeigte ihre Leiste.
   Zusaetzlich bekam die LETZTE Abteilung (Gesamtunternehmen) gar kein
   Sentinel, weil dieses nur am Bereichs-WECHSEL entstand; dort fehlte
   die Leiste immer. Beides erledigt das eigene Element.

   BREITE: die Leiste ist ein Block-Kind der Liste. Ihre volle Breite —
   auch in der Segmentansicht, quergescrollt — kommt gratis, weil
   .bwa-liste.bwa-scroll SELBST width:max-content traegt (es scrollt die
   Seite, nicht die Liste); der Block fuellt also die Inhaltsbreite. */
.bwa-liste .abteilung-abschluss {
  height: 0.85rem;
  border-radius: var(--kt-radius);
  background: var(--kt-bereich, var(--farbe-kopf));
  margin-block: 0.35rem 0.55rem;
}

/* Entdoppelung: die Leiste IST der Abschluss — der eigene Trennbalken
   des letzten Elements davor stuende sonst unmittelbar darueber als
   zweiter Balken. Er entfaellt deshalb, fuer beide Faelle (letztes
   Element ist eine Zeile bzw. eine Karte).

   Wichtig fuer den Fehlerfall: das hier ist NUR noch eine Entdoppelung.
   Greift eine dieser Regeln einmal nicht, steht ein Balken zu viel da —
   nie mehr einer zu wenig. Die Leiste selbst kommt strukturell. */
.bwa-zeile:has(+ .abteilung-abschluss),
.kt-block:has(+ .abteilung-abschluss) > .bwa-zeile.klappzeile {
  border-bottom: none;
  margin-bottom: 0;
  box-shadow: none;
}
/* (Die frueher hier noetige Abschaltung der ::after-Bruecken ist mit
   Nachbesserung 5 entfallen — es gibt keine Bruecken mehr, weil es
   keine margin-Spalte zwischen Zeilen mehr gibt. Siehe .blockende.) */

/* Nachbesserung 4 (K5): der Abteilungskopf ist eine UNUNTERBROCHENE
   Flaeche mit vier runden Ecken.

   URSACHE der gemeldeten Haarlinie (im Browser an 30000 Kundendienst
   nachgemessen): die Kopfzeile traegt aus den Stammdaten zusaetzlich das
   Kennzeichen "blockende". .bwa-zeile.blockende steht WEITER OBEN in
   dieser Datei, aber SPAETER als .bwa-zeile.abteilungskopf und hat
   dieselbe Spezifitaet (zwei Klassen) — die spaetere Regel gewann und
   setzte das dort ausdruecklich abgeschaltete border-bottom wieder:
   2px in --abt-kraeftig, fuer Kundendienst also #b02a2a aus der ALTEN
   Palette. Unter dem lila Balken stand damit eine dunkelrote Kante
   (Zeilenhoehe 42,19px = 40,19px Zellen + 2px Kante), darunter noch die
   9,6px-Pastellbruecke des blockende-Schattens.
   Es war also weder ein Rest-border-bottom in der Kopf-Regel noch der
   A7-Eckenschatten noch eine durchscheinende Folgezeile, sondern eine
   Kollision in der Kaskadenreihenfolge.

   Der Ausgleich steht deshalb HIER, nach .blockende/.seitenumbruch: ein
   Abteilungskopf ist nie eine Trennzeile — er EROEFFNET eine Abteilung,
   geschlossen wird sie von der Abschlussleiste oben. */
.bwa-zeile.abteilungskopf {
  border-bottom: none;
  margin-bottom: 0;
  box-shadow: var(--kt-shadow-sm);
}

/* Segmentansicht (W4): Marken/Standorte nebeneinander. Bei vielen
   Segmenten wird die Liste breiter als der Viewport -> horizontales
   Scrollen am Container; Klapp-Symbol, Nummer und Bezeichnung bleiben
   links "sticky" stehen (Bezugsrahmen ist der scrollende Container),
   mit weissem Hintergrund, damit Werte darunter durchlaufen koennen. */
/* Segmentansicht: nummer-Spalte ist schmaler (4rem) als in der Gesamt-
   ansicht (5rem) — daraus folgt der linke Sticky-Offset der Bezeichnung. */
.bwa-liste.bwa-segmente {
  --bez-left: 6.2rem;   /* klapp 1,2 + gap 0,5 + nummer 4 + gap 0,5 */
}

/* Kopfbereich UND Zeilen tragen im Scroll-Fall ihre INHALTSBREITE
   (max-content), damit der deckende weisse Hintergrund auch den horizontal
   gescrollten Bereich abdeckt. top kommt aus der Basis-Regel (unter dem
   Sticky-Stapel) — KEIN top:0 mehr: der Bezugsrahmen ist jetzt der Viewport
   (die Seite scrollt), nicht ein innerer Container. */
.bwa-scroll .bwa-kopfbereich,
.bwa-scroll .bwa-zeile {
  width: max-content;
}

/* Segmentansicht UNVERÄNDERT (Durchgang M): dort füllen Kopf und Zeilen
   weiterhin mindestens die Viewportbreite (min-width 100%) — bei wenigen
   Segmenten deckt der Hintergrund so den ganzen sichtbaren Bereich. Die
   Gesamtansicht steht dagegen linksbündig in natürlicher Breite (kein
   min-width, s. .bwa-liste.bwa-scroll). */
.bwa-liste.bwa-segmente,
.bwa-segmente .bwa-kopfbereich,
.bwa-segmente .bwa-zeile {
  min-width: 100%;
}

/* Deckende linke Spalten beim horizontalen SEITEN-Scrollen (Punkt 4,
   Durchgang L: gilt jetzt in ALLEN Scroll-Ansichten, Bezugsrahmen ist der
   Viewport). Klapp-Symbol, Nummer und Bezeichnung bleiben links stehen. */
.bwa-scroll .bwa-zeile .klapp,
.bwa-scroll .bwa-zeile .nummer,
.bwa-scroll .bwa-zeile .bezeichnung {
  position: sticky;
  /* Punkt 4: DECKEND weiß, damit horizontal gescrollte Wertzellen
     dahinter verschwinden. Der weiße Grund gilt für JEDE Zeile — kein
     Zeilentyp (fett/kursiv/Blockende, Summen-/Klappzeilen) setzt einen
     eigenen Hintergrund, der ihn überschreibt. z-index 1 hält die
     Spalten über den Wertzellen (z 0), aber unter dem Tabellenkopf
     (.bwa-kopfbereich, z 2). Die horizontalen Box-Shadows schließen
     zusätzlich die column-gap (0,5rem) zwischen den drei linken Spalten
     und rechts der Bezeichnung — sonst schiene der Inhalt durch.

     Punkt 5 (Optik-Etappe): der weiße Grund muss VOLLFLÄCHIG decken.
     Baseline-ausgerichtet war jede Zelle nur EINE Textzeile hoch —
     darüber und darunter (mehrzeilige Bezeichnungen, das vertikale
     Zeilen-Padding) schoben sich beim Querscrollen die Wertspalten
     sichtbar durch, im Extremfall vermischte sich die "% ∑"-Spalte
     optisch mit der Nummernspalte. align-self: stretch plus die
     negativen vertikalen Ränder decken jetzt die volle Zeilenhöhe
     inklusive Zeilen-Padding ab. margin-block/padding-block statt der
     Kurzschreibweise: das seitliche Padding der Bezeichnung trägt die
     Einrückung (--einzug) und darf nicht überschrieben werden.

     Nachbesserung AQ (A1): der vertikale Negativrand entfällt — seit das
     Polster in den Zellen sitzt, deckt jede Zelle die volle Zeilenhöhe
     von sich aus. Der frühere Ausgleich war auf genau ein Zeilenpolster
     geeicht und deckte bei den höheren DB-Zeilen nicht mehr. */
  background: var(--abt-pastell, #fff);
  z-index: 1;
  /* Nachbesserung 5 (N4): die Abdeckung ueberspannt die angrenzende
     Spaltenluecke auf BEIDEN Seiten — sie liest dafuer dieselbe
     Variable, aus der auch column-gap kommt. Vorher stand hier das
     Literal 0.5rem; stimmten die beiden Werte nicht mehr ueberein,
     entstuende genau in der Luecke ein Streifen, durch den
     quergescrollter Inhalt sichtbar bliebe. */
  box-shadow: var(--bwa-spaltenluecke) 0 0 var(--abt-pastell, #fff),
              calc(-1 * var(--bwa-spaltenluecke)) 0 0 var(--abt-pastell, #fff);
  align-self: stretch;
  /* Die Abdeckung ist eine Eigenschaft der ZELLE und reicht deshalb
     exakt so weit wie die Zeile hoch ist. Ein vertikaler Aussenabstand
     an einer Zeile waere ein Loch darin — siehe .blockende (N2). */
  margin-block: 0;
}

/* left-Offsets kumulativ aus den festen Spaltenbreiten (+ column-gap).
   klapp/nummer sind in beiden Ansichten gleich breit (1,2rem/…); nur die
   Bezeichnung startet je nach nummer-Breite anders — daher als Variable
   (Gesamt 7,2rem = klapp 1,2 + gap 0,5 + nummer 5 + gap 0,5; Segment setzt
   --bez-left auf 6,2rem, s. o.). */
.bwa-scroll .bwa-zeile .klapp { left: 0; }
.bwa-scroll .bwa-zeile .nummer { left: 1.7rem; }
.bwa-scroll .bwa-zeile .bezeichnung { left: var(--bez-left, 7.2rem); }

/* ---------- Bereichs-Akzent (Nachbesserung 4/5, K2/N3) ----------
   Schmaler Streifen in der Bereichsfarbe am linken Rand jeder Zeile des
   Bereichs. Andreas' Original-Element aus dem Entwurf, in A6
   versehentlich entfernt (siehe Kommentar bei den .bereich-*-Regeln).

   Nachbesserung 5 (N3) stellt Andreas' Referenz-KONSTRUKTION wieder her:
   der Streifen sitzt als inset-Schatten an der ZEILE, also an der
   Aussenkante der Kachel. Nachbesserung 4 hatte ihn auf die erste ZELLE
   (.klapp) gelegt, damit er beim Querscrollen stehenbleibt — die aber
   beginnt wegen padding: 0 0.5rem an der Zeile 8px weiter innen. Genau
   das war der gemeldete "abgerueckte" Streifen.

   Er liegt im linken Zeilenpolster. Ein inset-Schatten wird zwar unter
   den Hintergruenden der Kinder gemalt (dieselbe Mechanik wie beim
   Kartenrahmen in K3) — im Polster gibt es aber keine Zelle, also
   bleibt er sichtbar.

   PREIS, mit Michael abgestimmt: an der Zeile scrollt der Streifen
   quer weg. Stehenbleiben ist hier konstruktiv nicht erreichbar — die
   Sticky-Zone rastet buendig bei Viewport 0 ein, der Akzent liegt per
   Definition LINKS davon und laege damit ausserhalb des sichtbaren
   Bereichs. Die einzige stehenbleibende Variante ist die aus
   Nachbesserung 4, und die sitzt eben nicht an der Aussenkante.
   Vorgabe: Aussenkante gewinnt, Wegscrollen ist akzeptiert.

   Kein border-left: das verschoebe das Grid und damit die Linienflucht
   (dieselbe Regel wie bei den Karten). inset-Schatten hat keine
   Layout-Wirkung.

   Nachbesserung 6 (M1) korrigiert die EBENE. Der inset-Schatten an der
   Zeile war vollstaendig unsichtbar: die erste Sticky-Zelle traegt einen
   deckenden Schatten 8px nach LINKS (er sollte die Spaltenluecke
   schliessen, links der ersten Spalte gibt es aber keine — dort liegt
   nur das Zeilenpolster). Im Browser nachgemessen: Akzentzone
   [23,40; 26,40], Deckschatten-Zone [23,40; 31,40], Zelle sticky mit
   z-index 1 gegen eine Zeile mit z-index auto. Der Akzent lag also zu
   100 Prozent unter einer deckenden Flaeche — dieselbe Mechanik wie beim
   K3-Kartenrahmen (Nachbesserung 4), nur eine Ebene hoeher.

   Deshalb liegt der Streifen jetzt AUF der obersten deckenden Ebene: er
   ist der aeusserste Schatten DERSELBEN Sticky-Zelle. Zwei Schatten
   uebereinander erzeugen ihn buendig an der Zeilen-Aussenkante:
     -8px in Akzentfarbe  -> deckt [Zeilenkante, Zellkante]
     -5px in Deckfarbe    -> davon wieder alles ausser den ersten 3px
   Sichtbar bleibt exakt der 3px-Streifen an der Aussenkante, und die
   Deckung der Zone bleibt auf voller Breite erhalten (StickyVertrag).
   Die Masse kommen aus Variablen, nicht aus Literalen: der Streifen
   sitzt nur dann buendig, wenn er das Zeilenpolster kennt.

   Keine Layout-Wirkung — Schatten sind reine Malerei, die Linienflucht
   bleibt unberuehrt (Einrueck-Test).

   PREIS, mit Michael abgestimmt: beim Querscrollen rastet die Zone
   buendig bei Viewport 0 ein; der Akzent liegt per Definition links
   davon und scrollt damit weg. Ausdruecklich akzeptiert.

   Der Selektor traegt vier Klassen und gewinnt gegen die Sticky-Regel
   (drei). Der Abteilungskopf ist ausgenommen: er ist bereits
   vollflaechig in der Bereichsfarbe. */
.bwa-zeile[class*="bereich-"]:not(.abteilungskopf) > .klapp {
  box-shadow:
    calc(var(--kt-akzent-breite) - var(--bwa-zeilenpolster))
      0 0 var(--abt-pastell, #fff),
    calc(-1 * var(--bwa-zeilenpolster)) 0 0 var(--kt-akzent-bereich),
    var(--bwa-spaltenluecke) 0 0 var(--abt-pastell, #fff);
}

/* Lange Bezeichnungen duerfen in der schmaleren Spalte umbrechen */
.bwa-scroll .bezeichnung { overflow-wrap: anywhere; }

/* Zweizeiliger Spaltenkopf: Gruppenzeile mit Segmentnamen. Punkt C: die
   Zellen unten ausrichten (statt der von .bwa-zeile geerbten baseline) —
   der einzeilige "Gesamt"-Kopf und die zweizeiligen Segmentköpfe (Code
   über Name) haben unterschiedliche Höhen; ohne Bottom-Ausrichtung säße
   die Unterkanten-Trennlinie unter "Gesamt" höher als unter den
   Segmenten (Versatz). So liegt die Linie durchgehend auf EINER Höhe und
   "Gesamt" fluchtet mit der Namenszeile der Segmente.

   Nachbesserung 2 (F3): die Unterkanten-Linie sitzt jetzt an der ZEILE
   statt an den einzelnen Gruppen-Zellen. An den Zellen endete sie an
   jeder column-gap und lief in unterschiedlicher Laenge je Spalte —
   genau die gemeldeten Lueckenlinien. Horizontale Linien gehoeren im
   BWA-Bereich ausnahmslos an die Zeilenbox; die Zellen faerben nur
   Flaechen. */
.bwa-kopf-gruppen {
  border-bottom: 2px solid var(--farbe-linie);
  align-items: end;
}

.bwa-kopf-gruppen .gruppe {
  text-align: center;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Segment-Spaltenkopf (Punkt 1): der NAME dominiert (fett, etwas
   größer), der CODE steht klein und gedämpft darüber. Zweizeilig, damit
   der Name die Hauptinformation ist. */
.segment-kopf {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
}

.segment-kopf .segment-code {
  font-weight: 400;
  font-size: 0.7rem;
  color: #6b7280;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.segment-kopf .segment-name {
  font-weight: 700;
  font-size: 0.95rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* ==========================================================================
   Vorjahresvergleich (Etappe W6, FA-44-06): je Wertspalte ein aufklappbarer
   Block aus vier Zellen (Vorjahr | VJ % | Δ | Δ %; die VJ-%-Spalte kam in
   Durchgang BD dazu). Der Block wird dezent
   unterlegt, damit sofort erkennbar ist, welche Zahlen zum Vergleich
   gehoeren und welche zur Ist-Spalte.

   Farbwahl: ein neutraler, leicht warmer Grauton — bewusst KEIN Blau und
   kein Blaugruen, damit er weder mit der Kopfzeilen-Akzentfarbe
   (--farbe-kopf) noch mit der Modusfarbe der objektiven Ansicht
   konkurriert und in beiden Ansichten gleich gut liegt. Deshalb auch als
   feste Farbe statt ueber --farbe-kopf: der Vergleichsstreifen soll
   ruhiger Hintergrund bleiben und beim Moduswechsel nicht mitwandern.

   Punkt 3 (Optik-Etappe): die Unterlegung ist VOLLFLAECHIG. Die Zellen
   sind normalerweise baseline-ausgerichtet und damit nur EINE Textzeile
   hoch — bei mehrzeiligen Bezeichnungen blieben so Loecher, der Bereich
   sah aus wie eine Reihe einzelner Kaestchen. align-self: stretch zieht
   jede Zelle auf die volle Zeilenhoehe; die negativen Raender decken
   zusaetzlich das vertikale Zeilen-Padding (0,15rem) und je eine halbe
   column-gap (0,25rem) links/rechts ab. Dadurch stossen die Zellen
   eines Blocks nahtlos aneinander und der Block laeuft ueber alle Zeilen
   durch. Das Padding gibt exakt zurueck, was die negativen Raender
   nehmen — die Textposition bleibt unveraendert.

   Die 1px-Trennlinie zwischen den Zeilen bleibt bewusst sichtbar: sie
   gliedert auch innerhalb des Streifens, ohne ihn aufzubrechen.
   ========================================================================== */

:root {
  /* Durchgang AQ (V3): HALBTRANSPARENTES Dunkel statt eines festen
     Grautons. Nur so wirkt der Streifen ueber JEDER Zeilenfarbe — weisse
     Zeile, Abteilungskopf im Farbverlauf, DB-Meilenstein, Karte — jeweils
     "eine Spur dunkler". Ein Vollton koennte das nicht: er wuerde die
     Zeilenfarbe ueberdecken statt sie abzudunkeln, und der Bereichs-
     zusammenhang risse im Vorjahresbereich ab.
     Andreas' Entwurf nimmt den Abteilungskopf davon aus (transparent);
     V3 verlangt das Gegenteil — hier bleibt der Streifen geschlossen. */
  --farbe-vorjahr: #f3f1ec;
  --farbe-vorjahr-kopf: #eae7e0;

  /* Durchgang AQ — EIGENE Werte NUR fuer die BWA. Bewusst getrennt von
     --farbe-vorjahr: die beiden Variablen oben teilt sich die BWA mit dem
     OnePager (Bildschirm) UND mit dessen PDF, in dem derselbe Hexwert
     fest steht. Ein halbtransparenter Wert dort haette den OnePager still
     mitveraendert und ihn von seinem eigenen PDF entkoppelt. */
  --kt-vorjahr: rgba(28, 32, 51, 0.055);
  --kt-vorjahr-kopf: rgba(28, 32, 51, 0.09);
}

.bwa-zeile .vorjahr-zelle {
  align-self: stretch;
  /* Nachbesserung AQ (A1): kein vertikaler Negativrand mehr — die Zelle
     traegt das Polster der Zeile ohnehin (siehe .bwa-zeile > span) und
     deckt damit die volle Hoehe. Der horizontale Ausgleich bleibt: er
     schliesst die column-gap, damit das Band seitlich nicht aufreisst. */
  margin: 0 -0.25rem;
  padding-inline: 0.25rem;
  background: var(--kt-vorjahr);
}

/* V3: das Band laeuft DURCH — auch ueber Abteilungskoepfe, DB-Zeilen und
   Karteninhalte. Die Sonderbehandlung des Abteilungskopfes steht bei den
   Kopf-Regeln (A2: Vollton statt Transparenz ueber dem Verlauf). */

/* Die prozentuale Abweichung rendert in 0,75em (wie alle %-Zellen). Durch
   das Strecken sitzt ihr Text am Zellenoberrand statt auf der Grundlinie
   der grossen Zahlen — dieser Ausgleich holt sie optisch zurueck auf die
   gemeinsame Grundlinie (Wert in em der KLEINEN Schrift, damit er beim
   Zoomen mitwaechst). */
.bwa-zeile .prozent.vorjahr-zelle {
  padding-top: calc(0.15rem + 0.32em);
}

/* Die "Querlinien" (Blockende-, Abteilungstrenn-/Seitenumbruchzeilen)
   trennen sich vom naechsten Block ueber margin-bottom — und ein margin
   liegt AUSSERHALB der Zeilenbox, wohin kein Zellenhintergrund reicht.
   Genau dort riss der Vorjahresstreifen als weisser Balken auf. (Die
   Zeilen selbst haben KEINEN eigenen Hintergrund, der etwas
   ueberschriebe — im Browser gegengeprueft: background transparent.)

   Ein Pseudo-Element ueberbrueckt die Luecke: es setzt UNTER dem farbigen
   Trennbalken an (top: 100% + Balkenhoehe) und fuellt genau den Abstand.
   Der Balken selbst bleibt dadurch sichtbar und laeuft wie bisher ueber
   die Vorjahresspalten hinweg — nur die Flaeche darunter ist jetzt
   durchgehend unterlegt. Die Masse kommen als Variablen von der Zeile,
   sodass Balken/Abstand nur an EINER Stelle gepflegt werden. */
/* Nachbesserung 5 (N2): die Bruecken sind ERSATZLOS entfallen. Sie
   ueberbrueckten den Aussenabstand unter Trennzeilen — den gibt es nicht
   mehr, die Zeilen stossen direkt aneinander. Damit laeuft das Band
   ohnehin durch, ohne ein einziges Pseudo-Element.
   Sie waren ausserdem selbst Teil des Fehlers: ihr Startpunkt
   (top: 100% + --trennbalken) unterstellte einen Balken, der bei 113 von
   135 Zeilen gar nicht gezeichnet wurde, und sie malten als GESCROLLTER
   Inhalt in den Spalt, wo die Sticky-Abdeckung nicht hinreicht. */

/* In der Segmentansicht laufen die Zeilen unter den sticky linken Spalten
   durch (weisser Grund, z-index 1) — der Vergleichsstreifen liegt darunter
   und braucht daher keinen eigenen z-index. */

/* Der Vergleichsstreifen im Spaltenkopf traegt dieselbe Unterlegung,
   damit er optisch an den Zellen darunter haengt. */
.bwa-spaltenkopf .vorjahr-zelle {
  background: var(--kt-vorjahr-kopf);
}

/* ==========================================================================
   Punkt 4 (Optik-Etappe): vertikale Trennlinien ZWISCHEN den thematischen
   Spaltengruppen (Gesamt | Marke 1 | Marke 2 | …). Innerhalb einer Gruppe
   — Wert, %, % ∑ und der aufgeklappte Vorjahresblock — gibt es KEINE
   Linie: diese Spalten gehoeren zusammen.

   Die Klasse gruppenstart sitzt deshalb auf der ERSTEN Zelle jeder
   Segmentgruppe (der Wertspalte) und in beiden Kopfzeilen an derselben
   Stelle. Der negative linke Rand rueckt die Linie in die Mitte der
   column-gap (0,5rem), das gleich grosse Padding gibt die Textbreite
   zurueck — die Spaltenbreiten bleiben unveraendert. align-self: stretch
   zieht die Linie ueber die volle Zeilenhoehe (wie beim Vorjahresblock),
   sonst waere sie nur eine Textzeile hoch.
   ========================================================================== */

.bwa-zeile .gruppenstart {
  /* Deutlich sichtbar: nahezu schwarz und 2px statt der hellgrauen
     Haarlinie — die Trennung zwischen den thematischen Spalten ist die
     wichtigste Orientierung in der breiten Segmentansicht.
     Die Raender sind so gewaehlt, dass die Linie MITTIG in der
     column-gap (0,5rem) sitzt und die nutzbare Spaltenbreite exakt
     erhalten bleibt: margin -(0,25rem + 1px) verschiebt die Randbox,
     padding (0,25rem − 1px) gibt Rand und Linienbreite zurueck. */
  --linienbreite: 2px;
  border-left: var(--linienbreite) solid var(--farbe-gruppenlinie);
  margin-left: calc(-0.25rem - 1px);
  padding-left: calc(0.25rem - 1px);
}

/* Nur die Datenzeilen strecken: in der Gruppen-Kopfzeile richtet
   align-items: end die Koepfe bewusst an der Unterkante aus.

   Nachbesserung 3: der feste vertikale Negativrand ist entfallen — er war
   auf ein Zeilenpolster von 0,15rem geeicht und liess die Linie an den
   hoeheren DB-Zeilen (0,6rem) oben und unten offen. Das Polster kommt
   jetzt wie bei jeder Zelle aus --zeilen-polster (.bwa-zeile > span). */
.bwa-zeile:not(.bwa-kopf-gruppen) .gruppenstart {
  align-self: stretch;
}

/* Nachbesserung 5 (N2): auch hier ist die Ueberbrueckung ersatzlos
   entfallen — aus denselben Gruenden wie beim Vorjahresband (s. o.).
   Die Zeilen stossen direkt aneinander, die Trennlinie laeuft von der
   Kopfzeile bis zur letzten Zeile durch, ohne Pseudo-Element. */

/* Aufklapp-Symbol im Spaltenkopf: unauffaellige Schaltflaeche direkt
   hinter der Spaltenueberschrift; kein Button-Aussehen, damit der Kopf
   ruhig bleibt. */
.vorjahr-schalter {
  margin-left: 0.35rem;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 0.95em;
  line-height: 1;
  color: var(--farbe-kopf);
}

.vorjahr-schalter:hover,
.vorjahr-schalter:focus-visible {
  opacity: 0.7;
}

/* Einklappbare Bloecke (bwa.js): Kinder-Container und Summenzeile stehen
   in Datenreihenfolge im DOM (Kinder oben, Summe unten) — hier nur noch
   Sichtbarkeit und Symbol. Datenkonvention: die einklappbare Zeile ist
   die SUMMENZEILE UNTER ihrem Block. */
/* Ein zugeklappter Block verbirgt seine Inhaltszeilen — AUSSER den
   Kennzahlen-Zeilen (Durchgang E): stufen-sichtbare Kennzahlen bleiben
   als VORSCHAU stehen ("Alles einklappen" und trotzdem die wichtigen
   Kennzahlen sehen). Statt den Container zu verstecken, werden daher die
   NICHT-Kennzahl-Zeilen zeilenweise ausgeblendet — auf jeder
   Verschachtelungstiefe (Descendant-Selektor). Ein Block ohne Kennzahlen
   sieht damit unveraendert aus (alle Zeilen weg, leerer Container = 0
   hoch). Die .kennzahl-Zeilen behalten ihre helle Flaeche und ihre
   Position. Welche Stufen ueberhaupt gezeigt werden, entscheidet schon
   der serverseitige Stufen-Filter (praesentation) — hier stehen nur noch
   die sichtbaren Kennzahlen. */
.bwa-kinder.eingeklappt .bwa-zeile:not(.kennzahl) { display: none; }

/* Klick-Trennung (Etappe A): den Zeiger traegt nur noch der linke
   GRIFF (Symbol, Nummer, Bezeichnung) — die Zahlen rechts haben ihre
   eigene Drill-down-Affordanz weiter unten. Frueher war die ganze Zeile
   ein Zeiger, was beide Wirkungen gleich aussehen liess. */
.bwa-zeile.klappzeile .klappgriff { cursor: pointer; }

/* Dezenter Hinweis, dass der Griff der Schalter ist */
.bwa-zeile.klappzeile .klappgriff:hover,
.bwa-zeile.klappzeile .klappgriff:focus-visible {
  text-decoration: underline;
}

/* Klapp-Symbol in der festen ersten Spalte: nur Klappzeilen zeigen es,
   der Platz bleibt aber bei allen Zeilen gleich (buendige Nummern) */
.bwa-zeile.klappzeile .klapp::before { content: "\25BE"; }        /* ▾ */
.bwa-zeile.klappzeile.zugeklappt .klapp::before { content: "\25B8"; }  /* ▸ */

/* ==========================================================================
   Lade-Indikator (Etappe W5b): EIN zentraler CSS-Spinner (rotierender
   Bogen in der Kopfzeilen-Farbe, reine CSS-Animation) fuer alle Stellen,
   die spuerbar rechnen — Filter-/Dimensionswechsel und Drill-down-Modal.
   Der erste Seitenaufbau braucht bewusst keinen Spinner.
   ========================================================================== */

.spinner {
  display: inline-block;
  width: 2rem;
  height: 2rem;
  border: 3px solid var(--farbe-linie);
  border-top-color: var(--farbe-kopf);
  border-radius: 50%;
  animation: spinner-drehung 0.8s linear infinite;
}

@keyframes spinner-drehung {
  to { transform: rotate(360deg); }
}

/* Filter-/Dimensionswechsel: der Indikator (#bwa-laden, htmx-indicator)
   schwebt ohne Platzbedarf ueber dem Ergebnisbereich; htmx blendet ihn
   nur waehrend laufender Anfragen ein. */
.lade-ueberlagerung {
  position: relative;
  height: 0;
  z-index: 5;
}

.lade-ueberlagerung .spinner {
  position: absolute;
  left: 50%;
  top: 3rem;
  margin-left: -1rem;
}

/* Waehrend der Anfrage wird der alte Ergebnisinhalt leicht ausgegraut:
   sichtbar "es passiert etwas". WICHTIG: bei gesetztem hx-indicator
   vergibt htmx die Klasse htmx-request an das INDIKATOR-Element
   (#bwa-laden), nicht an das ausloesende Formular. */
#bwa-laden.htmx-request ~ #bwa-ergebnis {
  opacity: 0.4;
  pointer-events: none;
}

/* Drill-down: sofort beim Klick zeigt bwa.js dieses Modal-Geruest mit
   Spinner; HTMX ersetzt es durch den fertigen Inhalt. */
.modal.modal-laedt {
  max-width: 18rem;
  min-height: 9rem;
  align-items: center;
  justify-content: center;
}

/* Filterleiste (Etappe W3): drei Auswahlfelder + Ladehinweis. Der
   Ladehinweis nutzt htmx' eingebauten Indikator-Mechanismus
   (.htmx-indicator wird nur waehrend einer laufenden Anfrage sichtbar). */
/* Filterleiste in zwei logischen Zeilen (Punkt 2/Layout):
   Zeile 1 = Zeit-/Quelldimension (Händler | Geschäftsjahr | Monat |
   Werte), Zeile 2 = Ansicht/Aufteilung. Jede Zeile bricht bei schmalem
   Viewport für sich um (flex-wrap). */
.bwa-filter {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* Sticky unter der App-Kopfzeile (Punkt 3, gilt für ALLE Ansichten):
     Reihenfolge von oben App-Kopfzeile (z-index 10) -> Filterleiste
     (hier) -> Tabellen-Spaltenkopf (.bwa-kopfbereich, z-index 2). Der
     deckende Hintergrund lässt durchscrollende Zeilen dahinter
     verschwinden; die negativen Ränder + Padding dehnen den weißen
     Grund über die 1rem-Polsterung der .inhalt bis an die Kanten. */
  position: sticky;
  top: var(--hoehe-kopfzeile);
  z-index: 6;
  margin: 0 -1rem 0.4rem;
  /* R3: mehr Luft links und rechts. Die Kachel (::after) beginnt bei
     1rem — mit 1rem Polsterung sass der Inhalt GENAU auf ihrer
     Rundung. Die 1,9rem lassen 0,9rem Innenabstand INNERHALB der
     Kachel; oben/unten bleibt es beim bisherigen Mass. */
  padding: 0.7rem 1.9rem;
}

/* Erweiterung 5 — die Leiste in der Kachelsprache.
   ZWEI Schichten, weil zwei Anforderungen gegeneinander stehen:

   (1) V5a verlangt eine DECKENDE Flaeche ueber die volle Breite; sonst
       scheinen beim Scrollen Tabellenzeilen hinter der fixierten Leiste
       durch. Dafuer ::before, das bis an die Kanten reicht (die
       negativen Raender der Leiste eingerechnet).
   (2) Die Optik soll eine abgerundete Kachel sein — die kann per
       Definition nicht bis an die Kante laufen. Dafuer ::after, um 1rem
       eingerueckt (hebt die negativen Raender genau auf) mit Radius,
       Rahmen und Schatten aus den Kachel-Tokens.

   Beide liegen HINTER dem Inhalt (z-index -1) und innerhalb des
   Stapelkontexts der Leiste (die traegt z-index 6) — sie decken also
   weiterhin die Tabelle darunter ab. */
.bwa-filter::before,
.bwa-filter::after {
  content: "";
  position: absolute;
  z-index: -1;
}
.bwa-filter::before {
  inset: 0;
  background: var(--kt-bg);
}
.bwa-filter::after {
  inset: 0 1rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-lg);
  box-shadow: var(--kt-shadow-sm);
}

.bwa-filter-zeile {
  display: flex;
  gap: 0.7rem 1.1rem;
  align-items: center;
  flex-wrap: wrap;
}

.bwa-filter label {
  display: flex;
  gap: 0.45rem;
  align-items: center;
  font-size: 0.9rem;
  color: var(--kt-text-soft);
}

/* ==========================================================================
   Erweiterung 5 (Durchgang AQ): Bedienelemente der Filterleisten in der
   Kachel-Designsprache.

   GELTUNGSBEREICH: alles haengt an .bwa-filter — und diese Klasse tragen
   BEIDE Leisten (BWA und OnePager, siehe onepager_filter.html). Damit ist
   der gemeinsame Nenner die Huelle, nicht eine Liste von Einzelseiten;
   fremde Seiten bleiben unberuehrt (V8 sinngemaess).

   REINE OPTIK: kein Markup wurde angefasst. Die Controls behalten ihre
   Namen, Werte und HTMX-Ausloeser; die Haekchen bleiben echte
   <input type="checkbox"> mit klickbarem <label> (X1/X3).

   SAFARI: appearance wird IMMER doppelt gesetzt (-webkit- und
   ungepraefixt). Das ist die Lehre aus zwei frueheren Durchgaengen —
   ohne den Praefix zeichnet Safari seinen nativen Bevel weiter, sobald
   ein eigener Hintergrund gesetzt ist (vgl. .erfassung-zelle input und
   den Cache-Button in der Mapping-Verwaltung).
   ========================================================================== */

/* ---------- Selects: nativ, aber gestylt ---------- */
.bwa-filter select,
.kennzahl-wahl select {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.88rem;
  color: var(--kt-text);
  background-color: var(--kt-surface-2);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-sm);
  /* Rechts Platz fuer den eigenen Chevron. */
  padding: 0.4rem 2rem 0.4rem 0.7rem;
  line-height: 1.3;
  cursor: pointer;
  /* Feinschliff: dezenter Schlagschatten — Tiefe, kein Skeuomorphismus.
     Der Wert kommt aus dem Token, nicht als eigenes rgba (X4); er
     entspricht dem Richtwert 0 1px 2px, nur mit dem blauschwarzen Ton
     der uebrigen Schatten statt reinem Schwarz. */
  box-shadow: var(--kt-shadow-control);
  transition: border-color .15s ease, background-color .15s ease,
              box-shadow .15s ease;

  /* Eigenes Auswahl-Zeichen, aus zwei halbierten Verlaeufen gebaut: zwei
     0,32rem grosse Quadrate nebeneinander, im linken die obere rechte,
     im rechten die obere linke Haelfte gefuellt — zusammen ein nach
     unten zeigendes Dreieck.

     WARUM NICHT ALS SVG-DATA-URI: dort muesste die Farbe als Literal
     stehen, eine CSS-Variable ist in einem Data-URI nicht aufloesbar.
     Damit haette der Abschnitt eine zweite Farbquelle neben den Tokens
     (X4). Ein Verlauf nimmt var() an und bleibt token-rein. */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--kt-text-soft) 50%),
    linear-gradient(135deg, var(--kt-text-soft) 50%, transparent 50%);
  background-size: 0.32rem 0.32rem;
  background-repeat: no-repeat;
  background-position: right 0.92rem center, right 0.6rem center;
}

.bwa-filter select:hover,
.kennzahl-wahl select:hover,
.bwa-filter select:focus-visible,
.kennzahl-wahl select:focus-visible {
  border-color: var(--kt-accent);
  background-color: var(--kt-surface);
  box-shadow: var(--kt-shadow-anheben);
}

/* Fokus deutlich sichtbar (X3) — derselbe Ring an allen Controls. */
.bwa-filter select:focus-visible,
.kennzahl-wahl select:focus-visible,
.bwa-filter button:focus-visible,
.bwa-filter a:focus-visible,
.bwa-filter input[type="checkbox"]:focus-visible,
.klapp-master:focus-visible,
.filter-schalter:focus-visible {
  outline: 2px solid var(--kt-accent);
  outline-offset: 2px;
}

/* ---------- Haekchen als Pill-Schalter ----------
   Technisch bleibt es die echte Checkbox; sie wird nur neu gezeichnet.
   Der Schalter sitzt im <label>, das Label bleibt also klickbar und
   Screenreader lesen unveraendert Beschriftung + Zustand. */
.nullzeilen-schalter,
.onepager-leere {
  gap: 0.55rem !important;
  font-size: 0.85rem;
  color: var(--kt-text-soft);
  cursor: pointer;
  background: var(--kt-surface-2);
  border: 1px solid var(--kt-border);
  border-radius: 999px;
  padding: 0.35rem 0.85rem 0.35rem 0.6rem;
  transition: border-color .15s ease, background .15s ease;
}
.nullzeilen-schalter:hover,
.onepager-leere:hover { border-color: var(--kt-accent); }

/* Der Schalter selbst: Spur + Knauf, beides aus Tokens. */
.nullzeilen-schalter input[type="checkbox"],
.onepager-leere input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  flex: none;
  width: 2rem;
  height: 1.1rem;
  margin: 0;
  border-radius: 999px;
  /* Ausgeschaltete Spur: aus den Tokens gemischt statt als eigener
     Farbwert. --kt-border waere gegen die weisse Flaeche zu blass, um
     als Schalter erkennbar zu sein. */
  background: color-mix(in srgb, var(--kt-text-faint) 60%, var(--kt-surface));
  cursor: pointer;
  transition: background .15s ease;
}
.nullzeilen-schalter input[type="checkbox"]::after,
.onepager-leere input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 999px;
  background: var(--kt-surface);
  box-shadow: var(--kt-shadow-sm);
  transition: transform .15s ease;
}
.nullzeilen-schalter input[type="checkbox"]:checked,
.onepager-leere input[type="checkbox"]:checked {
  background: var(--kt-accent);
}
.nullzeilen-schalter input[type="checkbox"]:checked::after,
.onepager-leere input[type="checkbox"]:checked::after {
  transform: translateX(0.9rem);
}
/* Eingeschalteter Zustand auch am Label ablesbar — nicht nur am Knauf. */
.nullzeilen-schalter:has(input:checked),
.onepager-leere:has(input:checked) {
  background: var(--kt-accent-soft);
  border-color: var(--kt-accent);
  color: var(--kt-text);
}

/* ---------- Buttons als Pills ----------
   Primaeraktion (PDF) dunkel, Sekundaeraktionen dezent. */
.bwa-pdf,
.onepager-pdf {
  border-radius: 999px;
  padding: 0.45rem 1rem;
  font-size: 0.85rem;
  font-weight: 600;
  transition: background .15s ease, transform .15s ease;
}
.bwa-pdf:hover,
.onepager-pdf:hover { transform: translateY(-1px); }

.klapp-master,
.filter-schalter,
.monat-pfeil {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  border: 1px solid var(--kt-border);
  background: var(--kt-surface);
  color: var(--kt-text);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.klapp-master:hover,
.filter-schalter:hover:not(:disabled),
.monat-pfeil:hover:not(:disabled) {
  border-color: var(--kt-accent);
  color: var(--kt-accent);
  background: var(--kt-accent-soft);
}

/* ---------- Feinschliff: EINE Form fuer alle Schaltflaechen ----------
   Bis hierher waren nur die Bedienelemente der BWA-Leisten Pills. Die
   uebrigen Schaltflaechen der Anwendung standen weiter auf
   border-radius: 3px (Abmelden, Anmelden, Passwort vergessen) oder
   ganz ohne Regel als native Browser-Buttons da (Hochladen, Filtern,
   Uebernehmen, Anzeigen, Code senden …). Nebeneinander gestellt war
   das der auffaelligste Bruch — deshalb hier die gemeinsame Form.

   NUR DIE FORM ist gemeinsam. Die Hierarchie bleibt, wo sie war:
   dunkel = Primaeraktion (PDF, Anmelden, Ergaenzung/Ersatz), hell mit
   Rahmen = Sekundaeraktion (Alles einklappen, Passwort vergessen).

   WO DIE RUNDUNG STEHT: an der jeweils EIGENEN Regel der Schaltflaeche
   (.logout-formular button, .knopf-primaer & Co., .import-option
   button), nicht als Sammelregel hier. Erster Versuch war die
   Sammelregel an dieser Stelle — sie blieb an „Anmelden" wirkungslos,
   weil .knopf-primaer seinen border-radius WEITER UNTEN bei gleicher
   Spezifitaet noch einmal setzt und die spaetere Regel gewinnt. Am
   Ursprung geaendert gibt es diese Frage gar nicht.

   Grundform fuer die klassenlosen Aktions-Buttons der Fachseiten.
   In :where(), also mit Spezifitaet NULL: das ist eine BASIS, keine
   Ansage. Jede seitenspezifische Regel (z. B. .import-option button)
   ueberstimmt sie weiterhin ohne Spezifitaets-Arithmetik — dieselbe
   Lehre wie bei den Kartenregeln in Nachbesserung 1.

   :not([class]) grenzt sauber ab: die eigens gestalteten Buttons
   (.reiter, .modal-schliessen, .monat-pfeil, .filter-schalter,
   .klapp-master, .vorjahr-schalter) tragen alle eine Klasse und
   bleiben unberuehrt. */
:where(.inhalt form button:not([class])) {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  padding: 0.4rem 1.1rem;
  border: 1px solid var(--kt-border);
  border-radius: 999px;
  background: var(--kt-surface);
  color: var(--kt-text);
  cursor: pointer;
  box-shadow: var(--kt-shadow-control);
  transition: border-color .15s ease, color .15s ease,
              background .15s ease, box-shadow .15s ease;
}
:where(.inhalt form button:not([class]):hover) {
  border-color: var(--kt-accent);
  color: var(--kt-accent);
  background: var(--kt-accent-soft);
}
:where(.inhalt form button:not([class]):focus-visible) {
  outline: 2px solid var(--kt-accent);
  outline-offset: 2px;
}

/* ---------- Kein Nachspringen beim HTMX-Tausch ----------
   Die Leiste wird per hx-swap-oob komplett ersetzt. Ein frisch
   eingefuegtes Element startet zwar ohne Uebergang — waehrend der
   Settle-Phase setzt HTMX aber Klassen, und eine Stilaenderung dort
   WUERDE animieren. Der Schalter soll seinen Zustand gerendert
   bekommen, nicht animiert aufgebaut. */
.bwa-filter.htmx-swapping *,
.bwa-filter.htmx-settling *,
.bwa-filter.htmx-added * {
  transition: none !important;
}

/* Monats-Wähler mit Blätterpfeilen (‹ [Dropdown] ›), optisch wie ein
   Filter-Label; die Pfeile springen zum nächsten vorhandenen Monat. */
.monat-wahl {
  display: flex;
  gap: 0.3rem;
  align-items: center;
  font-size: 0.9rem;
}

/* Erweiterung 5: runde Schaltflaeche statt eckigem Kaestchen. Feste
   Groesse, damit beide Pfeile links und rechts des Dropdowns gleich
   wirken; Rahmen/Farben kommen aus der gemeinsamen Button-Regel oben. */
.monat-pfeil {
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  font-size: 0.95rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.monat-pfeil:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Zähler am Nullzeilen-Schalter: Anzahl der ausgeblendeten Zeilen */
.nullzeilen-anzahl {
  color: #4a5361;
  font-size: 0.8rem;
}

/* Fallback-Marker der objektiven Ansicht (FA-44-02): Kostenzeile mit
   Trigger-Summe 0 — Umlage nicht möglich, Buchhaltungswerte gezeigt */
.fallback-marker {
  font-size: 0.75em;
  color: #8a6d1a;
  cursor: help;
}

/* ==========================================================================
   BWA objektiv (FA-44-02): durchgängige Modus-Farbkennzeichnung
   ==========================================================================
   Sämtliche Akzente der Liste (Spaltenkopf-/Summenzeilen-Linien,
   Blockende-Trenner, Seitenumbruch, Lade-Spinner) hängen an der
   CSS-Variable --farbe-kopf: der Modus-Wrapper stellt sie auf ein
   gedämpftes Blaugrün um — EIN Override, alles folgt. Farbe ist dabei
   nur Zusatzsignal: H1 und Stand-Zeile tragen "objektiv" in Text
   (Zugänglichkeit; Kontrast #0f5e57 auf Weiß ≈ 6,8:1). */
/* Objektiv-Modus (Kosten umgelegt): die TABELLE wird NICHT mehr
   umgefaerbt — ihre Flaechen gehoeren den Abteilungen. Kennzeichnung
   jetzt auf den OBEREN Leisten: Titel, Statuszeile und Filterleiste
   tragen den Modus-Grundton (gesaettigter als das GW-Pastell). Farbe
   ist Zusatzsignal: der Text traegt "objektiv" weiterhin (Zugaeng-
   lichkeit).

   EINE QUELLE fuer den Leisten-Zustand (Durchgang: Objektiv-Leisten-Fix).
   Der Modus-Marker steht ausschliesslich am .bwa-modus-Wrapper INNERHALB
   von #bwa-ergebnis — dem HTMX-Hauptziel, das jeder Filterwechsel
   zuverlaessig und als Letztes tauscht. Titel (#bwa-titel) und
   Filterleiste (.bwa-filter) liegen AUSSERHALB dieses Ziels und wurden
   bisher per hx-swap-oob je fuer sich umgeschaltet; bei ueberlappenden
   Anfragen (Haekchen 'Marken gruppieren' setzen und kurz darauf den
   Modus wechseln) konnten die oob-Leisten dem Hauptziel HINTERHERHINKEN
   und fibu behalten, obwohl die Tabelle schon objektiv war — die Leisten
   blieben weiss. Darum leiten Titel und Filterleiste ihre Farbe jetzt
   per :has() aus GENAU diesem einen Marker ab: sie koennen gar nicht
   mehr auseinanderlaufen, und kuenftige Leisten/Pfade erben die Regel
   automatisch (die Modus-Klasse steht nur noch am Wrapper, nicht mehr an
   Titel/Filterleiste). */
.bwa-modus.modus-objektiv .bwa-stand {
  background: var(--objektiv-hintergrund);
  color: #14432a;
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 3px;
}
.inhalt:has(.bwa-modus.modus-objektiv) #bwa-titel {
  color: var(--objektiv-linie);
}
/* Filterleiste im Objektiv-Modus flaechig hinterlegt (Menueleiste oben) */
.inhalt:has(.bwa-modus.modus-objektiv) .bwa-filter {
  background: var(--objektiv-hintergrund);
  border-radius: 4px;
  padding: 0.3rem 0.5rem;
  box-shadow: inset 0 0 0 1px var(--objektiv-linie);
}

.bwa-stand {
  color: #4a5361;
  font-size: 0.9rem;
}

/* ==========================================================================
   Einklappbare Filterleiste (Durchgang I)
   ==========================================================================
   Der Klappzustand sitzt als Klasse filter-zu am STABILEN Wrapper
   #bwa-kopf (kein HTMX-Swap-Ziel) — er ueberlebt darum jeden Swap aus
   EINER Quelle, und die oob-getauschte Filterleiste kann ihm nicht mehr
   hinterherhinken. Eingeklappt verschwindet die ganze Leiste (display
   none -> offsetHeight 0, --hoehe-filter faellt auf 0, der sticky
   Tabellenkopf dockt lueckenlos direkt unter die App-Kopfzeile). Sichtbar
   bleiben Titel und Statuszeile; letztere traegt weiter die Modusfarbe
   (Objektiv-:has()-Regel, .bwa-stand ist ihr Nachfahre). */
#bwa-kopf.filter-zu .bwa-filter {
  display: none;
}

/* Statuszeile + Klappschalter in einer Reihe. Der Schalter ist der
   Chevron-Button; zusaetzlich klappt die Statuszeile selbst (beide tragen
   data-filter-schalter, bwa.js hoert delegiert).

   Sticky (Durchgang K): dockt unter der App-Kopfzeile + Filterleiste, in
   ALLEN drei Ansichten gleich. Deckender Hintergrund + Rand-Bleed (wie die
   Filterleiste), damit durchscrollende Zeilen nicht durchscheinen; die
   Objektiv-Farbe liegt weiter NUR um den Text (.bwa-stand, inline-block),
   die Leiste selbst bleibt weiss. */
.bwa-stand-leiste {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  flex-wrap: wrap;
  position: sticky;
  top: calc(var(--hoehe-kopfzeile) + var(--hoehe-filter));
  z-index: 5;
  margin: 0 -1rem;
  /* R3: dieselbe Innenpolsterung wie die Filterleiste. */
  padding: 0.35rem 1.9rem;
}
/* Erweiterung 5: runde Schaltflaeche; Rahmen/Farben aus der gemeinsamen
   Button-Regel. Der Schalter traegt die V5a-Mechanik (Leiste ein-/
   ausklappen) unveraendert — nur seine Optik hat sich geaendert. */
.filter-schalter {
  width: 1.7rem;
  height: 1.7rem;
  padding: 0;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  /* Feinschliff: dieselbe Schattenstufe wie die Selects — alle
     angehobenen Bedienelemente sprechen EINE Sprache. */
  box-shadow: var(--kt-shadow-control);
}
.filter-chevron {
  display: inline-block;
  font-size: 0.8rem;
  transition: transform 0.15s ease;
}
/* Eingeklappt zeigt der Chevron nach rechts (aufklappbar) — reines
   CSS ueber den Wrapper-Zustand, kein zweiter Zustandstraeger. */
#bwa-kopf.filter-zu .filter-chevron {
  transform: rotate(-90deg);
}
/* Die Statuszeile ist ebenfalls anklickbar (Klappflaeche). */
.bwa-stand[data-filter-schalter] {
  cursor: pointer;
}

/* Hinweis: Monatswert gewählt, aber Vormonat fehlt (Punkt 3) */
.bwa-monatswert-hinweis {
  color: #8a5a00;
  background: #fdf3e2;
  border-left: 3px solid #d89a3f;
  padding: 0.3rem 0.6rem;
  font-size: 0.85rem;
  margin: 0.2rem 0 0.6rem;
}

/* ==========================================================================
   Drill-down je BWA-Zeile (Etappe W5, FA-44-10 Sicht a)
   ========================================================================== */

/* Klickbare Wert-Zellen der Werte-Zeilen: Zeiger + dezenter Hover */
.bwa-zeile .drilldown {
  cursor: pointer;
  border-radius: 2px;
}

.bwa-zeile .drilldown:hover,
.bwa-zeile .drilldown:focus-visible {
  background: #e8eef6;
  text-decoration: underline;
}

/* Modal-Overlay: liegt ueber ALLEN Sticky-Ebenen (Kopfzeile z-index 10) */
.modal-hintergrund {
  position: fixed;
  inset: 0;
  background: rgba(28, 30, 33, 0.45);
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1rem 1.5rem;
}

.modal {
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
  width: 100%;
  max-width: 75rem;
  max-height: calc(100vh - 5rem);
  display: flex;
  flex-direction: column;
}

.modal-kopf {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  padding: 0.8rem 1rem 0.6rem;
}

.modal-kopf h2 {
  margin: 0;
  font-size: 1.05rem;
}

.modal-untertitel {
  margin: 0.2rem 0 0;
  color: #4a5361;
  font-size: 0.85rem;
}

.modal-schliessen {
  border: none;
  background: transparent;
  font-size: 1.05rem;
  line-height: 1;
  padding: 0.3rem 0.4rem;
  cursor: pointer;
  color: #4a5361;
}

.modal-schliessen:hover { color: #000; }

/* Reiter-Leiste: "Kontenliste" aktiv, "12-Monats-Verlauf" nur Platzhalter */
.modal-reiter {
  display: flex;
  gap: 0.4rem;
  padding: 0 1rem;
  border-bottom: 1px solid var(--farbe-linie);
  /* Reiter und Export-Knoepfe duerfen in eine zweite Zeile brechen —
     bei ~360 px Breite passen sie nicht nebeneinander, und nichts darf
     aus dem Modal ragen (Lektion aus der Zugangskarte, AQ/S5). */
  flex-wrap: wrap;
  align-items: flex-end;
  row-gap: 0.3rem;
}

/* Export-Knoepfe in der Reiterzeile (AR-Nachtrag): rechtsbuendig ueber
   auto-Rand. Beim Umbruch bleiben sie rechtsbuendig — in der zweiten
   Zeile stehen sie dann unter dem rechten Rand der Reiter. Gemessen bei
   360 px: Leiste 60 px hoch (zwei Zeilen), Knopfgruppe 225..344 im
   360er-Rahmen, kein Ueberstand, kein waagerechter Dokument-Scroll. */
.modal-reiter .reiter-export {
  display: flex;
  gap: 0.4rem;
  margin-left: auto;
  /* Mittig zur Reiterzeile, nicht auf deren Grundlinie: die Reiter
     sitzen ueber align-items:flex-end auf der Trennlinie (der aktive
     ueberdeckt sie), Werkzeuge daneben gehoeren auf die Mitte. */
  align-self: center;
}

/* DEUTLICH kompakter als die Knoepfe unter der Tabelle: sie stehen hier
   neben Reitern, nicht allein, und sollen als WERKZEUG daneben lesen,
   nicht als zwei weitere Reiter.
   Gemessen war der erste Anlauf 0,88 der Reiterhoehe — zu nah dran.
   Massstab ist jetzt die kleine Pille der Statuszeile (.klapp-mehr):
   0.7rem, line-height 1, schmales Polster.
   Die Pill-Form (border-radius 999px) kommt unveraendert aus
   .knopf-sekundaer und wird hier NICHT angefasst — die
   Reihenfolge-Falle aus AQ. */
.modal-reiter .reiter-export .knopf-sekundaer {
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.2rem 0.65rem;
}

.modal-reiter .reiter {
  border: 1px solid var(--farbe-linie);
  border-bottom: none;
  border-radius: 3px 3px 0 0;
  background: #f3f4f6;
  padding: 0.3rem 0.8rem;
  font-size: 0.9rem;
  cursor: default;
}

.modal-reiter .reiter.aktiv {
  background: #fff;
  border-color: var(--farbe-kopf);
  font-weight: 700;
  color: var(--farbe-kopf);
  /* ueberdeckt die Trennlinie der Leiste -> wirkt verbunden */
  position: relative;
  top: 1px;
}

.modal-reiter .reiter:disabled {
  color: #9aa1ab;
  cursor: not-allowed;
}

/* Ein Reiter mit hx-get ist anklickbar (Etappe B) */
.modal-reiter .reiter[hx-get] { cursor: pointer; }

.modal-reiter .reiter[hx-get]:hover { background: #e8eef6; }

/* Lade-Feedback des Reiterwechsels OHNE DOM-Eingriff: HTMX setzt fuer
   die Dauer der Anfrage htmx-request am ausloesenden Element. Wichtig,
   weil der 12-Monats-Verlauf zwoelf Auswertungslaeufe rechnet und
   spuerbar Zeit braucht — der Klick darf nicht ignoriert wirken. */
.modal-reiter .reiter.htmx-request {
  color: #9aa1ab;
  cursor: progress;
}

.modal-reiter .reiter.htmx-request::after {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-left: 0.45em;
  vertical-align: -1px;
  border: 2px solid var(--farbe-kopf);
  border-right-color: transparent;
  border-radius: 50%;
  animation: spinner-drehung 0.7s linear infinite;
}

/* ==========================================================================
   13-Monats-Verlauf (Etappe C, FA-44-10 Sicht b)

   Querformat: Grafik oben, darunter Monatsbeschriftung und die zwei
   Wertreihen — alles im SELBEN waagerecht scrollenden Bereich und mit
   derselben Spaltenbreite (--spalte, gesetzt vom Template aus
   praesentation.VERLAUF_SPALTE), damit Saeulen und Zahlen ohne
   Ausrichtungsrechnerei uebereinander stehen. Die Beschriftungsspalte
   links bleibt beim Scrollen stehen (sticky).
   ========================================================================== */

/* Der Verlauf braucht mehr Platz als Kontenliste/Formel.
   EINPASS-KASKADE STUFE (a): das Modal beharrt nicht auf einer festen
   Breite, sondern waechst mit seinem Inhalt bis zur Viewport-Breite.
   min-width haelt die bisherige Breite als Untergrenze — schmale
   Inhalte (%-Modus) sollen das Modal nicht zusammenschnurren lassen. */
.modal.modal-breit {
  width: fit-content;
  min-width: min(96vw, 1100px);
  max-width: 96vw;
}

/* Breite bestimmen soll allein der VERLAUF, nicht die Fliesstexte
   darunter: ohne das zieht der laengste Satz (Fussnote, Legende) das
   fit-content-Modal auf seine eigene Zeilenlaenge auf, und neben einer
   schmalen %-Tabelle stuende dann viel Leerraum.
   width: 0 nimmt sie aus der Breitenrechnung heraus, min-width: 100%
   laesst sie trotzdem die volle Breite fuellen und umbrechen. */
.modal-breit .verlauf-modus,
.modal-breit .verlauf-legende,
.modal-breit .fussnote {
  width: 0;
  min-width: 100%;
}

.verlauf-modus {
  margin: 0 0 .6rem;
  font-size: .9rem;
  color: #4a5361;
}

.verlauf-flaeche {
  overflow-x: auto;
  padding-bottom: .2rem;
}

/* DIE EINE QUELLE ALLER BREITEN (Etappe G).

   --zeichen  kommt aus dem Template: die Zeichenzahl der breitesten
              formatierten Zelle des ANGEZEIGTEN Datensatzes (beide
              Reihen). Im %-Modus ('12,3 %') deutlich kleiner als in
              Euro ('(48.300.117)').
   --spalten  Anzahl Monatsspalten (13).
   --spalte   daraus die Spaltenbreite. Schriftrelativ (ch/em), NICHT in
              Pixeln: nur so schrumpfen Spalten und Grafik gemeinsam,
              wenn Stufe (b) der Kaskade die Schrift verkleinert.

   Warum ch: mit tabular-nums hat jede Ziffer die Breite von '0', also
   genau 1ch — die Zeichenzahl ist damit ein ehrliches Breitenmass und
   keine Schaetzung. Satzzeichen ('.', ',') sind schmaler, der Wert ist
   also eine Obergrenze; das kleine Plus an Luft ist gewollt.

   Die em-Untergrenze faengt kurze Werte ab: dort bestimmt nicht mehr die
   Zahl die Breite, sondern die Monatsbeschriftung ('Mai 25' —
   Buchstaben sind breiter als Ziffern).

   ACHTUNG bei Aenderungen: --spalte enthaelt schriftrelative Einheiten
   und wird an dem Element aufgeloest, das sie BENUTZT. Sie darf deshalb
   nur an Stellen mit gleicher Schrift benutzt werden — hier
   ausschliesslich am colgroup. An den Zellen aufgeloest ergab sie im
   fetten Tabellenkopf 2,6 px mehr je Spalte als im normalen Text, und
   die Grafik lief um bis zu 30 px davon. */
.verlauf-inhalt {
  font-size: .82rem;
  --verlauf-beschriftung: 6.6em;
  --spalte: max(4.6em, calc(var(--zeichen, 10) * 1ch + .8em));
  display: inline-block;
  min-width: 100%;
}

/* EINPASS-KASKADE STUFE (b): eine einzige Stufe kleiner, mit definierter
   Untergrenze — keine stufenlose Verkleinerung bis zur Unlesbarkeit.
   Gesetzt von bwa.js, wenn der Bereich sonst waagerecht scrollen
   muesste. Weil ALLE Breiten oben schriftrelativ sind, schrumpfen
   Spalten, Beschriftungsspalte und Grafik hier gemeinsam — die
   Ausrichtung bleibt unberuehrt. */
.verlauf-inhalt.verlauf-eng { font-size: .70rem; }

/* Die Grafik sitzt in einer Zelle ueber ALLEN Monatsspalten und fuellt
   sie vollstaendig. Ihre Breite ist damit per Tabellenlayout exakt die
   Breite der 13 Spalten — es gibt gar keine zweite Breitenangabe mehr,
   die davon abweichen koennte. */
/* Spezifitaet bewusst ueber die Tabelle: die allgemeine Zellenregel
   weiter unten setzt Padding und Rahmen und wuerde sonst gewinnen —
   schon 4 px Innenabstand ruecken die Grafik gegen ihre Spalten. */
table.verlauf .verlauf-grafikzelle {
  padding: 0;
  border: 0;
  vertical-align: bottom;
}

table.verlauf .verlauf-grafikzeile .verlauf-ecke {
  padding: 0;
  border: 0;
}

.verlauf-grafik {
  display: block;
  width: 100%;
  height: var(--grafik-hoehe, 130px);
  overflow: visible;
}

/* Strichstaerken duerfen von der waagerechten Streckung nicht beruehrt
   werden (sonst waere eine senkrechte Linie im schmalen Modus duenner
   als im breiten). */
.verlauf-grafik line,
.verlauf-grafik polyline { vector-effect: non-scaling-stroke; }

.verlauf-nulllinie { stroke: #98a1ad; stroke-width: 1; }

/* Geschaeftsjahr-Wechsel: dort setzt die kumulierte Reihe zurueck */
.verlauf-gj-grenze {
  stroke: var(--farbe-kopf);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: .55;
}

/* Saeulen = Monatswerte. Richtung UND Farbe unterscheiden das Vorzeichen,
   damit die Unterscheidung nicht allein an der Farbe haengt. */
.verlauf-saeule.positiv { fill: var(--farbe-kopf); }
.verlauf-saeule.negativ { fill: #b4553f; }

/* Linie = kumuliert, auf EIGENER Skala -> bewusst dezent (duenn,
   gestrichelt), damit sie nicht als zweite Saeulenreihe missgelesen wird */
.verlauf-linie {
  fill: none;
  stroke: #7a6a3f;
  stroke-width: 1.6;
  stroke-dasharray: 5 3;
  stroke-linejoin: round;
}

.verlauf-linienpunkt { fill: #7a6a3f; }

/* font-size: inherit, damit die schriftrelativen Breiten (--spalte) im
   colgroup dieselbe Schrift sehen wie der Rest des Verlaufs. */
table.verlauf {
  border-collapse: collapse;
  font-size: inherit;
  table-layout: fixed;
  width: min-content;
}

/* DIE Stelle, an der die Spaltenbreiten festgelegt werden — einmal, und
   unabhaengig von Schriftstaerke oder Inhalt der einzelnen Zellen. */
.verlauf-col-beschriftung { width: var(--verlauf-beschriftung); }
.verlauf-col-monat { width: var(--spalte); }

table.verlauf th,
table.verlauf td {
  /* border-box ist hier KEIN Detail: ohne sie zaehlt das Padding zur
     Breite hinzu und die Zelle wird breiter als ihre Spalte.
     Die BREITE selbst steht bewusst NICHT hier, sondern im colgroup
     (siehe oben) — an der Zelle aufgeloest haengt sie an deren
     Schriftstaerke. */
  box-sizing: border-box;
  overflow: hidden;
  /* Padding in em, nicht rem: es steckt in --spalte mit drin und muss
     mit der Schrift schrumpfen, sonst stimmt die Rechnung in Stufe (b)
     nicht mehr. */
  padding: .25em .3em;
  text-align: right;
  white-space: nowrap;
  /* tabular-nums ist die Voraussetzung der ch-Rechnung: nur mit
     Tabellenziffern ist jede Ziffer genau 1ch breit. */
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--farbe-linie);
}

table.verlauf thead th {
  border-bottom: 2px solid var(--farbe-kopf);
  font-weight: 600;
}

/* Beschriftungsspalte links: bleibt beim Querscrollen stehen */
table.verlauf .verlauf-ecke,
table.verlauf .verlauf-reihe {
  position: sticky;
  left: 0;
  z-index: 1;
  text-align: left;
  background: #fff;
  font-weight: 600;
}

/* Geschaeftsjahr-Grenze auch in der Tabelle sichtbar */
table.verlauf .gj-grenze {
  border-left: 1px dashed var(--farbe-kopf);
}

/* Monate ohne belastbaren Wert treten zurueck */
table.verlauf td.ohne-wert { color: #9aa1ab; }

.verlauf-legende {
  margin: .6rem 0 .2rem;
  font-size: .8rem;
  color: #4a5361;
}

.legende-marke {
  display: inline-block;
  width: .85em;
  height: .55em;
  margin: 0 .25em 0 .9em;
  vertical-align: 1px;
}

.legende-marke:first-child { margin-left: 0; }

.legende-marke.saeule { background: var(--farbe-kopf); }

.legende-marke.linie {
  height: 0;
  border-top: 2px dashed #7a6a3f;
}

/* Nur fuer Screenreader (leere Ecke der Tabelle braucht eine Bedeutung) */
.visuell-versteckt {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.modal-inhalt {
  overflow: auto;
  padding: 0.8rem 1rem 1rem;
}

/* Kontenliste als schlichte Tabelle */
table.buchungen {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.85rem;
}

.buchungen th,
.buchungen td {
  text-align: left;
  padding: 0.2rem 0.6rem 0.2rem 0;
  border-bottom: 1px solid var(--farbe-linie);
  white-space: nowrap;
}

.buchungen th { border-bottom: 2px solid var(--farbe-kopf); }

/* Zweizeilige Zellen: Primärwert (Kontonummer bzw. KRM-Code) prominent,
   darunter der aufgelöste Klartext klein/grau (recessed, wie die Nummern in
   der BWA). Konto-/KRM-Bezeichnung können lang sein -> max-width + Ellipsis,
   der volle Text steht im title-Attribut. */
.buchungen td.zelle-zwei { line-height: 1.25; vertical-align: top; }
.buchungen .zwei-primaer { display: block; }
.buchungen .zwei-sekundaer {
  display: block;
  font-size: 0.78em;
  color: #6b7280;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.buchungen td.zelle-konto .zwei-sekundaer { max-width: 22ch; }
.buchungen td.zelle-krm .zwei-sekundaer { max-width: 14ch; }

.buchungen .zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.buchungen tfoot td {
  font-weight: 700;
  border-top: 2px solid var(--farbe-kopf);
  border-bottom: none;
}

.buchungen .hinweis td {
  color: #6b7280;
  font-style: italic;
}

/* ==========================================================================
   Durchgang AQ — Karten, Deckungsbeitrags-Kaskade, Ergebnis-Ampel
   (Redesign nach Andreas' Entwurf)

   GRUNDREGEL DIESES ABSCHNITTS: jede Regel, die eine Zeilenflaeche faerbt,
   setzt ZUGLEICH --abt-pastell auf denselben Wert. Die deckenden
   Sticky-Spalten (Punkt 4/5) lesen genau diese Variable — ohne das
   Mitziehen bliebe beim Seitwaertsscrollen ein weisser Streifen ueber der
   farbigen Zeile stehen. Das ist die Bedingung, unter der Karten und
   fixierte Spalten zusammen funktionieren (V4 + V5c).
   ========================================================================== */

/* ---------- Klappgruppe als Karte (V4) ---------- */

/* Aufgeklappt: sichtbar zusammengehoerige Flaeche aus Kind-Zeilen und
   ihrer Ergebniszeile. KEIN overflow:hidden — das machte die Karte zu
   einem eigenen Scroll-Kontext und braeche die Sticky-Spalten (der
   Entwurf meidet es am Listencontainer aus demselben Grund). Die runden
   Ecken kommen stattdessen ueber border-radius an den Randzeilen. */
/* Nachbesserung 3: der Kartenrahmen ist ein INSET-SCHATTEN, keine
   Border, und die Karte hat keine Aussenabstaende mehr.

   Beides dient EINEM Zweck: die vertikalen Marken-Trennlinien haengen an
   der Rasterkante der Zellen (.gruppenstart). Eine Border rueckt den
   Karteninhalt um ihre Breite ein — jede Zeile in einer Karte sass damit
   1px weiter rechts als eine Zeile ausserhalb, verschachtelt entsprechend
   mehr, und die Linie sprang an jeder Kartengrenze. Der Inset-Schatten
   zeichnet denselben Rahmen OHNE Layout-Wirkung; die vertikalen
   Abstaende fielen weg, damit die Linie auch zwischen den Karten
   durchlaeuft (F1: Einheitlichkeit vor Feinoptik).

   Merksatz fuer spaeter: in der BWA-Liste darf KEIN Container den Inhalt
   horizontal einruecken — weder Border noch Padding noch Margin. Sonst
   knickt die Linienflucht. */
/* Nachbesserung 4 korrigiert davon ZWEI Punkte — die Merksatz-Regel
   (kein Container rueckt horizontal ein) bleibt dabei unangetastet:

   K1: die Aussenabstaende kommen VERTIKAL zurueck. Ohne sie stiess die
   Karte unmittelbar an die Vorgaengerzeile, und die Kategorie-
   Beschriftung (::before) sass direkt auf ihr — der gemeldete Ueberlapp
   (im Browser gemessen: Kartenoberkante == Unterkante der Vorgaenger-
   zeile, auf 4 Nachkommastellen identisch). Bewusst in Kauf genommen:
   Vorjahresband und Marken-Trennlinien pausieren in diesen Luecken. Eine
   Kachelgrenze IST eine zulaessige Pause; das ist keine Regression,
   sondern die Abwaegung aus K1.

   K3: der Rahmen wandert von INSET nach AUSSEN. Ein inset-Schatten wird
   zwar innerhalb der Box gezeichnet, aber UNTER den Hintergruenden der
   Kinder — und die Zeilen der Karte fuellen die Box vollstaendig und
   deckend (im Browser gemessen: Kartenrechteck und Rechteck der ersten
   Zeile sind auf allen vier Kanten identisch). Der Rahmen war dadurch
   seit Nachbesserung 3 auf allen vier Seiten unsichtbar; ueberlebt hatte
   er nur bei den Kategorie-Karten, wo die ::before-Beschriftung einen
   Streifen der Kartenflaeche freilaesst. Die Karten-Optik der
   gewoehnlichen Klappgruppen ging also nicht durch eine geloeschte Regel
   verloren, sondern weil Rahmen und runde Ecken zugedeckt wurden.
   Ein Aussen-Schatten hat wie der inset KEINE Layout-Wirkung — die
   Linienflucht bleibt unberuehrt. */
.kt-block {
  margin-block: 0.4rem;
  margin-inline: 0;
  box-shadow: 0 0 0 1px var(--kt-border-soft);
  border-radius: var(--kt-radius);
  background: var(--kt-surface-2);
  /* K3: schmaler VERTIKALER Innenabstand, damit die eigene Flaeche der
     Karte mit ihren runden Ecken oben und unten sichtbar wird. Die
     Kinderzeilen sind rechteckig und deckend; ohne diesen Streifen
     stiessen sie quadratisch an die gerundete Kante. Nur vertikal —
     horizontales Polster bleibt verboten (Merksatz oben). */
  padding-block: 0.3rem;
}

/* Nachbesserung AQ (A4): KEIN horizontales Polster am Kinder-Container.
   Es verschob saemtliche Grid-Spalten der Kartenzeilen um 0,2rem gegen
   die Zeilen ausserhalb der Karte — sichtbar als Versatz der vertikalen
   Marken-Trennlinien. Das Grid-Raster muss fuer ALLE Zeilen identisch
   sein; die Karte darf es nicht verschieben. */
.kt-block > .bwa-kinder { padding: 0; }

/* Zeilen IN der Karte tragen die Kartenfarbe als VOLLTON. Der Entwurf
   setzt hier transparent; das ginge nicht, weil die Sticky-Spalten eine
   deckende Farbe brauchen (sie wuerden sonst durchscheinen lassen, was
   sie gerade verdecken sollen). Optisch identisch, technisch tragfaehig.

   Nachbesserung AQ (D1): die Kartenregeln stehen in :where(). Damit
   zaehlen sie mit Spezifitaet 0 und ueberschreiben NICHT mehr die
   Zustandsfarben der Zeile (DB-Stufe, Ampel). Genau das war die Ursache
   der fehlenden DB-Flaechen: eine DB-Zeile, die zugleich Klappzeile ist
   (24100, 34900, 33090 …), wurde von .kt-block > .bwa-zeile.klappzeile
   (drei Klassen) ueberstimmt und blieb weiss — waehrend die sonst
   gleichwertige Nicht-Klappzeile 14100 ihre Flaeche behielt. Die Daten
   waren dabei immer vollstaendig (90 von 90 DB-Zeilen gesetzt).

   EINE Variable statt vieler Sonderregeln: die Karte setzt
   --kt-karten-flaeche, und JEDE Zeile darin nimmt diesen Wert (als
   Hintergrund UND als --abt-pastell). Die Kategorien unten aendern nur
   noch die Variable. Dadurch tragen auch verschachtelte Karten
   automatisch die Farbe ihrer Umgebung (B2). */
.kt-block { --kt-karten-flaeche: var(--kt-surface-2); }

:where(.kt-block) .bwa-zeile {
  background: var(--kt-karten-flaeche);
  --abt-pastell: var(--kt-karten-flaeche);
  border-bottom: 1px solid var(--kt-border-soft);
}
:where(.kt-block) .bwa-zeile:last-child { border-bottom: none; }
:where(.kt-block) > .bwa-zeile.klappzeile {
  font-weight: 700;
  border-radius: 0 0 var(--kt-radius) var(--kt-radius);
}

/* Zugeklappt: eine GEWOEHNLICHE Klappgruppe tritt zurueck und liest sich
   wie eine normale Zeile der Liste (V4). Der Zustand wird NICHT doppelt
   gefuehrt — :has() liest den vorhandenen Merker .eingeklappt, den
   bwa.js ohnehin setzt.

   Nachbesserung AQ (B1): Kostenblock-Karten sind davon AUSGENOMMEN. Sie
   bleiben zugeklappt eine Karte (Toenung, Rahmen, runde Ecken,
   Kategorien-Beschriftung) — nur eben einzeilig. Deshalb :not([class*=
   "kt-fix"]) & Co. ueber die gemeinsame Marker-Klasse .kt-kategorie. */
.kt-block:not(.kt-kategorie):has(> .bwa-kinder.eingeklappt) {
  box-shadow: none;
  border-radius: 0;
  background: transparent;
  /* Nachbesserung 4 (K3): zugeklappt faellt auch die Karten-GEOMETRIE
     weg — Innenabstand und Aussenabstand. Sonst stuende die
     zusammengeklappte Gruppe mit Luft ober- und unterhalb in der Liste
     und laese sich gerade NICHT wie eine gewoehnliche Zeile. */
  padding-block: 0;
  margin-block: 0;
  --kt-karten-flaeche: var(--kt-surface);
}
:where(.kt-block:not(.kt-kategorie):has(> .bwa-kinder.eingeklappt))
    > .bwa-zeile.klappzeile {
  font-weight: inherit;
  border-radius: 0;
}

/* Zugeklappte Kategorie-Karte: die Summenzeile ist jetzt die EINZIGE
   Zeile der Karte und rundet deshalb oben wie unten. */
.kt-block.kt-kategorie:has(> .bwa-kinder.eingeklappt)
    > .bwa-zeile.klappzeile {
  border-radius: var(--kt-radius);
  border-top: none;
}

/* Verschachtelung (V4): ab der ZWEITEN Ebene nur noch eine leichte
   Toenung — sonst entstuende ein Karte-in-Karte-Schachbrett. Ab der
   dritten Ebene bleibt nur die Linie.

   Nachbesserung AQ (B2): die innere Karte bekommt KEINE eigene Flaeche —
   sie erbt die der umgebenden Karte. Vorher setzte sie background:
   transparent, ihre Klappzeile aber var(--kt-surface): eingeklappt stand
   dadurch eine weisse Linie mitten in der Fixkosten-Karte. */
.kt-block .kt-block {
  background: transparent;
  box-shadow: none;
  margin: 0;
  /* Nachbesserung 4 (K3): die Karten-Geometrie der Ebene 0 gilt NUR
     dort. Verschachtelt bleibt es bei der bestehenden Abstufung —
     keine eigene Flaeche, kein Rahmen, kein Polster, kein Abstand. */
  padding-block: 0;
  /* B2: KEINE eigene Flaeche — die innere Karte erbt die Farbe der
     umgebenden. Vorher stand hier eine eigene helle Flaeche, die
     eingeklappt als weisse Linie mitten in der Fixkosten-Karte auffiel. */
  --kt-karten-flaeche: inherit;
}

/* Nachbesserung 2 (F1): dieselbe Vererbung auch im ZUGEKLAPPTEN Zustand.
   Die Regel "gewoehnliche Karte tritt zugeklappt zurueck" traegt durch
   ihr :has() vier Klassen und ueberstimmte damit die Vererbungsregel
   darueber (zwei Klassen) — die innere Gruppe (z. B. 15300
   Vorfuehrwagenkosten) sprang deshalb auf Weiss zurueck und stand als
   heller Balken in der Fixkosten-Karte. Diese Regel steht danach und
   traegt selbst vier Klassen, gewinnt also. */
.kt-block .kt-block:has(> .bwa-kinder.eingeklappt) {
  --kt-karten-flaeche: inherit;
}
.kt-block .kt-block .kt-block {
  border-radius: 0;
}

/* ---------- Kategorie-Karten ----------
   Der Sonderfall "immer Karte" mit eigener Farbwelt. Die Zuordnung kommt
   aus dem Stammdatenfeld kostenblock, nicht aus dem Zeilentext (V1).

   Alle vier Kategorien folgen EINEM Bauplan: sie setzen nur ihre drei
   Werte (Flaeche, Rahmen, Akzentfarbe) — Mechanik und Beschriftung
   kommen aus den gemeinsamen Regeln darunter. Eine fuenfte Kategorie
   braeuchte damit genau drei Zeilen. */
.kt-block.kt-kategorie {
  background: var(--kt-karten-flaeche);
  /* Rahmen als Schatten — siehe .kt-block: eine Border wuerde den Inhalt
     einruecken und die Linienflucht knicken. Nachbesserung 4 (K3): AUSSEN
     statt inset, aus demselben Grund wie dort (die Kinderzeilen decken
     einen inset-Rahmen zu). */
  box-shadow: 0 0 0 1px var(--kt-kategorie-rand);
}
.kt-block.kt-kategorie > .bwa-zeile.klappzeile {
  color: var(--kt-kategorie-akzent);
  border-top: 1px solid var(--kt-kategorie-rand);
}
.kt-block.kt-kategorie > .bwa-zeile.klappzeile .zahl {
  color: var(--kt-kategorie-akzent);
}

.kt-block.kt-fix {
  --kt-karten-flaeche: var(--kt-fix-bg);
  --kt-kategorie-rand: var(--kt-fix-border);
  --kt-kategorie-akzent: var(--kt-fix);
}
.kt-block.kt-variabel {
  --kt-karten-flaeche: var(--kt-var-bg);
  --kt-kategorie-rand: var(--kt-var-border);
  --kt-kategorie-akzent: var(--kt-var);
}
/* Nachbesserung AQ (C1): Indirekte Kosten — kuehles Grau-Blau. Bewusst
   ruhiger als Fix/Variabel: der Block liegt zwischen DB III und DB IV und
   soll die DB-Meilensteine nicht ueberstrahlen. */
.kt-block.kt-indirekt {
  --kt-karten-flaeche: var(--kt-indirekt-bg);
  --kt-kategorie-rand: var(--kt-indirekt-border);
  --kt-kategorie-akzent: var(--kt-indirekt);
}
/* Kennzahlen — neutral hell, ohne eigene Farbaussage: Kennzahlen sind
   Ableitungen, keine Kostenart. */
.kt-block.kt-kennzahlen {
  --kt-karten-flaeche: var(--kt-kennzahlen-bg);
  --kt-kategorie-rand: var(--kt-kennzahlen-border);
  --kt-kategorie-akzent: var(--kt-kennzahlen);
}

/* Beschriftung der Kategorie-Karte — Nachbesserung 5 (N1).
   Sie ist jetzt eine ECHTE ZEILE (praesentation.kategorie_labelzeile,
   Klasse .kt-kategorie-label) und kein ::before mehr.

   Warum der Umbau: das ::before hing am Karten-Wrapper und war damit
   KEIN Grid-Element. Auf seiner Hoehe gab es keine einzige Zelle — im
   Browser nachgezaehlt: null. Daraus folgten drei der sechs Befunde:
   das Vorjahresband setzte auf Labelhoehe aus, die vertikalen
   Marken-Trennlinien brachen dort ab, und die Kachel-Abstaende
   rechneten das Label nicht mit (gemessen: 14,4px Luft ueber dem
   Label, 0px darunter — es klebte an seiner eigenen ersten Zeile und
   stand optisch in der Kachelluecke).
   Als Zeile bringt es seinen vollen Zellensatz mit; Band und Linien
   laufen dadurch von selbst durch, ohne eine einzige Sonderregel.

   Der Text kommt aus praesentation.KATEGORIE_TITEL, nicht mehr aus
   einer CSS-Variable: eine Beschriftung ist Inhalt. Das erledigt
   nebenbei die Kennzahlen-Karten, deren Kopfzeile (x9990) leer ist und
   den Block ohne das alte ::before gar nicht benannt haette. */
.bwa-zeile.kt-kategorie-label {
  font-size: 0.66rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--kt-kategorie-akzent);
  --zeilen-polster: 0.2rem;
}
/* Die Bezeichnung erbt Groesse und Gewicht der Zeile (sonst zoege die
   allgemeine .bezeichnung-Regel ihre eigene Schrift durch). */
.bwa-zeile.kt-kategorie-label .bezeichnung {
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  color: inherit;
}

/* ---------- Deckungsbeitrags-Kaskade ----------
   Vier Meilenstein-Stufen, gemischt aus der BEREICHSFARBE (--kt-db-base
   kommt von .bereich-XX): DB I am kraeftigsten, DB IV am hellsten.
   Der Fallback --kt-accent greift bei Zeilen ohne Bereich. */
.bwa-zeile.kt-db {
  /* Nachbesserung AQ (A1): die groessere Zeilenhoehe kommt jetzt ueber
     das Zellpolster — sonst deckten die Zellhintergruende (Vorjahresband,
     Trennlinien) nur den inneren Teil und rissen oben/unten auf. */
  --zeilen-polster: 0.6rem;
  border-radius: var(--kt-radius-sm);
  border-bottom: none;
  font-weight: 700;
  color: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 68%, black);
}
.bwa-zeile.kt-db .bezeichnung,
.bwa-zeile.kt-db .zahl { color: inherit; }
.bwa-zeile.kt-db .zahl { font-weight: 700; }

/* V3: KEIN vertikaler Aussenabstand (der Entwurf setzt margin: .5rem 0).
   Eine Luecke zwischen den Zeilen risse das Vorjahresband sichtbar auf —
   und das Band ist die Klammer, die die Vorjahresspalten als EINEN Block
   lesbar macht. Die optische Trennung tragen Radius und Flaeche. */
.bwa-zeile.kt-db { margin-block: 0; }

.bwa-zeile.kt-db-1 { background: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 34%, white); --abt-pastell: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 34%, white); }
.bwa-zeile.kt-db-2 { background: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 23%, white); --abt-pastell: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 23%, white); }
.bwa-zeile.kt-db-3 { background: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 14%, white); --abt-pastell: color-mix(in srgb, var(--kt-db-base, var(--kt-accent)) 14%, white); }
/* DB IV traegt seit Durchgang BA den VOLLTON der Bereichsfarbe — dieselbe
   Flaeche wie die Bereichs-UEBERSCHRIFT (Design-Review Andreas: „Neuwagen-
   Ueberschrift und DB IV Neuwagen identisch"). Der Abschluss einer
   Abteilung klammert damit sichtbar mit ihrem Anfang.

   KEINE zweite Hex-Konstante: --kt-bereich steht auf .bereich-XX und ist
   dort auf denselben Token gesetzt, den die Ueberschriftsregel benutzt
   (--kt-nw, --kt-gw …). Beide Chains enden also in derselben :root-
   Variablen, und die spiegelt farben.KT_BEREICHSFARBEN. Wer die
   Bereichsfarbe aendert, aendert beide.

   Kein color-mix mehr an dieser Stufe: 100 % einer Farbe IST die Farbe,
   und der Ausdruck haette den Ton nur verschleiert. */
.bwa-zeile.kt-db-4 { background: var(--kt-bereich, var(--kt-accent)); --abt-pastell: var(--kt-bereich, var(--kt-accent)); }

/* Auf dem Vollton ist die dunkle DB-Schrift (Bereichsfarbe 68 % auf
   Schwarz) nicht mehr lesbar — gemessen 1,5:1 bis 2,0:1. Sie weicht
   derselben weissen Schrift, die die Bereichs-Ueberschrift schon traegt;
   die Zeilennummer eingeschlossen, sonst bliebe sie als grauer Fleck
   stehen. Die Regel steht NACH .bwa-zeile.kt-db (gleiche Spezifitaet,
   spaetere Regel gewinnt) und vor der Ampel — eine Ergebniszeile
   ueberstimmt weiterhin beides. */
.bwa-zeile.kt-db-4,
.bwa-zeile.kt-db-4 .bezeichnung,
.bwa-zeile.kt-db-4 .nummer,
.bwa-zeile.kt-db-4 .zahl { color: var(--kt-bereich-schrift); }

/* Stufen-Etikett ("DB II") am rechten Rand. Der Text kommt aus
   data-kt-label und damit aus den Stammdaten (db_stufe), nicht aus einer
   Textanalyse im Browser. */
.bwa-zeile.kt-db::after {
  content: attr(data-kt-label);
  position: absolute;
  right: 0.85rem;
  top: -0.65rem;
  font-size: 0.6rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  background: inherit;
  padding: 0 0.4rem;
  opacity: 0.85;
}

/* Kennzahl-/Kursiv-Varianten ("Deckungsbeitrag II (€/%) pro NW") bleiben
   dezent: kein Etikett, leichteres Gewicht. */
.bwa-zeile.kt-db.kursiv,
.bwa-zeile.kt-db.kennzahl {
  --zeilen-polster: 0.4rem;
  font-weight: 500;
}
.bwa-zeile.kt-db.kursiv::after,
.bwa-zeile.kt-db.kennzahl::after { content: none; }

/* ---------- Ergebnis-Ampel ----------
   Gruen/rot nach dem GERECHNETEN Wert; die Klasse setzt der Server
   (praesentation._ampel), nicht ein Vorzeichen-Test am Text. */
.bwa-zeile.kt-ergebnis-positiv {
  background: var(--kt-ergebnis-pos-bg);
  --abt-pastell: var(--kt-ergebnis-pos-bg);
}
.bwa-zeile.kt-ergebnis-positiv .bezeichnung,
.bwa-zeile.kt-ergebnis-positiv .zahl { color: var(--kt-ergebnis-pos); }

.bwa-zeile.kt-ergebnis-negativ {
  background: var(--kt-ergebnis-neg-bg);
  --abt-pastell: var(--kt-ergebnis-neg-bg);
}
.bwa-zeile.kt-ergebnis-negativ .bezeichnung,
.bwa-zeile.kt-ergebnis-negativ .zahl { color: var(--kt-ergebnis-neg); }

/* ---------- Liste als Karte ---------- */
.bwa-liste {
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-lg);
  box-shadow: var(--kt-shadow);
  padding: 0.4rem;
}

.fussnote {
  margin: 0.5rem 0 0;
  color: #6b7280;
  font-size: 0.8rem;
}

.modal-leer { color: #4a5361; }

/* --------------------------------------------------------------------------
   Segment-Auswahl der Filterleiste (Durchgang AS): welche Marken-/
   Standortspalten angezeigt werden. Aufklappbare Haken-Liste im Muster
   des Excel-Filters, in der Kachel-/Pill-Sprache der Leiste.
   Die Liste liegt IMMER im Markup und wird hier ein-/ausgeblendet — ein
   nachgeladenes Fragment waere ein zweiter Zustandstraeger, der dem DOM
   hinterherhinken kann (Lehre aus dem Klapp-Split, AQ/T3).
   -------------------------------------------------------------------------- */
.seg-auswahl {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.seg-knopf {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.82rem;
  line-height: 1.2;
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--kt-border);
  border-radius: 999px;
  background: var(--kt-surface);
  color: var(--kt-text);
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--kt-shadow-control);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.seg-knopf:hover {
  border-color: var(--kt-accent);
  color: var(--kt-accent);
  background: var(--kt-accent-soft);
}
.seg-knopf:focus-visible,
.seg-liste button:focus-visible,
.seg-liste input:focus-visible {
  outline: 2px solid var(--kt-accent);
  outline-offset: 2px;
}
.seg-pfeil { font-size: 0.7em; margin-left: 0.3em; }

.seg-liste {
  display: none;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 30;
  min-width: 16rem;
  /* Nie breiter als der Bildschirm — dieselbe Deckelung wie bei den
     Zugangskarten (AQ/S5); eine lange Standortbezeichnung darf die
     Liste nicht aus dem Viewport schieben. */
  max-width: min(24rem, calc(100vw - 2rem));
  max-height: min(22rem, calc(100vh - 8rem));
  overflow-y: auto;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.5rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-lg);
  box-shadow: var(--kt-shadow);
  text-align: left;
}
.seg-auswahl.offen .seg-liste { display: flex; }

.seg-liste label {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0.22rem 0.35rem;
  border-radius: var(--kt-radius-sm);
  font-size: 0.82rem;
  cursor: pointer;
}
.seg-liste label:hover { background: var(--kt-accent-soft); }
.seg-alle {
  font-weight: 700;
  border-bottom: 1px solid var(--kt-border);
  border-radius: 0;
  margin-bottom: 0.25rem;
  padding-bottom: 0.4rem;
}
.seg-eintraege { display: flex; flex-direction: column; }
.seg-text { font-variant-numeric: tabular-nums; }
.seg-fuss {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--kt-border);
}
/* Die Pill-Form kommt aus .knopf-sekundaer und wird hier NICHT neu
   gesetzt (Reihenfolge-Falle aus AQ) — nur die Groesse. */
.seg-fuss .knopf-sekundaer {
  font-size: 0.78rem;
  padding: 0.25rem 0.9rem;
}

/* --------------------------------------------------------------------------
   Kontenlisten-Export (Durchgang AR): zwei Download-Knoepfe unter der
   Tabelle. Sie nutzen die vorhandene Pill-Klasse .knopf-sekundaer — die
   Form (border-radius 999px) kommt von dort und wird hier BEWUSST NICHT
   angefasst; nur Groesse und Anordnung sind Sache dieses Kontexts.
   Die hoehere Spezifitaet (.modal-export .knopf-sekundaer) stellt
   sicher, dass die kleinere Schrift gewinnt, ohne dass die Reihenfolge
   der Datei eine Rolle spielt.
   -------------------------------------------------------------------------- */
.modal-export {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.9rem;
}
.modal-export .knopf-sekundaer {
  font-size: 0.85rem;
  padding: 0.3rem 0.9rem;
}
.modal-export-hinweis {
  color: #6b7280;
  font-size: 0.8rem;
}

/* --------------------------------------------------------------------------
   Formel-Drill-down (Etappe A, Teil 2): Struktur + eingesetzte Werte.
   Beide Fassungen duerfen umbrechen (lange Zeilennamen) und bleiben
   trotzdem als Formel lesbar — daher grosszuegige Zeilenhoehe statt
   einer festen Zeile.
   -------------------------------------------------------------------------- */
.formel-block { margin-bottom: 1.2rem; }

.formel-titel {
  margin: 0 0 .35rem;
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #4a5361;
}

.formel-struktur,
.formel-werte {
  margin: 0;
  line-height: 1.7;
}

.formel-werte { font-variant-numeric: tabular-nums; }

.formel-gleich { margin: 0 .3rem; color: #4a5361; }

.formel-ergebnis { font-size: 1.05em; }

/* Gesperrte Referenz: bewusst nuechtern, kein Alarm — der Benutzer hat
   nichts falsch gemacht, ihm fehlt nur eine Freigabe. */
.formel-gesperrt {
  margin: 0;
  color: #4a5361;
  font-style: italic;
}

.formel-quelltext code {
  background: #f2f4f7;
  padding: .1rem .3rem;
  border-radius: 2px;
}

/* ==========================================================================
   Import-Seite (Upload-Etappe, FA-41-01/-06/-08)
   ========================================================================== */

.kopf-link {
  color: #fff;
  margin-right: 0.5rem;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.5);
}

.kopf-link:hover { border-bottom-color: #fff; }

.meldung { padding: 0.4rem 0.7rem; border-radius: 3px; }
.meldung-success { background: #e6f4ea; color: #1d6b34; }
.meldung-error { background: #fbeaea; color: #a1231b; }

.import-formular {
  display: flex;
  gap: 1rem;
  align-items: center;
  flex-wrap: wrap;
  margin: 0 0 1rem;
  padding: 0.7rem;
  border: 1px solid var(--farbe-linie);
  border-radius: 4px;
}

.import-formular label { display: flex; gap: 0.5rem; align-items: center; }

.import-hinweis { color: #4a5361; font-size: 0.9rem; }

table.import-historie {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9rem;
}

.import-historie th,
.import-historie td {
  text-align: left;
  padding: 0.25rem 0.6rem 0.25rem 0;
  border-bottom: 1px solid var(--farbe-linie);
  vertical-align: top;
}

.import-historie th { border-bottom: 2px solid var(--farbe-kopf); }
.import-historie .zahl { text-align: right; }

/* Statusfarben (FA-41-06): Punkt vor dem Status-Text */
.status-punkt {
  display: inline-block;
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: #9aa1ab;                          /* wartet: grau */
  margin-right: 0.25rem;
}

.import-status-laeuft .status-punkt { background: #1f6fd6; }  /* blau */
.import-status-ok .status-punkt { background: #1d8a3e; }      /* gruen */
.import-status-fehler .status-punkt { background: #c22013; }  /* rot */
.import-status-offen .status-punkt { background: #b98a1a; }   /* CLI offen */

.import-status-fehler .status { color: #a1231b; }

/* kleiner Spinner in der Historien-Zeile (dieselbe .spinner-Klasse) */
.spinner-klein {
  width: 0.85rem;
  height: 0.85rem;
  border-width: 2px;
  vertical-align: text-bottom;
}

pre.import-bemerkung {
  white-space: pre-wrap;
  max-width: 60rem;
  font-size: 0.8rem;
  color: #4a5361;
  margin: 0.3rem 0 0;
}

/* Warnung an einer erfolgreichen Import-Zeile (Durchgang BB). Bestehende
   Token, keine neue Farbfamilie: --kt-wartet ist seit AT der Ton fuer
   „hier passiert etwas, es ist kein Fehler" — genau die Lage eines
   Imports, der durchgelaufen ist und trotzdem etwas zu sagen hat. */
details.import-warnung > summary { color: var(--kt-wartet); }
.import-warnzeichen { margin-right: 0.15rem; }

/* Ergebnis-Kurzform des Workers (Durchgang AP): eine ruhige Zeile in
   derselben Spalte wie die Warnungen — der Fehlertext bleibt der
   auffaellige Teil. */
.import-ergebnis {
  display: block;
  font-size: 0.8rem;
  color: #4a5361;
}

/* Rueckfrage-Dialog Ergaenzung/Ersatz (FA-41-04) */
.import-optionen {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin: 1rem 0;
}

.import-option {
  flex: 1 1 18rem;
  max-width: 28rem;
  border: 1px solid var(--farbe-linie);
  border-radius: 4px;
  padding: 0.8rem;
}

/* Feinschliff Erweiterung 5: volle Pill; Farbe (Primaeraktion) bleibt. */
.import-option button {
  font-size: 1rem;
  font-weight: 700;
  padding: 0.4rem 1.2rem;
  border: 1px solid var(--farbe-kopf);
  border-radius: 999px;
  background: var(--farbe-kopf);
  color: #fff;
  cursor: pointer;
}

.import-option p { color: #4a5361; font-size: 0.9rem; }

/* Leiste des Master-Schalters: block-level und linksbuendig, damit der
   Button IMMER unterhalb der Stand-Zeile ganz links sitzt — unabhaengig
   vom Modus und vom uebrigen Zeileninhalt. Noetig, weil .bwa-stand im
   objektiven Modus inline-block ist (farbiger Grundton nur um den Text);
   ohne eigene Leiste rutschte der inline-block-Button daneben. */
.klapp-master-leiste {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  /* Sticky (Durchgang K): dockt unter App-Kopfzeile + Filter + Status,
     die unterste der drei Kopf-Leisten. Darunter kleben nur noch die
     Tabellen-Spaltenkoepfe. */
  position: sticky;
  top: calc(var(--hoehe-kopfzeile) + var(--hoehe-filter)
            + var(--hoehe-status));
  z-index: 4;
  margin: 0 -1rem;
  /* R3: dieselbe Innenpolsterung wie die Filterleiste. */
  padding: 0.4rem 1.9rem 0.5rem;
}

/* ---------- R3: die Statuszeile als EIGENE Kachel ----------
   Sie besteht aus ZWEI Leisten (Zusammenfassung; Klapp-Master +
   Kennzahlen-Stufe). Zusammengelegt werden sie NICHT: beide sind
   eigene Sticky-Ebenen mit eigenem Offset, und bwa.js misst ihre
   Hoehen getrennt (--hoehe-status, --hoehe-klappleiste). Ein
   Zusammenlegen waere ein Umbau der Klapp-Mechanik (X2).

   Stattdessen dieselbe Zwei-Schichten-Technik wie bei der
   Filterleiste — ::before deckt voll, ::after zeichnet die Kachel —
   und die beiden Kacheln werden optisch zu EINER: die obere rundet
   nur oben, die untere nur unten, dazwischen keine Fuge.

   Die Rundungs-Ausnahmen haengen an :has(+ …): steht die
   Klapp-Leiste NICHT direkt darunter (keine Bloecke, oder der
   Monatswert-Hinweis dazwischen), rundet die Statuszeile allein
   rundum. Kein Sonderfall im Template noetig. */
.bwa-stand-leiste::before,
.bwa-stand-leiste::after,
.klapp-master-leiste::before,
.klapp-master-leiste::after {
  content: "";
  position: absolute;
  z-index: -1;
}
.bwa-stand-leiste::before,
.klapp-master-leiste::before {
  inset: 0;
  background: var(--kt-bg);
}
.bwa-stand-leiste::after,
.klapp-master-leiste::after {
  inset: 0 1rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-lg);
  box-shadow: var(--kt-shadow-sm);
}
/* Obere Kachelhaelfte: unten offen, wenn die Klapp-Leiste folgt. */
.bwa-stand-leiste:has(+ .klapp-master-leiste)::after {
  border-bottom: none;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
/* Untere Kachelhaelfte: oben offen, wenn die Statuszeile davor steht. */
.bwa-stand-leiste:has(+ .klapp-master-leiste) + .klapp-master-leiste::after {
  border-top: none;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* Durchgang P: obere Leisten beim HORIZONTALEN Querscroll ECHT viewport-fix
   — position:fixed statt des JS-Ausgleichs aus O.

   O gab den Leisten transform:translateX(scrollX) per Scroll-Listener; weil
   der Scroll auf dem Compositor laeuft und das JS erst NACH dem Paint
   nachfuehrt, ZITTERTEN die Leisten sichtbar (mitwandern + zurueckspringen).
   Prinzipbedingt, nicht durch Listener-Optimierung behebbar. Ebenso scheidet
   reines sticky;left:0 aus: der umgebende Block ist nur viewportbreit
   (Sticky-Falle aus L); ihn inhaltsbreit zu machen und die Leisten auf 100vw
   zu setzen erzeugt in der Fits-Lage einen 32-px-Scrollbalken (100vw +
   .inhalt-Polsterung; am Bestand nachgemessen).

   Loesung: die vier Leisten werden position:fixed (top bleibt die Summe der
   darueberliegenden --hoehe-*-Variablen aus K/I; left:0; width:100%). Da
   width:100% eines fixed-Elements sich auf den INITIAL CONTAINING BLOCK
   (Viewport OHNE Scrollbalken) bezieht, entsteht KEIN neuer Scrollbalken —
   anders als 100vw. Voll scroll-immun in beiden Achsen, kompositorseitig,
   ohne Nachfuehrung (kein Zittern).

   SCOPING auf body:has(.bwa-scroll): nur wenn die Tabelle ueberhaupt
   querscrollen kann, werden die Leisten fixiert und der Inhalt per
   padding-top unter den Stapel geschoben. Ohne .bwa-scroll (Gesamtansicht
   ohne Zusatzspalten, Tabelle passt) bleibt ALLES beim sticky-Verhalten aus
   K/L — DOM/Optik byte-genau wie zuvor, kein Scrollbalken. Im fixierten Fall
   beginnt der Titel (kein top-Sticky) UNTER dem Stapel und scrollt vertikal
   hinter die deckenden Leisten (optisch wie bisher „weg"). Die negativen
   Rand-Bleed-Raender entfallen im fixed-Zustand (width:100% deckt die volle
   Breite), die Innenpolsterung haelt den Inhalt auf der 1rem-Flucht. */
body:has(.bwa-scroll) .kopfzeile,
body:has(.bwa-scroll) .bwa-filter,
body:has(.bwa-scroll) .bwa-stand-leiste,
body:has(.bwa-scroll) .klapp-master-leiste {
  position: fixed;
  left: 0;
  width: 100%;
  box-sizing: border-box;
}
body:has(.bwa-scroll) .bwa-filter { margin: 0 0 0.4rem; }
body:has(.bwa-scroll) .bwa-stand-leiste,
body:has(.bwa-scroll) .klapp-master-leiste { margin: 0; }
/* Der Inhalt rueckt unter den fixierten Stapel (Summe aller vier Hoehen
   plus die urspruengliche 1rem-Oberpolsterung). Ausserhalb der BWA und ohne
   .bwa-scroll unberuehrt (dort greift .inhalt { padding: 1rem }). */
.inhalt:has(.bwa-scroll) {
  padding-top: calc(var(--hoehe-kopfzeile) + var(--hoehe-filter)
                    + var(--hoehe-status) + var(--hoehe-klappleiste) + 1rem);
}

/* Kennzahlen-Dropdown (Durchgang E) neben dem Master-Schalter — dieselbe
   ruhige Optik wie die Filter-Labels der Filterleiste. */
.kennzahl-wahl {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.9rem;
  color: #4a5361;
}

/* Master-Schalter "Alles ein-/ausklappen" oberhalb der Liste.
   Erweiterung 5: Pill; Rahmen/Farben aus der gemeinsamen Button-Regel. */
.klapp-master {
  margin: 0 0 0.6rem;
  padding: 0.45rem 1rem;
  font-size: 0.82rem;
  font-weight: 600;
  box-shadow: var(--kt-shadow-control);
}

/* ---------- Split-Button „Alles auf-/einklappen" (Nachbesserung 4, T3)
   Zwei Pills, die als EINE wirken: der Hauptknopf rundet nur links, der
   Pfeil nur rechts, dazwischen eine Trennlinie. Beide behalten ihre
   eigene Schaltflaeche — deshalb bleiben es zwei echte Buttons und
   nicht ein Knopf mit Klickzonen. */
.klapp-split {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  margin: 0 0 0.6rem;
}
.klapp-split .klapp-master {
  margin: 0;
  border-radius: 999px 0 0 999px;
  border-right: none;
  padding-right: 0.7rem;
}
.klapp-mehr {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.7rem;
  line-height: 1;
  padding: 0 0.6rem;
  border: 1px solid var(--kt-border);
  border-left: 1px solid var(--kt-border);
  border-radius: 0 999px 999px 0;
  background: var(--kt-surface);
  color: var(--kt-text);
  cursor: pointer;
  box-shadow: var(--kt-shadow-control);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.klapp-mehr:hover {
  border-color: var(--kt-accent);
  color: var(--kt-accent);
  background: var(--kt-accent-soft);
}
.klapp-mehr:focus-visible,
.klapp-menue button:focus-visible {
  outline: 2px solid var(--kt-accent);
  outline-offset: 2px;
}

/* Das Menue liegt IMMER im Markup und wird hier ein-/ausgeblendet —
   ein zweiter Zustandstraeger (nachgeladenes Fragment) waere eine
   weitere Quelle, die dem DOM hinterherhinken koennte. */
.klapp-menue {
  display: none;
  position: absolute;
  top: calc(100% + 0.25rem);
  left: 0;
  z-index: 7;
  min-width: 100%;
  flex-direction: column;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius);
  box-shadow: var(--kt-shadow);
  padding: 0.25rem;
}
.klapp-split.offen .klapp-menue { display: flex; }
.klapp-menue button {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.82rem;
  text-align: left;
  white-space: nowrap;
  padding: 0.4rem 0.7rem;
  border: none;
  border-radius: var(--kt-radius-sm);
  background: transparent;
  color: var(--kt-text);
  cursor: pointer;
}
.klapp-menue button:hover {
  background: var(--kt-accent-soft);
  color: var(--kt-accent);
}

/* ==========================================================================
   OnePager (Etappe H, FA-44-04)

   Eine Tabelle: links die konfigurierten Zeilen, rechts je Standort ein
   Spaltenblock (Ist / Vorjahr), davor die Gesamtspalte. Bei vielen
   Standorten wird das breit — der Bereich scrollt dann waagerecht, die
   Beschriftungsspalte bleibt stehen (dieselbe Mechanik wie im
   13-Monats-Verlauf).
   ========================================================================== */

.onepager-kopf {
  margin: .4rem 0 .6rem;
  font-size: .9rem;
  color: #4a5361;
}

/* Der Bereich scrollt waagerecht UND senkrecht. Wegen overflow-x waere
   er ohnehin ein eigener Scroll-Kontext, in dem sticky-top nicht am
   Viewport haftet — deshalb dieselbe Rechnung wie in der BWA: die Hoehe
   wird auf den TATSAECHLICH verfuegbaren Sichtbereich begrenzt, sonst
   wandert die Container-Oberkante samt fixiertem Kopf beim Scrollen
   hinter die Filterleiste (--hoehe-filter wird von bwa.js gemessen). */
.onepager-flaeche {
  overflow: auto;
  padding-bottom: .2rem;
  /* Die Hoehe setzt bwa.js GEMESSEN (tabellenhoeheAktualisieren) — der
     Bereich fuellt genau den Rest des Fensters. Der Wert hier ist nur
     der Startwert fuer den Moment vor der ersten Messung und fuer den
     Fall ohne JavaScript. */
  max-height: calc(100vh - var(--hoehe-kopfzeile)
                   - var(--hoehe-filter) - 6rem);
}

table.onepager {
  border-collapse: collapse;
  font-size: .84rem;
  font-variant-numeric: tabular-nums;
}

table.onepager th,
table.onepager td {
  box-sizing: border-box;
  padding: .22em .45em;
  border-bottom: 1px solid var(--farbe-linie);
  white-space: nowrap;
}

table.onepager td.zahl,
table.onepager th.zahl { text-align: right; }

/* Spaltenkopf: Standortname ueber seinem Ist/Vorjahr-Paar.

   ZWEISTUFIG FIXIERT (Muster der BWA): die obere Zeile klebt an der
   Container-Oberkante, die untere direkt darunter. Der Versatz ist die
   Hoehe der oberen Zeile — sie ist einzeilig, deshalb genuegt hier eine
   feste Angabe (--onepager-kopfzeile) statt einer Messung per JS.

   DECKENDER Hintergrund ist Pflicht, nicht Kosmetik: ohne ihn scheinen
   die Wertzellen beim Scrollen durch den Kopf hindurch. Das ist
   dasselbe Thema wie bei der Beschriftungsspalte der BWA. */
table.onepager {
  --onepager-kopfzeile: 1.5rem;
}

table.onepager thead th {
  border-bottom: 2px solid var(--farbe-kopf);
  font-weight: 600;
  background: #fff;
  position: sticky;
  z-index: 2;
}

table.onepager thead tr:first-child th { top: 0; }
table.onepager thead tr:last-child th { top: var(--onepager-kopfzeile); }

/* Die Ecke oben links liegt in BEIDEN Richtungen fest und muss deshalb
   ueber allem anderen stehen (sie ist zugleich Kopf und
   Beschriftungsspalte). */
table.onepager thead th.onepager-ecke { z-index: 3; }

/* Spaltenkopf mittig ueber seinem Ist/Vorjahr-Block */
table.onepager .onepager-spaltenkopf { text-align: center; }
table.onepager .onepager-unterkopf { font-weight: 400; font-size: .78rem; }

/* Senkrechte Trennlinie zwischen den Spaltenbloecken (Gesamt | Standort
   | Standort …), in derselben Optik wie die Gruppenlinie der
   Segmentansicht: nahezu schwarz und 2px, weil sie in einer breiten
   Tabelle die wichtigste Orientierung ist.

   Sie steht am colgroup UND an den Zellen. Das colgroup ist der
   tragende Teil: nur so laeuft die Linie auch durch die
   Abschnitts-Balken, die als colspan-Zeile an dieser Stelle gar keine
   Zellgrenze haben. Die Zellenangabe sichert dieselbe Linie dort, wo
   Zellen einen eigenen Hintergrund haben (Kopf, Beschriftungsspalte)
   und den col-Rahmen sonst ueberdecken wuerden. */
table.onepager col.onepager-blockstart,
table.onepager th.blockstart,
table.onepager td.blockstart {
  border-left: 2px solid var(--farbe-gruppenlinie);
}

/* Der Abschnitts-Balken spannt ueber alle Spalten — an SEINER linken
   Kante darf keine Linie stehen (die saesse an der falschen Stelle);
   die durchgehende Linie kommt dort aus dem colgroup. */
table.onepager .onepager-blocktitel th { border-left: 0; }

/* Vorjahr tritt zurueck — es ist Vergleich, nicht Aussage. Farbliche
   Hinterlegung wie in der BWA (dieselben Variablen --farbe-vorjahr /
   --farbe-vorjahr-kopf, keine neue Farbe): der Vorjahresstreifen liest
   sich in beiden Ansichten gleich. In der echten Tabelle fuellt der
   Zellenhintergrund von selbst — der negative-margin-Trick der BWA
   (Grid) ist hier nicht noetig. */
table.onepager .vorjahr {
  color: #6b7480;
  background: var(--farbe-vorjahr);
}
table.onepager thead th.vorjahr { background: var(--farbe-vorjahr-kopf); }

/* Beschriftungsspalte bleibt beim Querscrollen stehen */
table.onepager .onepager-ecke,
table.onepager .onepager-beschriftung {
  position: sticky;
  left: 0;
  /* Ueber den Wertzellen (z 0), aber UNTER dem Tabellenkopf (z 2) —
     sonst schoebe sich die Beschriftung beim Scrollen ueber ihn. */
  z-index: 1;
  text-align: left;
  background: #fff;
  font-weight: 400;
  min-width: 16rem;
}

table.onepager .onepager-ecke { font-weight: 600; }

/* Abschnittsueberschrift (NW/GW/… bzw. NW je Markengruppe) */
table.onepager .onepager-blocktitel th {
  background: var(--farbe-kopf);
  color: #fff;
  text-align: left;
  font-weight: 600;
  /* Der Balken spannt ueber alle Spalten und darf weder waagerecht
     kleben (er hat keine eigene Spalte) noch den fixierten Kopf
     ueberdecken. */
  position: static;
  z-index: 0;
  padding: .3em .45em;
}

/* Der Balkentext bleibt beim Querscrollen stehen (siehe Template) */
.onepager-blocktitel-text {
  position: sticky;
  left: .45em;
  display: inline-block;
}

/* ---------- Bereichs-Kacheln (Durchgang AQ, OnePager-Angleichung) -------
   Jeder Abschnitt liest sich als Kachel in seiner Bereichsfarbe, wie die
   Abteilungen der BWA. Die Kennung kommt aus den Stammdaten
   (block.abschnitt -> .bereich-XX am tbody), nie aus dem Titeltext.

   WARUM DER KOPF EIN INNEN-ELEMENT IST: die Tabelle rechnet mit
   border-collapse: collapse — dort zeichnen weder Chrome noch
   WeasyPrint border-radius an Zellen. Die runde Kante entsteht deshalb
   an einem div IM Titel-th (.onepager-blockkopf), das die volle Breite
   der colspan-Zelle einnimmt. Das traegt in beiden Engines und laesst
   die bestehende Linienfuehrung unberuehrt — insbesondere die
   senkrechten Spaltenlinien aus dem colgroup, die auf collapse
   angewiesen sind. Ein Wechsel auf border-collapse: separate haette
   genau die gekostet.

   Der ABSCHLUSS ist eine kraeftige Unterkante an der letzten Zeile des
   Blocks statt einer abgerundeten Leiste: eine Leiste waere in einer
   Tabelle eine zusaetzliche Zeile mit vollem Zellensatz. Die Kante ist
   die tabellarische Entsprechung — Anfang und Ende der Kachel tragen
   dieselbe Farbe.

   Je Bereich werden nur WERTE gesetzt; die Mechanik steht einmal
   darunter. Eine siebte Abteilung braeuchte damit genau eine Zeile.

   FALLBACK: OnePagerZeile.abschnitt ist ein freies Feld und deckt sich
   NICHT zwingend mit den sechs BWA-Bereichen — im Bestand kommen
   zusaetzlich 'TEILE' und 'GESAMT' vor. Fuer solche Abschnitte greift
   var(--farbe-kopf), also genau der dunkelblaue Balken von vorher: die
   Kachel bleibt, nur ohne Bereichsfarbe. Die Zuordnung TEILE -> ET ist
   eine FACHLICHE Frage und wird hier bewusst nicht geraten. */
table.onepager tbody.bereich-NW { --op-bereich: var(--kt-nw); --op-akzent: var(--kt-nw-bg-strong); --op-db-1: var(--kt-db-nw-1); --op-db-2: var(--kt-db-nw-2); --op-db-3: var(--kt-db-nw-3); --op-db-4: var(--kt-db-nw-4); }
table.onepager tbody.bereich-GW { --op-bereich: var(--kt-gw); --op-akzent: var(--kt-gw-bg-strong); --op-db-1: var(--kt-db-gw-1); --op-db-2: var(--kt-db-gw-2); --op-db-3: var(--kt-db-gw-3); --op-db-4: var(--kt-db-gw-4); }
table.onepager tbody.bereich-KD { --op-bereich: var(--kt-kd); --op-akzent: var(--kt-kd-bg-strong); --op-db-1: var(--kt-db-kd-1); --op-db-2: var(--kt-db-kd-2); --op-db-3: var(--kt-db-kd-3); --op-db-4: var(--kt-db-kd-4); }
table.onepager tbody.bereich-ET { --op-bereich: var(--kt-et); --op-akzent: var(--kt-et-bg-strong); --op-db-1: var(--kt-db-et-1); --op-db-2: var(--kt-db-et-2); --op-db-3: var(--kt-db-et-3); --op-db-4: var(--kt-db-et-4); }
table.onepager tbody.bereich-NT { --op-bereich: var(--kt-nt); --op-akzent: var(--kt-nt-bg-strong); --op-db-1: var(--kt-db-nt-1); --op-db-2: var(--kt-db-nt-2); --op-db-3: var(--kt-db-nt-3); --op-db-4: var(--kt-db-nt-4); }
table.onepager tbody.bereich-GU { --op-bereich: var(--kt-gu); --op-akzent: var(--kt-gu-bg-strong); --op-db-1: var(--kt-db-gu-1); --op-db-2: var(--kt-db-gu-2); --op-db-3: var(--kt-db-gu-3); --op-db-4: var(--kt-db-gu-4); }

/* Kopf der Kachel: flache Bereichsfarbe, runde obere Ecken. Flach und
   nicht als Verlauf — dieselbe Begruendung wie in der BWA (F2): ueber
   einem Verlauf saesse jede eigene Zellflaeche auf einem anderen Ton. */
table.onepager .onepager-blocktitel th {
  background: transparent;
  padding: 0;
  /* Der Abstand zur vorigen Kachel. In einer Tabelle gibt es keinen
     Aussenabstand zwischen tbody-Elementen; die Luecke entsteht als
     Rahmen in der Seitenfarbe. */
  border-top: .5rem solid var(--kt-surface);
}

table.onepager .onepager-blockkopf {
  background: var(--op-bereich, var(--farbe-kopf));
  color: #fff;
  border-radius: var(--kt-radius-sm) var(--kt-radius-sm) 0 0;
  padding: .3em .45em;
  font-family: var(--kt-font-display);
  letter-spacing: -0.01em;
}

/* Abschluss der Kachel: kraeftige Unterkante in der Bereichsfarbe. */
table.onepager tbody.onepager-block > tr:last-child > * {
  border-bottom: 3px solid var(--op-bereich, var(--farbe-kopf));
}

/* Schmaler Bereichsakzent an der Beschriftungsspalte — dasselbe
   Element wie in der BWA (dort inset an der Zeile), hier an der
   stehenbleibenden ersten Spalte. */
table.onepager tbody.onepager-block .onepager-beschriftung {
  box-shadow: inset 3px 0 0 var(--op-akzent, transparent);
}

/* DB-Stufen: Flaeche je Meilenstein, aus den vorberechneten Tokens.
   Erkennung ausschliesslich ueber db_stufe aus den Stammdaten.
   Die Vorjahreszellen sind AUSGENOMMEN — dort gilt wie in der BWA
   „Vorjahr gewinnt in der Zelle", sonst risse das Band auf.

   VORRANGREGEL, hier eingebaut statt nebenan: Zellen mit
   Ergebnis-Ampel sind AUSGENOMMEN. Die Ampel gewinnt gegen die
   DB-Flaeche derselben Zeile — die Aussage "Ergebnis positiv/negativ"
   ist die staerkere, die Stufe ordnet nur ein.

   Warum die Ausnahme HIER steht und nicht als staerkere Ampelregel
   daneben: der Vorrang haengt dann nicht an Spezifitaets-Arithmetik.
   Erst gemessen und dann so gebaut — die Ampelregel daneben trug drei
   Klassen gegen vier dieser Regel und verlor auf background (die
   Textfarbe kam durch, weil hier keine gesetzt wird; am Bildschirm
   stand die Zahl rot auf grauer DB-Flaeche). */
table.onepager tbody.onepager-block tr.kt-db-1 > *:not(.vorjahr):not([class*="kt-ergebnis-"]) { background: var(--op-db-1); }
table.onepager tbody.onepager-block tr.kt-db-2 > *:not(.vorjahr):not([class*="kt-ergebnis-"]) { background: var(--op-db-2); }
table.onepager tbody.onepager-block tr.kt-db-3 > *:not(.vorjahr):not([class*="kt-ergebnis-"]) { background: var(--op-db-3); }
table.onepager tbody.onepager-block tr.kt-db-4 > *:not(.vorjahr):not([class*="kt-ergebnis-"]) { background: var(--op-db-4); }

/* Schriftschnitt aus den Stammdaten (FA-42-09) — wie in der BWA. */
table.onepager tr.fett > * { font-weight: 700; }
table.onepager tr.kursiv > * { font-style: italic; }

/* Ergebnis-Ampel. Sie sitzt hier an der ZELLE, nicht an der Zeile: der
   OnePager hat je Zeile mehrere Wertspalten, und das Vorzeichen kann
   sich von Standort zu Standort unterscheiden. In der BWA gibt es je
   Zeile nur eine Wertspalte, dort haengt sie deshalb an der Zeile.
   Entschieden wird am GERECHNETEN Wert (onepager._ampel_fuer) —
   dieselbe Regel wie dort, kein Textparsing.

   VORRANGREGEL (einheitlich BWA + OnePager): traegt eine Zeile sowohl
   eine DB-Stufe als auch die Ampel, GEWINNT DIE AMPEL. Durchgesetzt
   wird das nicht hier, sondern als AUSNAHME in der DB-Regel oben —
   sonst haenge es an der Spezifitaet, und die stand zunaechst falsch
   herum. In der BWA ergibt sich derselbe Vorrang aus der
   Regelreihenfolge (beide Regeln tragen dort zwei Klassen). */
table.onepager tbody.onepager-block tr > .kt-ergebnis-positiv {
  background: var(--kt-ergebnis-pos-bg);
  color: var(--kt-ergebnis-pos);
  font-weight: 700;
}
table.onepager tbody.onepager-block tr > .kt-ergebnis-negativ {
  background: var(--kt-ergebnis-neg-bg);
  color: var(--kt-ergebnis-neg);
  font-weight: 700;
}

/* Gesperrte Zeilen tragen ausschliesslich '---' — sie treten zurueck,
   bleiben aber sichtbar (Muster der Formel-Ansicht: Struktur ja, Werte
   nein). */
table.onepager tr.onepager-gesperrt { color: #9aa1ab; }

/* PDF-Export: rechts in der Filterleiste abgesetzt und als
   Schaltflaeche erkennbar — er ist die einzige Aktion dort, alles
   andere sind Auswahlfelder. */
/* Schriftwahl direkt vor dem Knopf, dorthin geschoben wie er selbst */
.onepager-pdf-schrift { margin-left: auto; }

/* Erweiterung 5: Pill in der dunklen Kopffarbe — die einzige
   PRIMAERaktion der Leiste. Radius/Polster kommen aus der gemeinsamen
   Regel oben; hier bleiben nur Farbe und Umbruchverhalten. */
.onepager-pdf {
  align-self: center;
  border: none;
  background: var(--kt-text);
  color: var(--kt-surface);
  text-decoration: none;
  white-space: nowrap;
}

.onepager-pdf:hover { background: var(--kt-accent); }

/* BWA-PDF-Export (Etappe I): dieselbe Optik wie im OnePager. Der Block
   schiebt sich mit margin-left:auto nach rechts ans Zeilenende. */
.bwa-pdf-block {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
}
.bwa-pdf {
  align-self: center;
  border: none;
  background: var(--kt-text);
  color: var(--kt-surface);
  text-decoration: none;
  white-space: nowrap;
}
.bwa-pdf:hover { background: var(--kt-accent); }

/* --------------------------------------------------------------------
   Manuelle Statistik-Erfassung (Durchgang AB)

   Die Matrix Marken x Standorte kann breit werden (gemessen bis 76
   gelieferte Segmente je Import). Sie bekommt deshalb einen eigenen
   Scroll-Rahmen, damit die SEITE nicht quer scrollt — dieselbe Regel wie
   bei den Segmentspalten der BWA.
   -------------------------------------------------------------------- */
.erfassung-kontext { color: #4a5361; font-size: .9rem; }

.erfassung-kopf {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-top: 1.2rem;
}
.erfassung-kopf h2 { margin: 0; }
.erfassung-fortschritt { color: #4a5361; font-size: .9rem; margin: 0; }

.erfassung-art {
  background: #f4f7fb;
  border-left: 3px solid var(--farbe-kopf);
  padding: .5rem .8rem;
  font-size: .9rem;
}

.erfassung-wahl {
  display: flex;
  gap: 1rem;
  align-items: end;
  flex-wrap: wrap;
  margin: .8rem 0;
}

/* Scroll-Rahmen der Matrix: BEIDE Achsen. Der Container ist zugleich der
   Bezugsrahmen der sticky Koepfe — deshalb braucht er eine Hoehengrenze,
   sonst hat `top: 0` nichts, woran es einrasten koennte. (overflow-x: auto
   allein genuegt nicht: die andere Achse rechnet der Browser ohnehin auf
   `auto` hoch, aber ohne max-height scrollt vertikal die SEITE und der
   Kopf wandert mit weg.) */
.erfassung-matrix-rahmen {
  overflow: auto;
  max-width: 100%;
  max-height: 70vh;
  margin: .8rem 0;
}

/* separate statt collapse: bei border-collapse malt der Browser die Rahmen
   der Tabelle, nicht der Zelle — sticky Zellen verlieren sie dann beim
   Scrollen. Mit separate + border-spacing 0 sieht es identisch aus, die
   Rahmen bleiben aber an der Zelle und scrollen mit ihr. */
table.erfassung-matrix {
  border-collapse: separate;
  border-spacing: 0;
}
.erfassung-matrix th,
.erfassung-matrix td {
  border-right: 1px solid #d5dae1;
  border-bottom: 1px solid #d5dae1;
  padding: .25rem .4rem;
  font-size: .85rem;
}
.erfassung-matrix tr > :first-child { border-left: 1px solid #d5dae1; }
.erfassung-matrix thead th { border-top: 1px solid #d5dae1; }

/* Sticky in zwei Achsen: Kopfzeile oben, Marken-Spalte links, die Ecke
   ueber beiden (sonst schoebe sich beim Querscrollen die erste Kopfzelle
   unter die Marken-Spalte). */
.erfassung-matrix thead th {
  background: #f4f7fb;
  position: sticky;
  top: 0;
  z-index: 2;
}
.erfassung-matrix .ecke,
.erfassung-matrix .marke {
  background: #f4f7fb;
  text-align: left;
  white-space: nowrap;
  position: sticky;
  left: 0;
  z-index: 1;
}
.erfassung-matrix thead .ecke { z-index: 3; }

/* Zweizeilige Koepfe: Nummer/Code oben, Klartext klein darunter — dasselbe
   Muster wie die Zweitzeilen im Drill-down. Der Klartext wird abgeschnitten
   statt die Spalte zu sprengen (title traegt den vollen Text); bei 12
   Marken x 11 Standorten zaehlt jede Spaltenbreite.

   EIGENE, GESCOPTE KLASSENNAMEN (AB4-Fix): die Koepfe hiessen zuvor
   `segment-kopf/-primaer/-sekundaer`. `segment-kopf` gibt es aber bereits
   fuer die BWA-Spaltenkoepfe (Zeile ~515) — dort ein Grid-Kind mit
   `display: flex`, was dort richtig ist. Auf einem <th> hebt flex die
   Tabellenzellen-Natur auf: die Kopfzellen fallen aus dem Zeilenraster und
   stapeln sich in der Ecke. Deshalb heissen die Matrix-Klassen jetzt
   `matrix-*` UND sind zusaetzlich unter `.erfassung-matrix` gescoped. */
.erfassung-matrix .matrix-kopf {
  display: table-cell;          /* explizit: keine fremde Regel kippt das */
  vertical-align: bottom;
}
.erfassung-matrix .matrix-primaer {
  display: block;
  font-weight: 600;
}
.erfassung-matrix .matrix-sekundaer {
  display: block;
  max-width: 7rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .72rem;
  font-weight: 400;
  color: #6b7280;
}
.erfassung-matrix .marke .matrix-sekundaer { max-width: 9rem; }

/* Kombinationen/Standorte ohne Buchungen in diesem Monat: HINWEIS, keine
   Sperre — das Feld bleibt voll bedienbar (neuer Standort, Verkaeufer vor
   dem ersten Umsatz). Einziger Unterschied zu einem normalen Feld: eine sehr
   dezente graue Hinterlegung. Rahmen exakt identisch (siehe Basisregel
   `.erfassung-zelle input` — appearance:none verhindert, dass Safari um ein
   Feld mit Hintergrundfarbe seinen dunklen nativen Inset-Rahmen zeichnet). */
.erfassung-zelle.ohne-buchungen input { background: #eef0f3; }

.erfassung-legende {
  color: #4a5361;
  font-size: .85rem;
  margin: .4rem 0 0;
}
.legende-marker {
  display: inline-block;
  width: 1.4rem;
  height: .9rem;
  vertical-align: -.1rem;
  background: #eef0f3;
  border: 1px solid #d5dae1;
}
.erfassung-zelle input {
  width: 6.5rem;
  text-align: right;
  font-size: .85rem;
  padding: .15rem .3rem;
  /* Einheitlicher, flacher Rahmen fuer ALLE Erfassungsfelder: appearance:none
     schaltet Safaris nativen Text-Input-Bevel ab (der bei gesetzter
     Hintergrundfarbe als dicker dunkler Inset erschien). So unterscheidet sich
     ein „ohne Buchungen"-Feld nur durch den Hintergrund, nicht durch den
     Rahmen. Rasterfarbe #d5dae1 wie die uebrigen Matrix-Linien. */
  -webkit-appearance: none;
  appearance: none;
  border: 1px solid #d5dae1;
  border-radius: 3px;
  background: #fff;
}
/* Der importierte (ignorierte) Wert steht klein unter dem Eingabefeld —
   dieselbe zurueckgenommene Zweitzeile wie im Drill-down. */
.erfassung-import {
  display: block;
  font-size: .72rem;
  color: #6b7280;
  text-align: right;
}
.erfassung-leer { background: #f0f0f0; color: #9aa1ab; text-align: center; }

.erfassung-knoepfe {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  margin: 1rem 0 .4rem;
}
.knopf-sekundaer {
  background: #fff;
  color: var(--farbe-kopf);
  border: 1px solid var(--farbe-kopf);
}
.erfassung-hinweis { color: #4a5361; font-size: .85rem; }
.erfassung-einstieg { font-weight: 600; }

/* Checkliste der Massenbearbeitung (Durchgang AD) */
table.zeilen-checkliste {
  border-collapse: collapse;
  width: 100%;
  max-width: 60rem;
  margin: .3rem 0 1.2rem;
}
.zeilen-checkliste th,
.zeilen-checkliste td {
  border-bottom: 1px solid #e3e7ec;
  padding: .3rem .5rem;
  font-size: .88rem;
  text-align: left;
}
.zeilen-checkliste thead th {
  border-bottom: 2px solid var(--farbe-kopf);
  white-space: nowrap;
}
.zeilen-checkliste .zahl { text-align: right; white-space: nowrap; }
.zeilen-checkliste .haken { width: 4rem; text-align: center; }
.zeilen-checkliste tr.ist-markiert { background: #f4f7fb; }
.zeilen-checkliste label { cursor: pointer; }
.zeilen-checkliste .erfassungsart { color: #4a5361; font-size: .8rem; }

h2.abteilung {
  margin: 1.4rem 0 .2rem;
  font-size: 1rem;
  border-bottom: 1px solid var(--farbe-kopf);
  padding-bottom: .15rem;
}

.kennzeichen {
  font-size: .75rem;
  color: #6b7280;
  border: 1px solid #d5dae1;
  border-radius: 3px;
  padding: .05rem .35rem;
  white-space: nowrap;
}
.kennzeichen-individuell { color: #16304f; border-color: var(--farbe-kopf); }

.warnung { color: #a04000; }

.modal-herkunft {
  background: #f4f7fb;
  border-left: 3px solid var(--farbe-kopf);
  padding: .5rem .8rem;
  font-size: .9rem;
}

/* --- Anmelde-/Reset-Buttons (Login-Optimierung) ------------------------
   EIN gemeinsames Aussehen: gleiche Schriftgroesse/Form fuer alle Buttons,
   Hierarchie ueber die Farbe. Die Basis ergaenzt die schon vorhandene
   Farbregel von .knopf-sekundaer (s. o.) um eine einheitliche Form und macht
   die Klasse auch als <a>-Button vollwertig. */
.knopf-primaer,
.knopf-sekundaer,
.passkey-button {
  display: inline-block;
  /* URSACHE VON S5: ohne border-box rechnet width: 100% (Zugangskarte)
     NUR den Inhalt — Polsterung und Rahmen kommen obendrauf, und der
     Knopf ragt um 2,4rem + 2px aus der Kachel heraus. Sichtbar wurde
     das an „Passwort vergessen?"; betroffen war jeder Knopf der Karte.
     Behoben wird es hier an der Quelle, nicht am einzelnen Knopf. */
  box-sizing: border-box;
  font-size: 1rem;
  font-weight: 700;
  padding: 0.4rem 1.2rem;
  border: 1px solid var(--farbe-kopf);
  /* Feinschliff Erweiterung 5: volle Pill wie die uebrigen
     Schaltflaechen; die Farb-Hierarchie darunter bleibt unberuehrt. */
  border-radius: 999px;
  cursor: pointer;
  font-family: inherit;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
}
.knopf-primaer {                      /* primaer: Anmelden / Weiter */
  background: var(--farbe-kopf);
  color: #fff;
}
.passkey-button {                     /* sekundaer: wie .knopf-sekundaer */
  background: #fff;
  color: var(--farbe-kopf);
}
.knopf-primaer:hover { filter: brightness(1.18); }
.knopf-sekundaer:hover,
.passkey-button:hover { background: #eef2f8; }

/* Trenner „oder" zwischen Passwort- und Passkey-Bereich (klassische Ansicht) */
.oder-trenner { margin: 1rem 0 0.6rem; color: #6b7280; font-size: 0.9rem; }
.passkey-status { margin: 0.4rem 0 0; font-size: 0.85rem; color: #4a5361; }
.login-hilfen { margin-top: 1.2rem; }
.reset-code-hinweis { margin: 1.6rem 0 0.6rem; font-size: 0.9rem; }
/* Aufklappbarer Passwort-Fallback in der Passkey-zuerst-Ansicht */
.passwort-fallback > summary {
  cursor: pointer;
  color: var(--farbe-kopf);
  margin: 1rem 0 0.6rem;
  font-size: 0.9rem;
}

/* ==========================================================================
   Fehlerbilder des BWA-Auflösungspfads (Durchgang AT)

   EIN Baustein, zwei Tonlagen — er steht sowohl allein im HTMX-Ziel als
   auch eingebettet in der Vollseite. Deshalb bringt er seine eigenen
   Aussenabstaende mit und verlaesst sich auf nichts von aussen.

   Die Karte folgt der Kachelsprache aus AQ (Radius, Schatten, Flaeche);
   nur der Rahmen traegt die Farbe des Fehlerbilds, damit sie sich in die
   Ansicht einfuegt statt sie zu uebertoenen.
   ========================================================================== */
.bwa-fehler {
  max-width: 44rem;
  margin: 1.4rem auto;
  padding: 1.2rem 1.4rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-left-width: 4px;
  border-radius: var(--kt-radius);
  box-shadow: var(--kt-shadow-sm);
  font-family: var(--kt-font);
  color: var(--kt-text);
}

.bwa-fehler-mappingkonflikt {
  border-color: var(--kt-stoerung-border);
  border-left-color: var(--kt-stoerung);
  background: var(--kt-stoerung-bg);
}

.bwa-fehler-aufwaermen {
  border-color: var(--kt-wartet-border);
  border-left-color: var(--kt-wartet);
  background: var(--kt-wartet-bg);
}

.bwa-fehler-kopf {
  margin: 0 0 0.5rem;
  font-family: var(--kt-font-display);
  font-size: 1.15rem;
  font-weight: 600;
}

.bwa-fehler-mappingkonflikt .bwa-fehler-kopf { color: var(--kt-stoerung); }
.bwa-fehler-aufwaermen .bwa-fehler-kopf { color: var(--kt-wartet); }

.bwa-fehler-text { margin: 0 0 0.8rem; line-height: 1.45; }

.bwa-fehler-tun {
  margin: 0.8rem 0 0;
  font-size: 0.9rem;
  color: var(--kt-text-soft);
  line-height: 1.45;
}

/* Die beteiligten Objekte: Bezeichner links, Werte rechts — bei
   schmalem Fenster untereinander (kein Grid-Zwang). */
.bwa-fehler-daten {
  margin: 0;
  padding: 0.8rem 0 0;
  border-top: 1px solid var(--kt-border-soft);
  font-size: 0.9rem;
}

.bwa-fehler-daten dt {
  font-weight: 600;
  color: var(--kt-text-soft);
  margin-top: 0.6rem;
}

.bwa-fehler-daten dd { margin: 0.15rem 0 0; }

.bwa-fehler-regeln { margin: 0.15rem 0 0; padding-left: 1.1rem; }
.bwa-fehler-regeln li { margin: 0.15rem 0; }

/* Das Regelmuster ist ein Schluessel, kein Fliesstext. */
.bwa-fehler-muster {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 0.85em;
  background: var(--kt-surface);
  border: 1px solid var(--kt-border);
  border-radius: var(--kt-radius-sm);
  padding: 0 0.3rem;
}

.bwa-fehler-aktion { margin: 1rem 0 0; }

/* Die Vollseite gibt der Karte nur Luft nach oben — die Kopfzeile der
   Anwendung bleibt stehen, damit man weiterklicken kann. */
.bwa-fehler-seite { padding: 0.6rem 0 2rem; }

/* ==========================================================================
   Banner „veraltet" und Fortschritt des Cache-Aufbaus (Durchgang AV)

   Das Banner ist BEWUSST schmaler und flacher als die Fehlerkarten: es
   steht ueber einer BENUTZBAREN Tabelle. Wer es liest, soll weiterarbeiten
   koennen und nicht das Gefuehl haben, die Seite sei kaputt.
   ========================================================================== */
.veraltet-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.9rem;
  margin: 0 0 0.8rem;
  padding: 0.6rem 0.9rem;
  /* Das Banner liegt IM Ergebnisbereich, und der wird so breit wie die
     Tabelle — bei vielen Segmentspalten weit breiter als das Fenster.
     Ohne die zwei Zeilen stuende der Knopf rechts ausserhalb des
     Sichtfelds (gemessen am Bildbeleg). `sticky` haelt das Banner beim
     Querscrollen am linken Rand, die Breite bindet es an das Fenster
     statt an die Tabelle. Dieselbe Mechanik wie bei der Statuszeile
     (V5c aus AQ). */
  position: sticky;
  left: 0;
  max-width: min(72rem, calc(100vw - 3rem));
  background: var(--kt-wartet-bg);
  border: 1px solid var(--kt-wartet-border);
  border-left: 3px solid var(--kt-wartet);
  border-radius: var(--kt-radius-sm);
  font-family: var(--kt-font);
  font-size: 0.85rem;
  color: var(--kt-text);
}

.veraltet-banner-kopf {
  margin: 0;
  font-weight: 600;
  color: var(--kt-wartet);
}

.veraltet-banner-text { margin: 0; color: var(--kt-text-soft); }

/* Der Knopf steht rechts aussen, aber im Fluss — kein absoluter Sitz, der
   bei schmalem Fenster ueber dem Text landet. */
.veraltet-banner-aktion { margin: 0 0 0 auto; }

.veraltet-banner-knopf {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.8rem;
  line-height: 1;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--kt-wartet-border);
  border-radius: 999px;
  background: var(--kt-surface);
  color: var(--kt-wartet);
  cursor: pointer;
  box-shadow: var(--kt-shadow-control);
}

.veraltet-banner-knopf:hover,
.veraltet-banner-knopf:focus {
  border-color: var(--kt-wartet);
  background: var(--kt-wartet-bg);
}

/* Fortschrittsbalken des Aufwaermens. Die Fuellung bekommt ihre Breite
   inline aus dem Lauf-Datensatz — das ist der einzige Wert, der sich
   waehrend des Laufs aendert. */
.cache-balken {
  margin: 0.8rem 0 0.4rem;
  height: 0.55rem;
  background: var(--kt-surface);
  border: 1px solid var(--kt-wartet-border);
  border-radius: 999px;
  overflow: hidden;
}

.cache-balken-fuellung {
  display: block;
  height: 100%;
  background: var(--kt-wartet);
  border-radius: 999px;
  transition: width .4s ease;
}

.cache-zahlen {
  font-variant-numeric: tabular-nums;   /* die Zahlen sollen nicht springen */
}
