/* ==========================================================================
   belaro-os.css · Design System v2 · BELARO OS
   Ablage: static/css/belaro-os.css
   Lädt NACH tailwind.build.css. Enthält Tokens + alle BELARO-Komponenten.
   Tailwind bleibt nur für Layout-Utilities (grid, flex, gap, hidden ...).
   Farben, Radien, Schatten, Typo NIE als Tailwind-Utility — immer Token.
   ========================================================================== */

/* ---------- 0 · Alpine.js x-cloak ----------
   Alpine versteckt x-cloak-Elemente NICHT selbst; ohne diese Regel sind
   Modale beim ersten Rendern sichtbar und fangen jeden Klick dahinter ab
   (Meldung damals: "Speichern tut nichts").

   Stand bis 08/2026 in belaro.css — die das Dashboard gar nicht laedt.
   Auf oeffentlichen Seiten wirkte die Regel, im Dashboard nie. Sie steht
   jetzt hier, weil belaro-os.css von JEDEM Base geladen wird: base,
   public/_base_public, public/landing, onboarding/_wizard_base,
   auth/_auth_base, errors/_base. Die Regel ist gewandert, die Datei
   nicht — belaro.css wird im Dashboard weiterhin nicht geladen. */
[x-cloak] { display: none !important; }

/* ---------- 1 · Tokens ---------- */
:root{
  /* ── `--f-ui` VON Inter AUF Hanken Grotesk, 27.08.2026 ──────────────
     Inter ist als Marken-Schrift seit dem 24.08.2026 nicht mehr
     zulaessig. Das Token stand trotzdem noch darauf.

     WO ES WIRKTE, GEMESSEN — nicht ueberall, aber genau dort, wo der
     Kunde arbeitet:
       `--f-ui` steht an zwei Stellen (Z216 `body` unter
       `[data-bl-ui="v2"]`, Z652 `.bl-tip::after`). Die Body-Regel
       liegt in `:where()`, Spezifitaet 0 — jede Basis mit eigener
       body-Regel schlaegt sie. Und genau eine Basis hat keine:
       `base.html`, die 38 Seiten des Dashboards, Admin und Workbench
       traegt.
       Gemessen am 27.08.2026 mit Chromium:
         /login, /, /demo   body = "Hanken Grotesk", sans-serif
         /dashboard/*       body = Inter, -apple-system, …
       Auf den oeffentlichen Seiten war das Token also folgenlos, im
       Dashboard nicht.

     UND ES ZEIGTE DORT AUCH NICHT INS LEERE: `templates/base.html:54`
     laedt Inter ueber Google Fonts. Der Befund „Inter wird von keiner
     Seite geladen" stimmt fuer `/` und `/login` — die beiden
     gemessenen Seiten —, aber nicht fuer das Dashboard. Der Font-Link
     dort wird in diesem Zug mit entfernt; sonst bliebe eine Ladung
     ohne Verwender.

     Die Fallback-Kette bleibt unveraendert stehen. Sie traegt den
     Fall, dass Google Fonts nicht antwortet — und dieser Fall ist
     real: aus dem Bau-Container ist die Domain nicht erreichbar. */
  --f-ui:'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', sans-serif;
  --f-serif:'Newsreader', Georgia, serif;   /* nur Logo, Berichte, Marketing */
  --f-mono:'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;

  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:64px;
  --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:22px; --r-pill:999px;

  --t-hover:150ms; --t-card:200ms; --t-chart:300ms; --t-drawer:250ms; --t-modal:200ms;
  --e-out:cubic-bezier(.16,1,.3,1);
  --e-io:cubic-bezier(.45,.05,.25,1);
  --e-spring:cubic-bezier(.34,1.16,.64,1);

  --rail:252px; --rail-slim:72px; --wrap-max:1560px;
}

:root,[data-theme="dark"]{
  --bg:#080B14; --bg-2:#0B0F1B;
  --surface:#111726; --surface-2:#161D2F; --surface-3:#1C2438;
  --line:rgba(255,255,255,.065); --line-2:rgba(255,255,255,.10); --line-gold:rgba(212,169,74,.28);
  /* ── --mute VON .58 AUF .68, 23.08.2026 ──────────────────────────
     `--mute` ist der Ton fuer abgeschwaechte Schrift und steht an
     rund 65 Stellen im Repository. Er lag im HELLMODUS bei 4,76:1 auf
     `--surface` — 0,26 ueber der Schwelle, der duennste tragende Wert
     im System. Er war dreimal hintereinander der schwaechste Rest
     eines Pakets: der Platzhalter (#323), das Schliess-Kreuz (#326)
     und jetzt die 92 U2-Befunde, die auf ihn gelegt werden sollen.
     Ein Ton, auf den man 92 Befunde legt, darf nicht auf der Schwelle
     stehen.

     ANGEHOBEN WIRD DIE DECKKRAFT, NICHT DIE FARBE. Kein neuer
     Farbwert, kein neues Token — dieselbe Farbe, weniger
     Durchsichtigkeit. Beide Modi bekommen denselben Wert; die
     bisherige Ungleichheit (.58 dunkel / .60 hell) hatte keinen
     genannten Grund.

     GEMESSEN im Browser gegen alle vier Flaechen, beide Modi:

                  --surface  --surface-2  --surface-3   --bg
       hell .60      4,76        4,68         4,57      4,59   (vorher)
       hell .68      6,31        6,14         5,92      6,01   (jetzt)
       dunkel .58    5,90        5,74         5,48      6,09   (vorher)
       dunkel .68    7,69        7,38         6,96      8,08   (jetzt)

     .66 haette das Ziel „mindestens 5,5:1" auf `--surface` knapp
     erreicht (5,85 hell), auf `--surface-3` aber nur mit 5,56 — ein
     Wert auf der Schwelle. .68 haelt ueber ALLE Flaechen und beide
     Modi mindestens 5,92. */
  --text:#EDEFF4; --mute:rgba(237,239,244,.68);
  /* ⚠️ `--mute-2` IST KEINE SCHRIFTFARBE. Gemessen am 23.08.2026 auf
     Stand 3a970fc gegen `--surface`: 2,58:1 hell und 2,85:1 dunkel —
     in beiden Modi weit unter der Schwelle. Der Ton ist fuer Linien,
     Trenner und Symbole gedacht, nicht fuer Text. Wer eine noch
     schwaechere Schrift als `--mute` braucht, braucht statt dessen
     eine andere Groesse oder ein anderes Gewicht.
     Der Wert bleibt unveraendert.

     SEIT 24.08.2026 STEHT DER SATZ NICHT MEHR ALLEIN DA.
     Bis dahin hat diese Datei ihre eigene Regel 13-mal gebrochen —
     der Waechter konnte es nicht sehen, weil er die Deckkraft der
     Schriftfarbe wegwarf (behoben in Paket 10). Nach der Korrektur
     standen 390 Befunde statt 38, der groesste Teil davon hier.
     Paket 11 hat alle 25 Schriftstellen im Repository auf `--mute`
     umgestellt. Was noch auf `--mute-2` zeigt, sind SECHS Stellen,
     und alle sechs sind Linie, Symbol oder Flaeche:
       belaro-os.css:474        .bl-empty svg   stroke
       bl-charts.js:25          TONE.mute       Linien + Legendenpunkte
       base.html:238            Lupensymbol     stroke
       pruefstand.html:131      Lupensymbol     stroke
       liquidity.html:323       Legendenpunkt   background
       tailwind.config.PHASE6   Namenszuordnung, nicht in Betrieb
     Kommt eine siebte dazu, gehoert sie in diese Liste — oder sie
     ist eine Schriftstelle und dann falsch. */
  --mute-2:rgba(237,239,244,.34);
  --gold:#D4A94A; --gold-2:#E6C377; --gold-dim:rgba(212,169,74,.12);
  /* GOLD ALS SCHRIFT. Der Markenton ist eine FLAECHENfarbe; als Text
     traegt er nur auf dunklem Grund. Im Hellmodus faellt er auf 3,67:1
     (--gold #A87F24 auf Weiss) und die Tailwind-Stufe gold-500
     (#AA8A41) sogar auf 3,27:1 — beides unter der WCAG-Schwelle.
     Deshalb ein eigenes Token fuer den Schrift-Fall, das dem Modus
     folgt. Im Dunkeln ist es der Markenton, im Hellen `--gold-text`
     (#7F631C, 5,67:1 auf Weiss) aus dem zentralen Stylesheet.
     Gemessen am 15.08.2026, docs/waechter.md. */
  --gold-ink: var(--gold);
  --ok:#3EA97B; --info:#4E86D9; --warn:#DFA23C; --push:#DD8340; --bad:#D65C50;
  --grid:rgba(255,255,255,.05);
  --sh-1:0 1px 0 rgba(255,255,255,.04) inset, 0 8px 24px -16px rgba(0,0,0,.9);
  --sh-2:0 1px 0 rgba(255,255,255,.07) inset, 0 20px 48px -22px rgba(0,0,0,1);
  --glass:rgba(11,15,27,.68);
  --glow:0 0 0 1px rgba(212,169,74,.18), 0 0 32px -10px rgba(212,169,74,.30);
  --on-accent:#0A1028;
}

/* ---------- 1b · Schrift auf einer GOLDFLAECHE ----------------------------
   `--on-gold` ist in BEIDEN Modi Navy, und das ist kein Versehen.

   WARUM ES `--on-accent` NICHT TUT — die beiden sehen sich aehnlich und
   verhalten sich verschieden. Das ist eine Falle, deshalb steht der
   Unterschied an beiden Stellen:

       --on-accent   dunkel #0A1028   ·   hell #FFFFFF
       --on-gold     dunkel #0A1028   ·   hell #0A1028

   `--on-accent` kippt mit dem Modus, weil die Akzentflaechen darunter
   es tun. `--gold` tut es NICHT in dieselbe Richtung: im Dunkeln ist
   der Markenton hell (#D4A94A), im Hellen dunkel (#A87F24). Eine
   Schrift, die mitkippt, geht deshalb einmal in die falsche Richtung.
   Gemessen am 23.08.2026 auf `--gold`:

       --text        dunkel 1,91:1  ·  hell 5,01:1
       --on-accent   dunkel 8,57:1  ·  hell 3,67:1   (Weiss auf #A87F24)
       --on-gold     dunkel 8,57:1  ·  hell 8,29:1

   Navy traegt auf beiden Goldtoenen, weil beide dunkel genug ABSTAND
   zu Navy haben und hell genug sind, um Navy zu tragen. Deshalb steht
   der Wert zweimal gleich da statt einmal mit Modus-Wechsel.

   NICHT ZU VERWECHSELN mit `--gold-ink`: das ist die Gegenrichtung —
   GOLD als Schrift auf hellem oder dunklem Grund. `--on-gold` ist
   Schrift AUF Gold. */
:root,[data-theme="dark"]{ --on-gold:#0A1028; }
[data-theme="light"]{      --on-gold:#0A1028; }

[data-theme="light"]{
  --bg:#F2F1EC; --bg-2:#EDEBE4;
  --surface:#FFFFFF; --surface-2:#F8F7F2; --surface-3:#F1EFE8;
  --line:rgba(10,16,40,.09); --line-2:rgba(10,16,40,.14); --line-gold:rgba(168,127,36,.34);
  /* .60 -> .68, Begruendung und Messwerte im Dunkelmodus-Block oben. */
  --text:#0E1526; --mute:rgba(14,21,38,.68);
  /* ⚠️ Keine Schriftfarbe — 2,58:1 hell. Siehe oben. */
  --mute-2:rgba(14,21,38,.40);
  --gold:#A87F24; --gold-2:#C29435; --gold-dim:rgba(212,169,74,.16);
  --gold-ink: var(--gold-text, #7F631C);
  /* --push VON #B96420 AUF #A65518, 15.08.2026. Gemessen: 4,28:1 auf
     Weiss und 3,78:1 auf Creme — unter der Schwelle, und der Ton traegt
     auf der Uebersicht die Kachel „Sie finanzieren 116 Tage" sowie im
     Verlauf die Monatsbetraege. Der neue Wert liegt bei 5,34:1 / 4,72:1.
     Die Aenderung gilt NUR im Hellmodus; im Dunkeln bleibt #DD8340. */
  --ok:#1C7A54; --info:#2F62B0; --warn:#9C7420; --push:#A65518; --bad:#B0402F;
  --grid:rgba(10,16,40,.07);
  --sh-1:0 1px 2px rgba(10,16,40,.05), 0 10px 24px -20px rgba(10,16,40,.30);
  --sh-2:0 2px 6px rgba(10,16,40,.07), 0 22px 44px -22px rgba(10,16,40,.35);
  --glass:rgba(242,241,236,.76);
  --glow:0 0 0 1px rgba(168,127,36,.22), 0 0 28px -12px rgba(168,127,36,.28);
  /* ⚠️ NICHT MIT `--on-gold` VERWECHSELN. Hier ist der Wert WEISS,
     dort Navy — und `--on-gold` ist in beiden Modi Navy. Wer auf einer
     Goldflaeche `--on-accent` benutzt, misst im Hellmodus 3,67:1.
     Die vollstaendige Begruendung steht bei `--on-gold` in Abschnitt 1b. */
  --on-accent:#FFFFFF;
}

/* Heller Gold-Ton für Hover — BEWUSST theme-unabhängig (eine Quelle).
   --gold/--gold-2 kippen mit dem Theme; --gold-bright nicht: die Auth-,
   Errors- und Public-CTAs sind fest dunkel gemalt, laufen aber im Hell-Theme.
   Dort wäre das helle --gold-2 auf Navy DUNKLER (falsche Richtung), deshalb
   ein fixer heller Ton (= --gold-2 des Dunkelmodus). Gold-Hover geht auf
   dunklem Grund nach oben, auf hellem nach unten. */
:root{ --gold-bright:#E6C377; }

/* Score-Stufen — semantisch, nie frei wählen */
:root{
  --score-stabil:var(--ok);
  --score-wachstum:var(--warn);
  --score-druck:var(--push);
  --score-risiko:var(--bad);
}

/* ---------- 2 · Basis ----------------------------------------------------
   ACHTUNG · GESCHALTET.
   Alle globalen Regeln hängen an [data-bl-ui="v2"] auf <html>. Ohne dieses
   Attribut liefert diese Datei NUR Tokens (Abschnitt 1) und die bl-*-
   Komponenten — sie verändert keine bestehende Seite.

   Phase 1: Attribut NICHT setzen. belaro-os.css wird geladen, wirkt aber
            nur als Variablen-Quelle. Aussehen bleibt unverändert.
   Ab Phase 2: <html data-bl-ui="v2"> in den umgestellten Köpfen setzen.
            Kopf für Kopf, nicht global — so bleibt jeder Schritt umkehrbar.

   Ohne diese Schaltung würde das Laden der Datei jede Seite dunkel färben,
   die Schrift auf Inter/14px stellen und Abstände von Überschriften,
   Links und Schaltflächen entfernen.

   ZUSÄTZLICH: Die Regeln stehen in :where() und haben damit Spezifität 0.
   Jede Tailwind-Utility, jede bl-*-Komponente und jede Seitenklasse gewinnt
   gegen den Reset. Ohne :where() läge [data-bl-ui="v2"] a bei 0-1-1 und
   würde text-*-Utilities schlagen — genau daran brach der CTA im
   Snapshot-Banner (weiß auf weiß). Ausgenommen sind :focus-visible und
   ::selection: die tragen die Bedienbarkeit und bleiben scharf.
   ------------------------------------------------------------------------ */
:where([data-bl-ui="v2"]) *{box-sizing:border-box}
:where([data-bl-ui="v2"]),:where([data-bl-ui="v2"] body){margin:0;padding:0;min-height:100%}
:where([data-bl-ui="v2"] body){
  background:var(--bg); color:var(--text);
  font-family:var(--f-ui); font-size:14px; line-height:1.5; letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
  transition:background-color var(--t-card) var(--e-io), color var(--t-card) var(--e-io);
}
:where([data-bl-ui="v2"][data-theme="dark"] body){
  background-image:
    radial-gradient(1200px 620px at 84% -18%, rgba(212,169,74,.075), transparent 62%),
    radial-gradient(900px 520px at 4% 104%, rgba(78,134,217,.09), transparent 64%);
  background-attachment:fixed;
}
:where([data-bl-ui="v2"] a){color:inherit;text-decoration:none}
:where([data-bl-ui="v2"] button){font:inherit;color:inherit;background:none;border:0;cursor:pointer}
:where([data-bl-ui="v2"] h1,[data-bl-ui="v2"] h2,
       [data-bl-ui="v2"] h3,[data-bl-ui="v2"] h4){margin:0;font-weight:600;letter-spacing:-.015em;line-height:1.25}
/* Fokus und Auswahl bleiben scharf — sie dürfen von Utilities nicht
   überschrieben werden, weil sie die Bedienbarkeit tragen. */
[data-bl-ui="v2"] :focus-visible{outline:none;box-shadow:var(--glow);border-radius:8px}
[data-bl-ui="v2"] ::selection{background:var(--gold-dim)}

/* ---------- 3 · Gerüst ---------- */
.bl-app{display:flex;min-height:100dvh;padding:var(--s3);gap:var(--s3)}
.bl-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--s3)}
.bl-wrap{padding:0 0 var(--s7);display:flex;flex-direction:column;gap:var(--s3);max-width:var(--wrap-max)}

.bl-rail{
  width:var(--rail);flex:none;position:sticky;top:var(--s3);align-self:flex-start;
  height:calc(100dvh - var(--s5));display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);
  box-shadow:var(--sh-1);z-index:40;overflow:hidden;
}
.bl-rail__head{display:flex;align-items:center;gap:var(--s3);padding:18px 16px 14px}
.bl-mark{width:32px;height:32px;border-radius:9px;flex:none;display:grid;place-items:center;
  background:linear-gradient(155deg,var(--gold-2),#B08830);color:#0A1028;
  font-family:var(--f-serif);font-weight:600;font-size:19px;
  box-shadow:0 6px 16px -8px rgba(212,169,74,.6)}
.bl-wm{font-size:15px;font-weight:600;white-space:nowrap}
.bl-wm span{color:var(--gold-ink);font-weight:450}

.bl-nav{padding:var(--s2) var(--s3);display:flex;flex-direction:column;gap:2px;overflow-y:auto}
.bl-nav__cap{padding:16px 8px 6px}
.bl-nav a{display:flex;align-items:center;gap:11px;padding:9px 10px;border-radius:var(--r-sm);
  font-size:13.5px;font-weight:450;color:var(--mute);position:relative;white-space:nowrap;
  transition:background var(--t-hover) var(--e-out),color var(--t-hover) var(--e-out)}
.bl-nav a:hover{background:var(--surface-2);color:var(--text)}
.bl-nav a.is-active{background:var(--surface-2);color:var(--text);font-weight:500}
.bl-nav a.is-active::before{content:'';position:absolute;left:-13px;top:8px;bottom:8px;width:2px;background:var(--gold);border-radius:0 2px 2px 0}
.bl-nav svg{width:17px;height:17px;flex:none;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.bl-nav__cnt{margin-left:auto;font-family:var(--f-mono);font-size:10px;color:var(--mute)}
.bl-rail__foot{margin-top:auto;padding:var(--s3);border-top:1px solid var(--line)}

.bl-top{
  position:sticky;top:var(--s3);z-index:30;display:flex;align-items:center;gap:var(--s2);
  padding:10px 14px;border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--glass);backdrop-filter:saturate(160%) blur(20px);-webkit-backdrop-filter:saturate(160%) blur(20px);
  box-shadow:var(--sh-1);
}

/* ---------- 4 · Raster (12 Spalten) ---------- */
.bl-g{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--s3)}
/* Senkrechter Stapel mit demselben Abstand wie .bl-main. Noetig fuer
   Zwischencontainer — ein Reiter-Panel etwa ist selbst direktes Kind von
   .bl-main und bekommt den Abstand, seine Kinder aber nicht. Ohne das
   stossen die Karten im Panel ohne Luft aneinander. */
.bl-stack{display:flex;flex-direction:column;gap:var(--s3)}

/* `hidden` muss IMMER gewinnen — auch gegen Klassen, die display setzen.
   Die UA-Regel [hidden]{display:none} hat Spezifitaet 0-1-0 und steht ganz
   vorn; jede spaetere Klasse mit display schlaegt sie. Beim Einbau von
   .bl-stack ist genau das passiert: Alle vier Reiter-Panels waren
   gleichzeitig sichtbar, obwohl drei das hidden-Attribut trugen. Kein Test
   findet das — es ist eine Kaskaden-Frage, kein Markup-Fehler.
   Eine Regel statt eines Flickens je Klasse. */
[hidden]{display:none !important}
.bl-c3{grid-column:span 3}.bl-c4{grid-column:span 4}.bl-c5{grid-column:span 5}
.bl-c6{grid-column:span 6}.bl-c7{grid-column:span 7}.bl-c8{grid-column:span 8}
.bl-c9{grid-column:span 9}.bl-c12{grid-column:span 12}

/* ---------- 5 · Card ---------- */
.bl-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-1);position:relative;overflow:hidden;
  transition:transform var(--t-card) var(--e-out),box-shadow var(--t-card) var(--e-out),border-color var(--t-card) var(--e-out);
}
.bl-card--pad{padding:var(--s4) 18px}
.bl-card--flat{box-shadow:none;background:var(--surface-2)}
.bl-card__h{display:flex;align-items:center;gap:10px;padding:14px 18px;border-bottom:1px solid var(--line)}
.bl-card__h h2{font-size:13.5px;font-weight:600}
.bl-card__h .bl-eyebrow{margin-left:auto}
.bl-card__f{padding:12px 18px;border-top:1px solid var(--line);display:flex;align-items:center;gap:10px}
.bl-tap{cursor:pointer}
.bl-tap:hover{transform:scale(1.012);box-shadow:var(--sh-2);border-color:var(--line-2)}
.bl-tap:active{transform:scale(1.004)}

/* ---------- 6 · Buttons / Inputs ---------- */
.bl-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:8px 13px;border-radius:var(--r-sm);
  font-size:13px;font-weight:450;color:var(--mute);border:1px solid var(--line);
  transition:border-color var(--t-hover) var(--e-out),color var(--t-hover) var(--e-out),background var(--t-hover) var(--e-out)}
.bl-btn:hover{border-color:var(--line-2);color:var(--text);background:var(--surface-2)}
.bl-btn svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.7}
.bl-btn--gold{background:linear-gradient(155deg,var(--gold-2),#B08830);color:#0A1028;font-weight:600;border-color:transparent;
  box-shadow:0 6px 18px -10px rgba(212,169,74,.8);
  transition:filter var(--t-hover) var(--e-out),box-shadow var(--t-hover) var(--e-out),transform var(--t-hover) var(--e-out)}
.bl-btn--gold:hover{filter:brightness(1.06);transform:translateY(-1px);color:#0A1028;background:linear-gradient(155deg,var(--gold-2),#B08830)}
.bl-btn--ghost{border-color:transparent}
.bl-btn--ghost:hover{border-color:var(--line)}
.bl-btn--wide{width:100%}
.bl-btn--sm{padding:6px 10px;font-size:12px}
.bl-icb{width:34px;height:34px;border-radius:var(--r-sm);border:1px solid var(--line);display:grid;place-items:center;position:relative;
  transition:border-color var(--t-hover) var(--e-out),background var(--t-hover) var(--e-out)}
.bl-icb:hover{border-color:var(--line-2);background:var(--surface-2)}
.bl-icb svg{width:16px;height:16px;stroke:var(--mute);fill:none;stroke-width:1.7}

.bl-field{display:flex;flex-direction:column;gap:6px}
.bl-field label{font-size:12.5px;color:var(--mute)}
.bl-input,.bl-select,.bl-textarea{
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:9px 12px;font-size:14px;color:var(--text);width:100%;
  transition:border-color var(--t-hover) var(--e-out),box-shadow var(--t-hover) var(--e-out)}
.bl-input:hover,.bl-select:hover{border-color:var(--line-2)}
.bl-input:focus,.bl-select:focus,.bl-textarea:focus{outline:none;border-color:var(--gold);box-shadow:var(--glow)}
.bl-input.bl-num{font-family:var(--f-mono);text-align:right}
.bl-hint{font-size:11.5px;color:var(--mute)}
.bl-seg{display:flex;border:1px solid var(--line);border-radius:var(--r-pill);padding:2px;width:max-content}
.bl-seg button{padding:5px 12px;border-radius:var(--r-pill);font-size:12.5px;color:var(--mute);
  transition:background var(--t-hover) var(--e-out),color var(--t-hover) var(--e-out)}
.bl-seg button[aria-pressed="true"]{background:var(--surface-2);color:var(--text);font-weight:500}

/* ---------- 7 · Status ---------- */
.bl-badge{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line-2);border-radius:var(--r-pill);
  padding:3px 10px;font-size:12px;color:var(--mute)}
.bl-badge i{width:6px;height:6px;border-radius:50%;flex:none}
.bl-badge--ok i{background:var(--ok)} .bl-badge--warn i{background:var(--warn)}
.bl-badge--push i{background:var(--push)} .bl-badge--bad i{background:var(--bad)}
/* .bl-tag ist eine WERTanzeige, kein Zustand. „30 Tage", „gesperrt".
   Wer damit eine Kategorie oder einen Aufwand zeigt, benutzt die
   falsche Familie — dafuer gibt es .bl-pl (Abschnitt 7b). */
.bl-tag{font-family:var(--f-mono);font-size:9px;letter-spacing:.05em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:4px;padding:2px 5px;color:var(--mute)}
.bl-help{width:14px;height:14px;border-radius:var(--r-pill);display:inline-grid;place-items:center;
  border:1px solid var(--line-2);font-size:9px;color:var(--mute);flex:none;cursor:help}

/* ---------- 7b · Plaketten ------------------------------------------
   DER ZUSTAND STECKT IN DER FLAECHE EINES PUNKTES, NIE IN DER FARBE
   DER SCHRIFT.

   Bis 24.08.2026 gab es elf Plaketten-Familien in neun <style>-
   Bloecken, jede mit eigenen festen Farben, und jede nach demselben
   Muster gebaut: farbige Schrift auf einer durchsichtigen Fuellung
   derselben Farbe. Das ergab im Dunkelmodus Werte bis herunter zu
   1,34:1 (`.pill-tier-core`, gemessen). Der Grund ist keine falsche
   Farbwahl — es ist die Bauart: Schrift und Flaeche muessen beide
   dem Thema folgen, und eine Fuellung, die den Zustand traegt, kann
   das nicht, ohne die Schrift darauf mitzureissen.

   Deshalb: Die SCHRIFT ist immer `--mute` (oder `--text`), also
   themengefuehrt und gemessen ueber 4,5:1. Der ZUSTAND sitzt in
   einem 6px-Punkt. Ein Punkt ist kein Text; fuer ihn gilt WCAG
   1.4.11 mit 3:1 gegen seinen Grund, nicht 4,5:1.

   Vorbild ist `.bl-badge` — die einzige Familie im Bestand, die vor
   diesem Umbau in beiden Modi getragen hat, und zwar genau deshalb.
   `.bl-badge` bleibt unveraendert; `.bl-pl` ist ihre kleine,
   versale Schwester fuer Tabellen und Listen.

   ── DIE TOENE, GEMESSEN AM 24.08.2026 ────────────────────────────
   Punkt gegen seinen Grund (Schwelle 3,0:1), schwaechster der vier
   Flaechen --surface/-2/-3/--bg:

     --ok    5,27 dunkel / 4,61 hell      --push  5,44 / 4,64
     --info  4,22 dunkel / 4,22 hell      --bad   4,05 / 5,04
     --warn  6,90 dunkel / 3,70 hell      --gold  7,05 / 3,19
     --mute  6,96 dunkel / 5,94 hell      --text 13,43 / 15,82

   `--mute-2` faellt mit 2,79 dunkel / 2,52 hell und ist als Punkt
   NICHT brauchbar — derselbe Ton, der auch als Schrift nicht taugt.

   ── WAS SICH UNTERSCHEIDEN LAESST ────────────────────────────────
   Zwei Zustaende muessen im Punkt AUSEINANDERZUHALTEN sein. Das ist
   nicht dasselbe wie „kontrastreich gegen den Grund": zwei Farben
   koennen dieselbe Leuchtdichte haben und klar verschieden aussehen.
   Gemessen wird deshalb der Farbabstand dE (CIE76), nicht das
   Kontrastverhaeltnis. Von 28 Paaren liegt genau EINES unter der
   Marke dE 20:

     --warn / --gold   dE 9,6 dunkel · dE 5,2 hell

   Die beiden sind faktisch derselbe Ton. Innerhalb EINER Zustands-
   art duerfen sie nie zusammen vorkommen. Das engste noch gueltige
   Paar ist --warn / --push mit dE 20,0 dunkel und 22,6 hell.

   Damit stehen SIEBEN unterscheidbare Toene bereit:
     --ok · --info · --push · --bad · --mute · --text · und EINER
     von { --warn, --gold }.
   -------------------------------------------------------------- */
.bl-pl{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-family:var(--f-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;
  border:1px solid var(--line-2);border-radius:2px;padding:3px 8px;
  background:transparent;color:var(--mute)}
.bl-pl::before{content:'';width:6px;height:6px;border-radius:50%;flex:none;
  background:var(--mute)}
/* Fuer die eine Plakette, die lauter sein soll als ihre Nachbarn —
   ueber das GEWICHT der Schrift, nicht ueber ihre Farbe. */
.bl-pl--laut{color:var(--text)}

/* Z1 · Kategorie einer Massnahme — unterscheidend, nicht wertend.
   DSO/DPO/DIO/CR/FA. Kein --warn, weil --gold dabei ist. */
.bl-pl--kat-dso::before{background:var(--info)}
.bl-pl--kat-dpo::before{background:var(--gold)}
.bl-pl--kat-dio::before{background:var(--ok)}
.bl-pl--kat-cr::before {background:var(--bad)}
.bl-pl--kat-fa::before {background:var(--push)}

/* Z2 · Tarif — unterscheidend. Kein --warn (--gold ist dabei). */
.bl-pl--tarif-core::before    {background:var(--mute)}
.bl-pl--tarif-pro::before     {background:var(--gold)}
.bl-pl--tarif-advanced::before{background:var(--info)}
.bl-pl--tarif-addon::before   {background:var(--push)}

/* Z3 · Abostatus — wertend. Kein --gold (--warn ist dabei). */
.bl-pl--abo-active::before  {background:var(--ok)}
.bl-pl--abo-trialing::before{background:var(--info)}
.bl-pl--abo-pending::before {background:var(--warn)}
.bl-pl--abo-past_due::before{background:var(--push)}
.bl-pl--abo-canceled::before{background:var(--bad)}
.bl-pl--abo-inaktiv::before {background:var(--mute)}

/* Z4 · Faelligkeit einer Rechnung — wertend. */
.bl-pl--rg-bezahlt::before    {background:var(--ok)}
.bl-pl--rg-offen::before      {background:var(--warn)}
.bl-pl--rg-bald::before       {background:var(--push)}
.bl-pl--rg-ueberfaellig::before{background:var(--bad)}

/* Z5 · Schwierigkeit / Aufwand — wertend. */
.bl-pl--auf-niedrig::before{background:var(--ok)}
.bl-pl--auf-mittel::before {background:var(--warn)}
.bl-pl--auf-hoch::before   {background:var(--bad)}

/* Z6 · Projektphase — SIEBEN Werte, siehe den Befund unten.
   Verbraucht alle sieben unterscheidbaren Toene. --gold faellt
   weg, weil --warn gebraucht wird. */
.bl-pl--ph-open::before     {background:var(--mute)}
.bl-pl--ph-kickoff::before  {background:var(--info)}
.bl-pl--ph-analysis::before {background:var(--push)}
.bl-pl--ph-plan::before     {background:var(--warn)}
.bl-pl--ph-execution::before{background:var(--text)}
.bl-pl--ph-review::before   {background:var(--bad)}
.bl-pl--ph-closed::before   {background:var(--ok)}

/* Z7 · Herkunft eines Einstellungswerts — unterscheidend. */
.bl-pl--q-db::before     {background:var(--ok)}
.bl-pl--q-env::before    {background:var(--info)}
.bl-pl--q-default::before{background:var(--gold)}
.bl-pl--q-empty::before  {background:var(--mute)}

/* Z8 · Fortschritt der Baseline — wertend. */
.bl-pl--bl-ok::before     {background:var(--ok)}
.bl-pl--bl-pending::before{background:var(--warn)}

/* Z9 · Vertrauensgrad einer maschinell gelesenen Zahl — wertend. */
.bl-pl--vt-high::before   {background:var(--ok)}
.bl-pl--vt-medium::before {background:var(--warn)}
.bl-pl--vt-low::before    {background:var(--bad)}
.bl-pl--vt-missing::before{background:var(--mute)}

/* ---------- 8 · Lagebild (KI-Zeile, jede Seite oben) ---------- */
.bl-brief{display:flex;align-items:center;gap:14px;padding:14px 18px;
  background:linear-gradient(100deg,var(--gold-dim),transparent 62%),var(--surface);
  border:1px solid var(--line-gold);border-radius:var(--r-lg);box-shadow:var(--sh-1)}
.bl-brief__sig{width:34px;height:34px;border-radius:10px;flex:none;display:grid;place-items:center;
  border:1px solid var(--line-gold);color:var(--gold-ink);background:var(--gold-dim)}
.bl-brief__sig svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.6}
.bl-brief p{margin:0;font-size:14px}
.bl-brief b{font-weight:600}
.bl-brief__sub{font-size:12px;color:var(--mute);margin-top:2px}
.bl-brief__acts{margin-left:auto;display:flex;gap:var(--s2);flex:none}

/* ---------- 9 · KPI ---------- */
.bl-kpi{display:flex;flex-direction:column;gap:9px}
.bl-kpi__lbl{font-size:12.5px;color:var(--mute);display:flex;align-items:center;gap:6px}
.bl-kpi__val{font-size:30px}
.bl-kpi__val u{text-decoration:none;font-size:.46em;color:var(--mute);font-weight:450;margin-left:4px;letter-spacing:0}
.bl-delta{font-family:var(--f-mono);font-size:11px;display:flex;align-items:center;gap:5px}
.bl-delta--up{color:var(--ok)} .bl-delta--down{color:var(--bad)} .bl-delta--flat{color:var(--mute)}
.bl-spark{width:100%;height:32px;display:block;overflow:visible}

/* ---------- 10 · Grafik-Grammatik ---------- */
/* 10a Balken-Spur (Anteile, Alterung, Auslastung) */
.bl-track{display:flex;height:10px;border-radius:5px;overflow:hidden;background:var(--grid)}
.bl-track i{display:block;height:100%;transform-origin:left center}
.bl-track--thin{height:3px;border-radius:2px}
.bl-legend{display:flex;align-items:center;gap:10px;font-size:12.5px;line-height:1.4;padding:7px 0;border-bottom:1px solid var(--line)}
.bl-legend:last-child{border-bottom:0}
.bl-legend i{width:8px;height:8px;border-radius:2px;flex:none}
.bl-legend__amt{margin-left:auto;font-family:var(--f-mono);font-size:12.5px;white-space:nowrap}
.bl-legend__pct{color:var(--mute);font-family:var(--f-mono);font-size:11px;width:40px;text-align:right;flex:none;white-space:nowrap}

/* 10b Ampel-Instrument */
.bl-dial{width:190px;height:118px}
.bl-dial .arc{stroke-dasharray:280;stroke-dashoffset:280}
.is-in .bl-dial .arc{animation:bl-draw 700ms var(--e-out) forwards}
.is-in .bl-dial .arc.a2{animation-delay:70ms}
.is-in .bl-dial .arc.a3{animation-delay:140ms}
.is-in .bl-dial .arc.a4{animation-delay:210ms}

/* 10c Kapital-Kreislauf (Signatur) */
.bl-cyc{padding:16px 18px 18px}
.bl-cyc__scale{position:relative;height:12px;margin-bottom:8px}
.bl-cyc__scale span{position:absolute;top:0;transform:translateX(-50%);font-family:var(--f-mono);font-size:10px;color:var(--mute)}
.bl-lane{display:flex;align-items:center;gap:14px;margin-bottom:8px}
.bl-lane__key{width:108px;flex:none;text-align:right;font-family:var(--f-mono);font-size:9.5px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--mute);line-height:1.35}
.bl-lane__trk{flex:1;position:relative;height:30px}
.bl-bar{position:absolute;inset:0;display:flex;border-radius:9px}
.bl-bar--clip{overflow:hidden}
.bl-sg{display:flex;align-items:center;padding:0 11px;font-family:var(--f-mono);font-size:10.5px;
  white-space:nowrap;overflow:hidden;transition:filter var(--t-hover) var(--e-out)}
.bl-sg:hover{filter:brightness(1.12)}
.bl-sg--dio{background:linear-gradient(180deg,#26304A,#1E273D);color:#A8B4D0}
.bl-sg--dso{background:linear-gradient(180deg,#33436E,#2A3759);color:#C6D0E8}
[data-theme="light"] .bl-sg--dio{background:#DEE2EC;color:#26304A}
[data-theme="light"] .bl-sg--dso{background:#C2CBE0;color:#22304F}
.bl-sg--dpo{background:repeating-linear-gradient(135deg,rgba(212,169,74,.26) 0 7px,rgba(212,169,74,.09) 7px 14px);
  border:1px dashed var(--line-gold);border-radius:9px;color:var(--gold-ink)}
.bl-sg--net{border:1px solid var(--push);border-left:0;border-radius:0 9px 9px 0;color:var(--push);justify-content:flex-end}

/* 10d Chart-Rahmen */
.bl-chart{padding:12px 18px 16px}
.bl-chart svg{width:100%;height:210px;display:block;overflow:visible}
.bl-chart--sm svg{height:150px}
.bl-chart--lg svg{height:300px}
.bl-chart__foot{display:flex;gap:18px;flex-wrap:wrap;margin-top:12px;font-size:12px;color:var(--mute)}
.bl-chart__foot i{width:14px;height:2px;display:inline-block;margin-right:7px;vertical-align:middle;border-radius:2px}

/* ---------- 11 · Listen ---------- */
.bl-row{display:flex;align-items:center;gap:12px;padding:11px 18px;border-bottom:1px solid var(--line);font-size:13.5px}
.bl-row:last-child{border-bottom:0}
.bl-row .amt{margin-left:auto;font-family:var(--f-mono);font-size:13px}
.bl-row small{display:block;font-size:11px;color:var(--mute)}
.bl-row--tap{cursor:pointer;transition:background var(--t-hover) var(--e-out)}
.bl-row--tap:hover{background:var(--surface-2)}
.bl-mini{width:26px;height:26px;border-radius:8px;flex:none;display:grid;place-items:center;border:1px solid var(--line)}
.bl-mini svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:1.7}

/* Rangzeile (Maßnahmen, Empfehlungen) */
.bl-rank{display:grid;grid-template-columns:26px 1fr auto;gap:14px;align-items:center;
  padding:13px 18px;border-bottom:1px solid var(--line);cursor:pointer;
  transition:background var(--t-hover) var(--e-out)}
.bl-rank:last-child{border-bottom:0}
.bl-rank:hover{background:var(--surface-2)}
.bl-rank__n{font-family:var(--f-mono);font-size:10.5px;color:var(--mute);border:1px solid var(--line);
  border-radius:6px;text-align:center;padding:3px 0}
.bl-rank h3{font-size:13.5px;font-weight:500}
.bl-rank p{margin:3px 0 0;font-size:12px;color:var(--mute)}
.bl-rank__eff{text-align:right}
.bl-rank__eff b{font-size:15px;font-weight:600;color:var(--ok);font-variant-numeric:tabular-nums;letter-spacing:-.02em}

/* Datentabelle (Admin, Workbench, Aging-Detail) */
.bl-table{width:100%;border-collapse:collapse;font-size:13px}
.bl-table th{text-align:left;font-family:var(--f-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);font-weight:400;padding:10px 14px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--surface)}
.bl-table td{padding:11px 14px;border-bottom:1px solid var(--line)}
.bl-table tr:last-child td{border-bottom:0}
.bl-table tbody tr{transition:background var(--t-hover) var(--e-out)}
.bl-table tbody tr:hover{background:var(--surface-2)}
.bl-table .n{font-family:var(--f-mono);text-align:right;font-variant-numeric:tabular-nums}

/* ---------- 12 · Dropzone / Intake ---------- */
.bl-drop{border:1.5px dashed var(--line-2);border-radius:var(--r-lg);padding:var(--s6) var(--s5);
  text-align:center;background:var(--surface-2);
  transition:border-color var(--t-hover) var(--e-out),background var(--t-hover) var(--e-out)}
.bl-drop:hover,.bl-drop.is-over{border-color:var(--gold);background:var(--gold-dim)}
.bl-drop svg{width:30px;height:30px;stroke:var(--gold);fill:none;stroke-width:1.4;margin-bottom:10px}
.bl-drop h3{font-size:15px;margin-bottom:5px}
.bl-drop p{margin:0;font-size:12.5px;color:var(--mute)}

/* Verarbeitungs-Pipeline */
.bl-pipe{display:flex;align-items:center;gap:0;padding:16px 18px}
.bl-pipe__st{flex:1;display:flex;flex-direction:column;gap:6px;position:relative;padding-right:14px}
.bl-pipe__st::after{content:'';position:absolute;right:0;top:9px;width:10px;height:1px;background:var(--line-2)}
.bl-pipe__st:last-child::after{display:none}
.bl-pipe__dot{width:18px;height:18px;border-radius:50%;border:1.5px solid var(--line-2);display:grid;place-items:center}
.bl-pipe__st.is-done .bl-pipe__dot{border-color:var(--ok);background:var(--ok);color:var(--on-accent)}
.bl-pipe__st.is-now .bl-pipe__dot{border-color:var(--gold);box-shadow:var(--glow)}
.bl-pipe__st span{font-size:11.5px;color:var(--mute)}
.bl-pipe__st.is-now span{color:var(--text)}

/* ---------- 13a · Hover-Hilfen für Gold-Links/CTAs auf DUNKLEM Grund --------
   Ersetzen frühere No-op-Hover (hover:text-gold-400 auf text-gold-400 usw.).
   Alle heutigen Einsatzstellen (Auth, Errors, Public-CTAs) sind gold-auf-navy.
   Bewusst NICHT --gold-2 (theme-gebunden): Standard-Theme ist jetzt hell,
   diese Seiten sind aber weiterhin dunkel gemalt → der Hell-Wert von --gold-2
   wäre auf Navy DUNKLER statt heller. Fixer Hell-Gold-Ton (#E6C377, = --gold-2
   im Dunkelmodus) lässt das Element auf Dunkel „aufleuchten". Wenn diese Seiten
   auf Tokens migriert sind (spätere Phase), auf --gold-2 umstellen. */
.bl-hgold{transition:color var(--t-hover) var(--e-io)}
.bl-hgold:hover{color:var(--gold-bright)}
.bl-hgold-fill{transition:background-color var(--t-hover) var(--e-io)}
.bl-hgold-fill:hover{background:var(--gold-bright)}

/* ---------- 13 · Leerzustand ---------- */
.bl-empty{padding:var(--s7) var(--s5);text-align:center;display:flex;flex-direction:column;align-items:center;gap:10px}
.bl-empty svg{width:48px;height:48px;stroke:var(--mute-2);fill:none;stroke-width:1.2}
.bl-empty h3{font-size:15px}
.bl-empty p{margin:0;font-size:13px;color:var(--mute);max-width:44ch}

/* ---------- 14 · Drawer + Modal + Palette ---------- */
.bl-scrim{position:fixed;inset:0;background:rgba(4,7,14,.55);backdrop-filter:blur(4px);
  opacity:0;pointer-events:none;transition:opacity var(--t-drawer) var(--e-io);z-index:60}
.bl-scrim.is-open{opacity:1;pointer-events:auto}
.bl-drawer{position:fixed;top:var(--s3);right:var(--s3);bottom:var(--s3);width:min(430px,92vw);
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-xl);
  box-shadow:0 40px 90px -40px rgba(0,0,0,.9);transform:translateX(calc(100% + 16px));
  z-index:61;display:flex;flex-direction:column;overflow:hidden;
  /* visibility haelt den geschlossenen Zustand aus der Tab-Reihenfolge heraus:
     ohne sie waeren die Links im Ueberlauf-Sheet per Tastatur erreichbar,
     obwohl es unsichtbar neben dem Bildschirm liegt. Verzoegert, damit die
     Schliess-Bewegung noch sichtbar ablaeuft. */
  visibility:hidden;
  transition:transform var(--t-drawer) var(--e-out),visibility 0s linear var(--t-drawer)}
.bl-drawer.is-open{transform:none;visibility:visible;
  transition:transform var(--t-drawer) var(--e-out),visibility 0s}
.bl-drawer__h{display:flex;align-items:center;gap:12px;padding:18px;border-bottom:1px solid var(--line)}
.bl-drawer__b{padding:18px;overflow:auto}
.bl-modal{position:fixed;inset:0;z-index:70;display:grid;place-items:start center;padding-top:13vh;
  background:rgba(4,7,14,.5);backdrop-filter:blur(8px);opacity:0;pointer-events:none;
  transition:opacity var(--t-modal) var(--e-io)}
.bl-modal.is-open{opacity:1;pointer-events:auto}
.bl-modal__box{width:min(580px,92vw);background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-xl);
  box-shadow:0 50px 100px -40px rgba(0,0,0,.9);overflow:hidden;
  transform:translateY(-8px) scale(.985);transition:transform var(--t-modal) var(--e-out)}
.bl-modal.is-open .bl-modal__box{transform:none}

/* ---------- 15 · Tooltip ---------- */
.bl-tip{position:relative}
.bl-tip::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translate(-50%,4px);
  background:var(--surface-3);border:1px solid var(--line-2);color:var(--text);padding:7px 10px;border-radius:8px;
  font-size:12px;font-family:var(--f-ui);letter-spacing:0;white-space:normal;width:max-content;max-width:240px;
  opacity:0;pointer-events:none;z-index:55;box-shadow:var(--sh-2);
  transition:opacity var(--t-hover) var(--e-out),transform var(--t-hover) var(--e-out)}
.bl-tip:hover::after,.bl-tip:focus-visible::after{opacity:1;transform:translate(-50%,0)}

/* ---------- 16 · Bewegung ---------- */
.bl-rise{opacity:0;transform:translateY(10px)}
.is-in.bl-rise{animation:bl-rise 420ms var(--e-out) both}
@keyframes bl-rise{to{opacity:1;transform:none}}
.bl-draw{stroke-dasharray:var(--len,900);stroke-dashoffset:var(--len,900)}
.is-in .bl-draw{animation:bl-draw 900ms var(--e-out) forwards}
@keyframes bl-draw{to{stroke-dashoffset:0}}
.bl-fade{opacity:0}
.is-in .bl-fade{animation:bl-fade 420ms var(--e-out) 260ms forwards}
@keyframes bl-fade{to{opacity:1}}
.bl-growx{transform:scaleX(0);transform-origin:left center}
.is-in .bl-growx{animation:bl-growx 640ms var(--e-out) both}
.is-in .bl-growx.d2{animation-delay:100ms}
.is-in .bl-growx.d3{animation-delay:180ms}
@keyframes bl-growx{to{transform:scaleX(1)}}
.bl-mk{opacity:0}
.is-in .bl-mk{animation:bl-mk 320ms var(--e-spring) 760ms forwards}
@keyframes bl-mk{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}
.bl-skel{background:linear-gradient(90deg,var(--surface-2) 0%,var(--surface-3) 50%,var(--surface-2) 100%);
  background-size:200% 100%;animation:bl-skel 1.3s var(--e-io) infinite;border-radius:6px}
@keyframes bl-skel{to{background-position:-200% 0}}

/* ---------- 17 · Breakpoints ----------
   Die Sichtbarkeits-Standards stehen BEWUSST vor den Media-Queries: sie haben
   dieselbe Spezifität (0-1-0) wie die Regeln darin, also entscheidet die
   Reihenfolge. Standen sie danach (wie urspruenglich), gewann immer der
   Standard und .bl-only-sm/.bl-txt-m blieben auf jeder Breite unsichtbar —
   deshalb war der Theme-Umschalter auf dem Handy nicht erreichbar. */
.bl-txt-m{display:none}
.bl-only-sm{display:none}
/* Sichtbar genau dort, wo .bl-hide-md wegblendet (unter 1280) — aber nicht auf
   dem Handy, dort uebernimmt das Ueberlauf-Sheet. Schliesst die Luecke
   768–1279, in der sonst weder Segment noch Sheet erreichbar waeren. */
.bl-only-md{display:none}

@media (max-width:1279px){
  :root{--rail:var(--rail-slim)}
  .bl-rail .bl-wm,.bl-rail .bl-nav__cap,.bl-rail .bl-nav__cnt,.bl-rail .bl-nav a .txt{display:none}
  /* Icon-Rail: im Fuß bleibt nur das Kürzel stehen. Ohne diese Regel
     umbrechen Name und Firma senkrecht in 72 px Breite. */
  .bl-rail__foot b,.bl-rail__foot small,.bl-rail__foot .txt{display:none}
  .bl-rail__foot > *{justify-content:center;padding:6px;gap:0}
  .bl-rail__foot > * > *:not(.bl-mini):not(.bl-av){display:none}
  .bl-rail__head{justify-content:center;padding:18px 0 14px}
  .bl-nav a{justify-content:center;padding:11px 0;gap:0}
  .bl-nav a::after{content:attr(data-label);position:absolute;left:calc(100% + 12px);white-space:nowrap;
    background:var(--surface-3);border:1px solid var(--line-2);color:var(--text);padding:5px 10px;border-radius:8px;
    font-size:12px;opacity:0;pointer-events:none;transform:translateX(-4px);z-index:50;
    transition:opacity var(--t-hover) var(--e-out),transform var(--t-hover) var(--e-out)}
  .bl-nav a:hover::after{opacity:1;transform:none}
  .bl-c3,.bl-c4{grid-column:span 6}
  .bl-c5,.bl-c6,.bl-c7,.bl-c8,.bl-c9{grid-column:span 12}
  .bl-t12{grid-column:span 12}
  .bl-hide-md{display:none!important}
  .bl-only-md{display:grid}
}
@media (max-width:767px){
  .bl-app{padding:0;gap:0;display:block}
  .bl-rail{position:fixed;left:0;right:0;bottom:0;top:auto;width:auto;height:auto;flex-direction:row;
    border-radius:0;border-left:0;border-right:0;border-bottom:0;box-shadow:none;
    background:var(--glass);backdrop-filter:saturate(170%) blur(22px);-webkit-backdrop-filter:saturate(170%) blur(22px);
    padding-bottom:env(safe-area-inset-bottom)}
  .bl-rail__head,.bl-rail__foot{display:none}
  .bl-nav{flex-direction:row;width:100%;padding:7px 4px 8px;gap:0;overflow:visible}
  .bl-nav a{flex:1;flex-direction:column;gap:4px;font-size:9.5px;padding:6px 2px;text-align:center}
  .bl-nav a::after{display:none}
  .bl-nav a.is-active{background:none}
  .bl-nav a.is-active::before{left:50%;transform:translateX(-50%);top:-7px;bottom:auto;width:20px;height:2px;border-radius:0 0 2px 2px}
  .bl-nav a .txt{display:none}
  .bl-nav a .txt-m{display:block}
  .bl-nav a.bl-nav--sec{display:none}
  .bl-main{gap:10px}
  .bl-top{position:sticky;top:0;border-radius:0;border-left:0;border-right:0;border-top:0;padding:9px 12px}
  .bl-wrap{padding:0 12px 96px;gap:10px}
  .bl-g{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .bl-c3{grid-column:span 1}
  .bl-c4,.bl-c5,.bl-c6,.bl-c7,.bl-c8,.bl-c9,.bl-c12{grid-column:span 2}
  .bl-kpi__val{font-size:22px}
  .bl-kpi__lbl{font-size:11.5px}
  .bl-spark{height:24px}
  .bl-card--pad{padding:12px 13px}
  .bl-card__h{padding:12px 14px}
  .bl-card__h .bl-eyebrow{display:none}
  .bl-brief{flex-direction:column;align-items:flex-start;gap:10px;padding:14px}
  .bl-brief__acts{display:none}
  .bl-rank{grid-template-columns:22px 1fr;gap:10px}
  .bl-rank__eff{grid-column:2;text-align:left}
  .bl-lane{gap:8px}
  .bl-lane__key{width:64px;font-size:8px;letter-spacing:.03em}
  .bl-sg{font-size:8.5px;padding:0 5px}
  .bl-drawer{top:auto;left:0;right:0;bottom:0;width:auto;border-radius:20px 20px 0 0;height:88dvh;
    transform:translateY(calc(100% + 16px))}
  .bl-chart svg{height:170px}
  .bl-hide-sm{display:none!important}
  .bl-only-sm{display:grid}
  .bl-only-md{display:none}   /* hier traegt das Ueberlauf-Sheet den Umschalter */
  /* Tabellen werden zu Karten */
  .bl-table--stack thead{display:none}
  .bl-table--stack tr{display:block;border:1px solid var(--line);border-radius:var(--r-md);margin-bottom:8px;padding:10px 12px}
  .bl-table--stack td{display:flex;border:0;padding:4px 0;justify-content:space-between}
  .bl-table--stack td::before{content:attr(data-th);font-family:var(--f-mono);font-size:10px;
    letter-spacing:.1em;text-transform:uppercase;color:var(--mute)}
}

/* ---------- 18 · Bewegung aus ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  .bl-rise,.bl-fade,.bl-mk{opacity:1!important;transform:none!important}
  .bl-draw,.arc{stroke-dashoffset:0!important}
  .bl-growx{transform:none!important}
}

/* ---------- 19 · Druck (Berichte) ---------- */
@media print{
  .bl-rail,.bl-top,.bl-drawer,.bl-scrim,.bl-modal{display:none!important}
  [data-bl-ui="v2"] body{background:#fff;color:#000}
  .bl-card{break-inside:avoid;box-shadow:none;border:1px solid #ccc}
  .bl-app{padding:0}
}

/* ─── Tailwind-Kompat: navy/white-Utilities im DUNKELMODUS ────────────
   Befund aus PR #228: Acht kundensichtbare Seiten waren dunkel nicht
   lesbar — "Kontoauszüge" stand als rgb(10,16,40) auf rgb(8,11,20),
   Kontrast 1,05:1. Gemessen mit scripts/check-kontrast.py.

   URSACHE, EINE EINZIGE: Diese Seiten sind nie auf das Token-System
   umgestellt worden und schreiben Tailwind-Utilities direkt ins Markup —
   text-navy-800, bg-white, border-navy-200. Die Werte stehen fest im
   Build und wissen nichts von data-theme. Im hellen Modus stimmen sie,
   im dunklen bleiben sie dunkel.

   Umfang: 362× text-navy-*, 73× border-navy-*, 31× bg-white in
   templates/dashboard/. Die drei umgebauten Seiten (Übersicht,
   Liquidität, Maßnahmen) enthalten davon EXAKT NULL — sie können von
   diesem Block also nicht betroffen sein. Belegt in
   docs/dunkelmodus-schnitt.md.

   WARUM HIER UND NICHT IM MARKUP: 466 Fundstellen von Hand auf Tokens
   umzuschreiben wäre 466 Gelegenheiten für einen Tippfehler, ohne dass
   ein Wächter die Vollständigkeit prüfen könnte. Der Shim behebt alle
   auf einmal und hebt sich auf, sobald eine Seite echt umgebaut wird —
   dann stehen die Utilities dort nicht mehr.

   WARUM IN DIESER DATEI: templates/base.html laedt tailwind.build.css
   und belaro-os.css — NICHT belaro.css. Letztere gehoert den
   oeffentlichen Seiten. Der erste Anlauf legte den Block dort ab; er
   war syntaktisch einwandfrei, wurde auf dem Dashboard aber nie
   geladen, und die Messung aenderte sich um keinen einzigen Wert.
   Aufgefallen ist es nur, weil der Waechter danach erneut lief.

   Reihenfolge stimmt hier zusaetzlich: belaro-os.css kommt NACH
   tailwind.build.css.

   NICHT ANGEFASST: report_pdf.html, report_bank_pdf.html und
   yearly_recap.html. Das sind DRUCKANSICHTEN — ein PDF kennt kein
   data-theme, dort sind feste Werte richtig. Der erste Durchlauf hat
   sie mitersetzt und den Jahresrueckblick von 1 auf 18 Verstoesse
   verschlechtert; der Waechter hat es beim naechsten Lauf gemeldet.
   check-farben.py nimmt Druckvorlagen aus demselben Grund aus.

   Nur unter [data-theme="dark"]. Der helle Modus bleibt unangetastet.
   Ausschliesslich Tokens, kein fester Farbwert. */

[data-theme="dark"] .text-navy-800,
[data-theme="dark"] .text-navy-700 { color: var(--text); }
[data-theme="dark"] .text-navy-600 { color: rgba(237,239,244,.78); }
[data-theme="dark"] .text-navy-500 { color: var(--mute); }
/* text-navy-400 auf --mute (nicht --mute-2): Der schwaechere Ton hat
   auf der Kartenflaeche nur 3,7:1 und faellt damit unter die
   AA-Schwelle fuer kleine Schrift. --mute-2 bleibt als Gestaltungston
   richtig — hier geht es um Fliesstext und Tabellenzahlen. */
[data-theme="dark"] .text-navy-400,
[data-theme="dark"] .text-navy-300 { color: var(--mute); }

/* ── DIE SPIEGELUNG: Gold als SCHRIFT im HELLMODUS ──────────────────
   Der Block oben repariert dunkle Tailwind-Toene im Dunkelmodus. Dies
   hier ist derselbe Fall in die andere Richtung, und er ist genauso
   lange unbemerkt geblieben: `text-gold-500` (#AA8A41) erreicht auf
   Weiss 3,27:1 und auf Creme 2,89:1 — unter der Schwelle, im
   HELLMODUS, also in dem Modus, den die Mehrheit im Geschaeftsumfeld
   benutzt.

   Gemessen am 15.08.2026 auf Kundenseiten: „öffnen →" (Forecast),
   „DETAILS →" (Kontoauszuege), „— CHAT NICHT AKTIV" (Assistent),
   „— OPTIONAL · WERTE AUTOMATISCH ZIEHEN" und „OP-Listen" (Snapshot
   hochladen), „2,2 M" und „29 k" (Massnahme · Detail).

   Ein Shim statt 45 Einzelaenderungen: Die Klasse bleibt, ihre
   Bedeutung wird an `--gold-ink` gebunden — im Hellen #7F631C
   (5,67:1), im Dunkeln der Markenton. CLAUDE.md laesst lokale
   Tailwind-Kompat-Shims genau dafuer zu.

   NUR unter [data-theme="light"]. Im Dunkelmodus traegt gold-500
   ohnehin, und #7F631C waere dort der Fehler, den dieser Shim behebt —
   dieselbe Umkehrung, die schon bei `auth/_auth_base.html` passiert
   ist. */
/* `text-navy-300` (#7C8AB7) traegt im HELLMODUS nur 3,40:1 auf Weiss
   und 3,01:1 auf Creme. Der Dunkelmodus hat dafuer seit Wochen einen
   Shim (weiter unten, .text-navy-300 -> --mute); sein helles
   Gegenstueck fehlte — dieselbe fehlende Spiegelung wie bei
   `text-gold-500`, und deshalb hier direkt daneben.

   Vier kundensichtbare Vorlagen benutzen die Klasse: die
   Snapshot-Felder, die Berichte (zweimal), die Einstellungen. Dazu
   demo.html. `--mute` liegt bei 4,78:1 und traegt dieselbe Rolle:
   Nebenangabe, nicht Fliesstext.

   ⚠️ NICHT GEBAUT, ABER GEMESSEN: `text-green-600` (#16A34A) traegt im
   Hellmodus 3,30:1 und hat im Dunkelmodus ebenfalls einen Shim ohne
   Gegenstueck. Sie kommt heute in NULL kundensichtbaren Vorlagen vor —
   wer sie das naechste Mal einsetzt, erzeugt einen Befund. Dann gehoert
   sie in diese Zeile. `text-green-700` (5,02:1) traegt. */
[data-theme="light"] .text-navy-300 { color: var(--mute); }

[data-theme="light"] .text-gold-500,
[data-theme="light"] .text-gold-600,
[data-theme="light"] .hover\:text-gold-500:hover,
[data-theme="light"] .hover\:text-gold-600:hover { color: var(--gold-ink); }

/* `text-red-600` (#DC2626) traegt auf Creme nur 4,27:1 — gemessen an
   „Forecast löschen" und „AUSZUG LÖSCHEN", beides Knoepfe, die eine
   unwiderrufliche Handlung ankuendigen. `--bad` liegt im Hellmodus bei
   5,13:1 auf Creme und ist derselbe Gedanke in Token-Form. */
[data-theme="light"] .text-red-600,
[data-theme="light"] .hover\:text-red-700:hover { color: var(--bad); }

/* AUSNAHME zur Ausnahme: auf goldenem Grund ist gold-500 als Schrift
   ohnehin falsch — dort gilt --on-gold.
   BIS 24.08.2026 STAND HIER `--on-accent`, UND DAS WAR FALSCH.
   `--on-accent` ist im Hellmodus WEISS; auf `--gold` (#A87F24) sind
   das 3,67:1. Der Fehler war latent — kein Element im Bestand traf
   die Regel, also hat ihn nie jemand gesehen. Gemeldet in #326,
   behoben hier. `--on-gold` ist in beiden Modi Navy und traegt
   8,57:1 dunkel / 8,29:1 hell. */
[data-theme="light"] .bg-gold-300 .text-gold-500,
[data-theme="light"] .bg-gold-400 .text-gold-500,
[data-theme="light"] .bg-gold-500 .text-gold-500 { color: var(--on-gold); }

/* AUSNAHME: Auf goldenem Grund ist DUNKLE Schrift richtig. Der Block
   oben hat die Knoepfe mit aufgehellt — hell auf Gold sind 2,09:1.
   Dafuer gibt es --on-accent, genau fuer diesen Fall. */
[data-theme="dark"] .bg-gold-300.text-navy-800,
[data-theme="dark"] .bg-gold-400.text-navy-800,
[data-theme="dark"] .bg-gold-500.text-navy-800,
[data-theme="dark"] .bg-gold-300 .text-navy-800,
[data-theme="dark"] .bg-gold-400 .text-navy-800,
[data-theme="dark"] .bg-gold-500 .text-navy-800 { color: var(--on-accent); }

/* Flächen: eine weisse Karte auf dunklem Grund ist der zweite Teil des
   Befunds — dort stand heller Text auf Weiss (1,15:1 in der
   Team-Tabelle). Karte auf Oberflächen-Token, Ränder auf Linien-Token. */
[data-theme="dark"] .bg-white      { background-color: var(--surface); }
[data-theme="dark"] .bg-navy-50,
[data-theme="dark"] .bg-navy-100   { background-color: var(--surface-2); }
[data-theme="dark"] .border-navy-100,
[data-theme="dark"] .border-navy-200 { border-color: var(--line); }
[data-theme="dark"] .border-navy-300,
[data-theme="dark"] .border-navy-800 { border-color: var(--line-2); }

/* Tabellenkoepfe und Zebrastreifen der alten Seiten. */
[data-theme="dark"] thead.bg-navy-50 th,
[data-theme="dark"] .bg-navy-50 th { color: var(--mute); }

/* Eingabefelder: hell gerahmt auf hellem Grund, sonst unsichtbar. */
[data-theme="dark"] input.bg-white,
[data-theme="dark"] select.bg-white,
[data-theme="dark"] textarea.bg-white { background-color: var(--surface-2); color: var(--text); }

/* Statusfarben und Tint-Flaechen der Alt-Seiten. Dieselbe Ursache wie
   oben, nur andere Tailwind-Familie: feste Werte, die im Dunkeln nicht
   mehr tragen. text-gold-600 ist ein dunkles Gold (3,9:1), text-red-600
   ein dunkles Rot (3,7:1) — beide unter der AA-Schwelle. Die Tokens
   --gold und --bad sind fuer den dunklen Grund gemacht. */
[data-theme="dark"] .text-gold-600,
[data-theme="dark"] .text-gold-700 { color: var(--gold); }
[data-theme="dark"] .text-red-600,
[data-theme="dark"] .text-red-700  { color: var(--bad); }
[data-theme="dark"] .text-green-600,
[data-theme="dark"] .text-green-700,
/* `text-emerald-700` (#047857) fehlte hier. Auf --surface im Dunkeln
   3,26:1 — gefunden am 24.08.2026, als der Waechter blockierend wurde
   und die CI gegen einen Datenbestand lief, in dem Admin·Fallstudien
   ueberhaupt Datensaetze hatte (23 Elemente statt 5). Eine Farbklasse
   ohne Shim faellt nicht auf, solange die Seite leer ist. */
[data-theme="dark"] .text-emerald-700 { color: var(--ok); }

/* Tint-Flaechen: helle Hinweisbloecke mit jetzt hellem Text darin. */
[data-theme="dark"] .bg-gold-50  { background-color: var(--gold-dim); }
[data-theme="dark"] .bg-red-50   { background-color: rgba(214,92,80,.12); }
[data-theme="dark"] .bg-green-50 { background-color: rgba(62,169,123,.12); }
[data-theme="dark"] .bg-blue-50  { background-color: rgba(78,134,217,.12); }

/* Die 100er-Tints tragen Status-Etiketten (bg-green-100 text-green-700).
   Ohne sie steht heller Statustext auf hellem Tint — 2,67:1. */
[data-theme="dark"] .bg-green-100 { background-color: rgba(62,169,123,.16); }
[data-theme="dark"] .bg-red-100   { background-color: rgba(214,92,80,.16); }
[data-theme="dark"] .bg-gold-100  { background-color: rgba(212,169,74,.16); }
[data-theme="dark"] .bg-blue-100  { background-color: rgba(78,134,217,.16); }

/* Seiteneigene Status-Pillen (.pill) der Alt-Seiten. */
[data-theme="dark"] .pill-active { color: var(--ok); }

/* ══════════════════════════════════════════════════════════════════════
   FORMULARFELD — EINE DEFINITION STATT SIEBEN

   Bis 22.08.2026 stand `.field input/select/textarea` in SIEBEN
   Vorlagen, jede mit eigenem <style>-Block:

     auth/_auth_base · onboarding/_wizard_base · dashboard/settings ·
     dashboard/monthly_update · workbench/new · workbench/detail ·
     admin/activities/form

   Sie waren nicht gleich. Gemessen: zweimal `#C8A24C` als feste
   Fokusfarbe gegen zweimal `var(--gold)`, drei verschiedene
   Polsterungen — und die Platzhalter-Regel gab es in ZWEI von vier
   kundensichtbaren Definitionen. Ein Kunde sah denselben Feldtyp je
   nach Seite anders, und auf zwei Seiten war der Platzhalter im
   Hellmodus unlesbar (B2 aus Datenmodell-30).

   WARUM HIER UND NICHT IM ZENTRALEN STYLESHEET.
   Das zentrale belaro-system.css faerbt Platzhalter bereits — aber
   nur fuer `.input` und `.textarea`, also klassengebunden. Gemessen:
   140 Eingabefelder in kundensichtbaren Vorlagen, davon 8 mit dieser
   Klasse. Die uebrigen 132 erben nichts.

   Die Felder auf `.input` umzustellen waere der andere Weg — er
   aendert 132 Markup-Stellen. Diese Definition aendert eine. Und sie
   liegt LOKAL: `belaro-os.css` laden alle fuenf Basisvorlagen, keine
   andere Property ist betroffen.

   DIE UNTERSCHIEDE, DIE BLEIBEN, SIND JETZT BENANNT.
   Die dichten Raster (Einstellungen, Monats-Update) hatten engere
   Polsterung, das Monats-Update ausserdem Ziffernschrift. Beides ist
   Absicht und heisst jetzt so — statt aus einer zweiten Definition zu
   folgen, die zufaellig anders aussieht.
   ══════════════════════════════════════════════════════════════════ */

.field label {
  display: block;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--mute);
  margin-bottom: .35rem;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--text);
  padding: .75rem .9rem;
  font-family: var(--f-body, 'Hanken Grotesk', sans-serif);
  transition: border-color .15s ease;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--gold);
}

/* PLATZHALTER — DIE STELLE, DIE ZWEI VON VIER VORLAGEN FEHLTE.
   Sie war der Befund B2 aus Datenmodell-30, und sie stand hier ab
   #319 als EINE Regel statt sieben.

   ══ 22.08.2026: DIE EINE REGEL WAR SELBST UNTER DER SCHWELLE ══
   Hier stand `color: var(--mute); opacity: .7`. Beides ist
   durchsichtig, und beides multipliziert sich:

       --mute dunkel  rgba(237,239,244,.58) × .7  =  41 %
       --mute hell    rgba(14, 21, 38,.60)  × .7  =  42 %

   Gemessen mit dem erweiterten check-kontrast.py (Paket 3, das den
   Platzhalter ueberhaupt erst sehen kann):

       dunkel  3,55:1   hell  2,72:1     Soll 4,5:1

   Die Korrektur von #319 hat den Ton vereinheitlicht und seinen Wert
   nicht gemessen — sie konnte es nicht, der Waechter war blind. Das
   ist die Reihenfolge, die hier zaehlt: erst sehen koennen, dann
   beheben.

   ══ WARUM NICHT EINFACH `opacity` WEG ══
   `--mute` IST `--text` bei 58 % / 60 % — dieselbe Farbe, weniger
   Deckkraft. Ohne den zweiten Schleier bliebe also `--mute` pur, und
   das sind gemessen 4,74:1 im Hellmodus. Ueber der Schwelle, aber um
   0,24 — ein Wert auf der Schwelle ist keine Loesung, sondern der
   naechste Befund. `--mute` ist als schwaechster noch zulaessiger
   Fliesstext gebaut (4,78:1 auf Weiss, siehe Abschnitt 1); ein
   Platzhalter, der genau dort liegt, hat keinen Abstand mehr.

   ══ WAS JETZT DASTEHT ══
   EINE Durchsichtigkeit statt zwei, und sie steht sichtbar da:
   `--text` ist der volle Ton, `opacity` macht ihn zum Platzhalter.

   Gemessen am 22.08.2026 an `/register`, `.field input[placeholder]`,
   gegen den Feldgrund (`--surface`):

                       Platzhalter   eingegebener Text   Abstand
       dunkel             8,06:1          15,54:1         7,48
       hell               6,80:1          18,20:1        11,40

   Der Platzhalter bleibt also deutlich schwaecher als das, was der
   Kunde tippt — und trotzdem klar ueber der Schwelle. Beides war
   verlangt: unterscheidbar UND lesbar.

   KEIN NEUES TOKEN. Ein eigenes `--placeholder` waere der andere Weg
   und ist bewusst NICHT gegangen: Es gaebe einen dritten Grauton
   neben `--mute` und `--mute-2`, den niemand bestellt hat. Wenn das
   Design-System ihn eines Tages will, ersetzt er hier zwei Zeilen.

   Das zentrale belaro-system.css faerbt `.input::placeholder` mit
   `--mute-2` — noch schwaecher. Es wird von base.html nicht geladen
   und trifft hier nichts; wo es geladen wird (public/auth/onboarding),
   tragen die Felder `.field`, nicht `.input`. Als Befund benannt,
   nicht angefasst — es ist ein anderes Repository. */
/* SEIT 24.08.2026 GILT DIE REGEL FUER JEDES FELD, NICHT NUR FUER
   `.field`.

   Die Regel oben stand von #323 bis Paket 13 an `.field` — und ein
   Feld, das keine `.field`-Huelle hatte, bekam sie nicht. Das waren
   neun Felder auf sechs Seiten, jedes mit dem Browser-Vorgabewert
   `#9CA3AF` auf Weiss: 2,54:1 in BEIDEN Modi. Die Huelle ist ein
   Gestaltungsdetail; der Kontrast eines Platzhalters haengt nicht
   davon ab, wie sein Kasten heisst.

   Der Selektor ist bewusst ein ELEMENT-Selektor (0,0,1) und keine
   Klasse: Er soll von jeder gezielteren Regel geschlagen werden
   koennen, aber ueberall greifen, wo nichts anderes dasteht.
   `admin/settings.html` hatte dafuer eine eigene Kopie an `.row` —
   die ist mit dieser Zeile ueberfluessig geworden und geloescht. */
input::placeholder,
textarea::placeholder {
  color: var(--text);
  opacity: .7;
}

/* ── DIE GRUNDREGEL FUER JEDES FELD ──────────────────────────────────
   `:where()` hat SPEZIFITAET NULL. Jede gezieltere Regel — `.field
   input`, `.bl-input`, eine Tailwind-Utility — schlaegt sie. Sie ist
   der Boden, nicht die Ansage.

   NACHGETRAGEN AM 24.08.2026, weil Paket 13 zu kurz gegriffen hat.
   Dort bekamen NEUN namentlich gefundene Felder `.bl-eingabe`. Die
   Platzhalter-Regel darueber gilt aber fuer ALLE Felder — und auf
   einem Feld, das weiterhin eine weisse Insel ist, macht sie es
   schlechter statt besser: `--text` ist im Dunkeln fast-weiss.

   Aufgefallen ist es NICHT lokal, sondern in der CI, im selben Lauf,
   in dem dieser Waechter blockierend wurde. Der Grund fuer den
   Unterschied ist der Datenbestand: in der CI laeuft `pytest` vorher
   und legt Datensaetze an, durch die Felder ueberhaupt erst rendern.
   Lokal hatte /dashboard/chat 5 messbare Elemente, in der CI 12.

       Assistent          textarea „Frag etwas …"      1,10:1
       Massnahme · Detail input „z. B. 12000"          1,10:1
       Massnahme · Detail textarea                     1,15:1
       jeweils rgb(237,239,244) auf rgb(255,255,255)

   Die Lehre steht in docs/waechter.md: neun namentlich gefundene
   Stellen sind neun Stellen, nicht die Menge. Deshalb jetzt eine
   Regel fuer die MENGE, und `.bl-eingabe` ist damit nur noch die
   ausdrueckliche Fassung desselben. */
/* KEIN ZEILENUMBRUCH INNERHALB DER :not()-Kette — ein Umbruch ist in
   CSS ein Nachfahren-Kombinator und haette aus dem Selektor etwas
   ganz anderes gemacht. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="submit"]):not([type="button"]), textarea, select) {
  background: var(--surface);
  color: var(--text);
}

/* ── DIE REGEL DARUEBER HAT NIE GEGRIFFEN, 26.08.2026 ────────────────
   `:where()` hat Spezifitaet 0,0,0 — das war Absicht, damit jede
   gezieltere Regel sie schlaegt. Uebersehen wurde dabei, dass
   Tailwinds Preflight selbst eine solche Regel ist:

       button,input,optgroup,select,textarea{color:inherit; …}
       (static/css/tailwind.build.css, Zeile 2)

   Spezifitaet 0,0,1. Sie gewinnt gegen `:where()` — IMMER, egal in
   welcher Reihenfolge die Dateien geladen werden. Das Feld erbt
   seitdem seine Schriftfarbe vom Rumpf, statt sie aus `--text` zu
   nehmen. Die Flaeche kam durch (`background` steht nicht im
   Preflight), die Schrift nicht. Wieder ein getrenntes Paar.

   Auf /demo hiess das im Dunkelmodus 1,05:1 auf vier Feldern.

   DIESE REGEL IST DER GEGENZUG: derselbe Elementselektor, dieselbe
   Spezifitaet 0,0,1 — und sie steht in einer Datei, die NACH
   tailwind.build.css geladen wird (Reihenfolge in allen Basis-
   Vorlagen: tailwind.build -> belaro-os). Bei Gleichstand entscheidet
   die Quelltextreihenfolge, also gewinnt sie.

   CLAUDE.md nennt „Tailwind-Kompat-Shims" als einen der zwei
   erlaubten Gruende fuer eine lokale Regel. Das hier ist genau das.

   `:where()` bleibt stehen: Es traegt weiterhin die Faelle, in denen
   der Preflight nicht greift, und es bleibt der Boden, den jede
   gezieltere Regel schlagen darf. Diese Regel hier ist der Boden
   EINE Stufe hoeher, gerade hoch genug fuer den Preflight.

   DIE `:not()`-KETTE STEHT IN `:where()`, UND ZWAR ABSICHTLICH.
   Ohne die Huelle waere `input:not([type="checkbox"]):not(…)` nicht
   0,0,1, sondern 0,6,1 — jedes Attribut in einem `:not()` zaehlt mit.
   Diese Regel haette dann Fassungen wie `.row input` in
   admin/settings.html (0,2,1) geschlagen, also genau die gezielten
   Regeln, die sie NICHT anfassen soll. `:where()` steuert null bei;
   damit steht hier wirklich 0,0,1, und der Gleichstand mit dem
   Preflight wird ueber die Quelltextreihenfolge entschieden. */
input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="submit"]):not([type="button"])),
textarea,
select {
  background: var(--surface);
  color: var(--text);
}

/* DIE REGEL OBEN ALLEIN MACHT ES SCHLIMMER — nachgemessen, 24.08.2026.

   Neun Felder tragen nur Tailwind-Raender (`border border-navy-200`)
   und sonst nichts: keine Flaeche, keine Schriftfarbe. Sie bleiben in
   BEIDEN Modi weiss mit schwarzer Schrift — helle Inseln. Setzt man
   dort den Platzhalter auf `--text`, ist das im Dunkeln fast-weiss
   auf weiss: der erste Anlauf hat sie von 2,54:1 auf 1,10:1
   GESENKT.

   Der Platzhalter war das Symptom. Der Defekt ist das Feld: Schrift
   folgt dem Thema, Flaeche nicht — dieselbe Bauart wie in Paket 2.
   Behoben wird das Paar, nicht die Schrift. */
.bl-eingabe {
  background: var(--surface);
  color: var(--text);
}

/* AUSWAHLPFEIL: DER DES BROWSERS.

   Vorher zeichnete `onboarding/_wizard_base` einen eigenen Pfeil als
   Daten-URI mit fest eingebautem Goldton (`%23D4A94A`) — eine Farbe
   mitten im Hintergrundbild, die dem Thema nicht folgen kann und die
   kein Farbwaechter sieht (Bilder werden nicht geprueft).

   Ein eigener Pfeil braucht entweder eine feste Farbe oder ein
   Wrapper-Element im Markup. Beides kostet mehr, als es traegt: Der
   Pfeil des Browsers folgt Hell und Dunkel von allein, an allen
   Feldern gleich, ohne eine einzige Farbangabe.

   `appearance` bleibt deshalb unangetastet. Das ist eine sichtbare
   Aenderung an den Auswahlfeldern im Onboarding — und die einzige in
   diesem Umbau. */

/* Dichte Raster.

   `.field--kompakt` steht am Feldkasten (Einstellungen), `.field-grid`
   ist der Rasterbehaelter des Monats-Updates und traegt die Dichte
   fuer alle seine Felder — dort haette ein Modifikator an jedem
   einzelnen Kasten nichts hinzugefuegt, was der Behaelter nicht schon
   sagt. */
.field--kompakt input,
.field--kompakt select,
.field--kompakt textarea,
.field-grid .field input {
  padding: .55rem .7rem;
  font-size: 14px;
}

/* Zahlenfelder: Ziffernschrift, damit Spalten untereinander stehen.
   Im Monats-Update stehen Zahlen in Spalten — mit Proportionalschrift
   springen die Ziffern gegeneinander. */
.field--zahl input,
.field-grid .field input { font-family: var(--f-mono); }

.field-grid .field label { letter-spacing: .14em; margin-bottom: .25rem; }

.field .hint-label { font-size: 11px; color: var(--mute); margin-top: .25rem; }
