  /* ============================================================================================
     core/tokens@1 — DER TOKEN-BLOCK DES KITS. EINE Quelle, alle Traeger (#1614/#1615 Stufe 1).

     WAS HIER LIEGT: jede CSS-Regel, die auf einem `.app`-Selektor `--ctr-*`-Tokens DEKLARIERT —
     der Grundsatz (hell), der dunkle Modus, die vier Schriftstufen, die zwei Dichtestufen und
     die vier Motiv-Regeln. Das ist die Grundgesamtheit, die `design_gate.token_regeln()` liest
     und `G-TokenMonopol` byte-scharf gegen dieses Fragment prueft.

     WARUM ALS FRAGMENT (kit1, 22.08.2026): bis hierher war der Token-Block eine BYTE-KOPIE in
     17 Masken, und `G9` verglich davon genau ZWEI Regeln (`.app{}` hell + dunkel) gegen die
     Referenz-Maske. Die uebrigen neun Regeln — Schriftstufen, Dichte, Motive — trug jede Maske
     ungeprueft selbst. GEMESSEN am Bestand vom 22.08.: `.app[data-zoom="xs"]` stand in 14 Masken
     und fehlte ausgerechnet in der Referenz-Maske, gegen die G9 misst; `galerie_gen.py` hatte den
     Riss bereits umschifft, indem es die Schriftskala aus `plan_kostenstellen.html` statt aus dem
     SSOT zog (Kommentar dort: „die vollstaendige Schriftgroessenskala (A−− ab b7k) traegt Stufe 0
     nicht bzw. nicht mehr aktuell"). Ein Monopol, das nicht byte-scharf geprueft wird, driftet —
     bereits, unbemerkt, im Bestand.

     WAS HIER NICHT LIEGT (bewusst, mit Begruendung):
       * `.app { --ctr-zeilenraster: 26px; }` und die drei Zeilenraster-Regeln der Dichte-/
         Tablet-Achse. Sie liegen im Monopol-Block `core/tablet-haertung@1` und werden dort von
         `G-Tablet` byte-scharf bewacht. Sie hierher zu ziehen wuerde EIN Monopol aufbrechen, um
         ein anderes zu bauen — und pr1/freigaben tragen die Tablet-Haertung nicht.
       * `.app[data-dichte="…"] .panel li` / `… .side-item` (Polster von Navigator und Panel).
         Das sind LAYOUT-Regeln von Z1/Z10, keine Token-Deklarationen; sie unterscheiden sich je
         Maske (2 bzw. 4 bzw. 0 Zeilen) und gehoeren in die Runde, die den Navigator hebt.
       * `.app { width: … }` / `.app.side-hidden` / `.app[data-vp="th"]` (Rahmen-Geometrie des
         Pruefrahmens). Sie deklarieren keinen Token.

     Thomas 22.08.: „Wesentliche Maskenteile muessen im Grundlayout in Zukunft aus der UI-Galerie
     kommen. Agenten setzen dort maskenspezifische Funktionen ein, richten sich aber nach den
     Layoutvorgaben." Der Token-Block ist die unterste Ebene dieser Vorgabe.
     ============================================================================================ */
  .app {
    --ctr-bg: #f6f8f6; --ctr-surface: #ffffff; --ctr-surface-2: #eef3ef; --ctr-tint: #e9f2ec; --ctr-zone: #e1eae4; --ctr-side: #c9d6cf;
    --ctr-ink: #1a2420; --ctr-ink-2: #4c5a53; --ctr-label: #242f2a; --ctr-border: #dde4de;
    --ctr-accent: #1e7a46; --ctr-accent-ink: #ffffff; --ctr-accent-soft: #e3f1e8;
    --ctr-warn: #8a5a0c; --ctr-warn-soft: #f7ecd9; --ctr-crit: #b3362b; --ctr-crit-soft: #f6e2e0;
    --ctr-mark: #ffe28f;
    --ctr-info: #2563a8; --ctr-info-soft: #e2ecf7;
    --ctr-pos: #1e7a46; --ctr-neg: #b3362b;
    --ctr-radius: 8px; --ctr-radius-sm: 6px;
    --ctr-gap-1: 6px; --ctr-gap-2: 10px; --ctr-gap-3: 16px; --ctr-gap-4: 24px;
    --ctr-font: "Segoe UI Variable Text","Segoe UI",system-ui,sans-serif;
    --ctr-fs-0: 11px; --ctr-fs-1: 12.5px; --ctr-fs-2: 14px; --ctr-fs-3: 16px; --ctr-fs-4: 21px; --ctr-fs-kpi: 30px; --ctr-fs-kpi-name: 15px;
    --ctr-shadow: 0 1px 3px rgba(16,32,24,.08);
    /* --- Bedien-Masse (tok1) — motorische Konstanten, NICHT skinbar ------------------------
       Grundeinstellung = EINE Zeile: wer ein Bedien-Mass aendert, aendert es HIER; die Runde tok1
       hat die verstreuten Literale beseitigt, und `design_gate` liest seine Touch-/Icon-/Kompakt-
       Schwellen aus GENAU diesen Werten (G-TokenPflicht) statt aus eigenen Sonden-Literalen.
       Norm-Quelle: #25b »Verbindliche Mindestwerte« — Interaktions-Ziel 32 px Maus / 44 px Touch,
       Icons 15–16 px im Ziel, 16 px inline. WCAG 2.2 AA 2.5.8 verlangt nur 24 px; wir liegen
       bewusst darueber (Fitts). Die Maus-MINDESTgroesse wird in CSS NICHT verwendet — sie ist die
       harte Untergrenze, aus der das Gate seine Desktop-Schwelle liest.
       Sie stehen NUR im hellen Block und haben bewusst KEIN dunkles Gegenstueck: eine Zielgroesse
       ist kein Farbwert, sie darf sich mit dem Modus nicht aendern (#25b Skalierungs-Matrix). */
    --ctr-ziel-touch: 44px; --ctr-ziel-maus: 32px; --ctr-ziel-maus-min: 24px; --ctr-ziel-kompakt: 34px;
    --ctr-icon: 16px; --ctr-icon-btn: 15px; --ctr-icon-sm: 13px;
    --ctr-motion: 170ms;
    /* z-Schichten — Ordnung: Dialog > Melde > Overlay > Panel > FAB > Nav > Inhalt.
       Werte aus dem Ist-Bestand abgeleitet (keine Umnummerierung: jede Fundstelle behaelt ihren
       rechnerischen Wert ueber eine Schicht plus/minus Versatz — die Runde bleibt stapel-neutral).
       Meldung/Toast liegt UEBER Menues und Popovers — die Quittung einer Aktion darf nicht hinter
       dem Menue verschwinden, das sie ausgeloest hat —, aber UNTER dem modalen Dialog: ein Modal
       verlangt Alleinstellung, seine eigene Rueckmeldung erscheint in seinem Rahmen. Die BLENDE
       (Provenienz-Panel, Attrappen-Dialog) ist die modale Nebenform: eigener Abdunkler, ueber den
       Menues, aber unter Meldung und Dialog — sie erklaert etwas zur Maske, sie ersetzt sie nicht.
       Werte unterhalb der Inhalts-Schicht sind KEINE Schicht, sondern lokale Stapelordnung
       innerhalb EINER Flaeche (Tabellen-Sticky-Verbund, Badge-Ring): sie bleiben nackte Zahlen. */
    --ctr-z-inhalt: 6; --ctr-z-nav: 35; --ctr-z-fab: 38; --ctr-z-panel: 39;
    --ctr-z-overlay: 45; --ctr-z-blende: 55; --ctr-z-melde: 60; --ctr-z-dialog: 85;
    /* --- Layout-Deckel der Steuer-Baender + Datendichte (fix2, Content-First) --------------
       Thomas 15.08.: „die screens bestehen fast nur mehr aus steuerelementen nicht mehr aus dem
       eigentlichen Inhalt". Ab hier sind die BANDHOEHEN Tokens statt je Maske getippter Polster:
       die Layout-Wache (design_gate G-Band/G-Inhalt) liest ihre Schwellen aus GENAU diesen
       Zeilen (`layoutmasse()`), nicht aus Sonden-Literalen — dieselbe Kopplung, die tok1 fuer
       die Bedien-Masse gebaut hat. Es sind PRODUKT-Masse: nutzerseitig NICHT verstellbar. Was
       der Anwender waehlt (Dichte, Ansichts-Stufe, Skalierung), steht im Erscheinungsbild-
       Dialog bzw. im Ansicht-Menue und aendert diese Zeilen nicht.
       Der Inhalts-Anteil ist EINHEITENLOS (Prozent-Zahl): ein Verhaeltnis ist kein Mass, eine
       px-Einheit waere hier eine Luege. Zwei Werte, weil das Stufenmodell zwei Zustaende kennt
       (Stufe 0 „Voll" traegt Tabs + Befehle, ab Stufe 1 sind sie weg).
       `--ctr-band-abstand` (fix2_af2 · ldn1) ist der freie ABSTAND UEBER den Band-3-Zielen und
       gehoert zu seinem Deckel: unter dem Deckel liegen die Band-Ziele bei 24 px und bestehen
       `target-size` nur ueber die SPACING-Ausnahme von WCAG 2.5.8 — die verlangt einen freien
       24-px-Kreis um jedes Ziel. Gemessener Kipppunkt 6/7 px (s. steuerband.css), gesetzt sind 8.
       Seit ldn1 wird er so weit wie moeglich INNEN getragen (Kopfluft = Band-Deckel minus
       Zielhoehe) und nur der Rest als Aussenabstand — die Zusage bleibt gleich, ihr Preis an
       Chromhoehe sinkt. Ein PRODUKT-Mass wie die Bandhoehen selbst: dichte-fest, damit die
       Zusage nicht an einer Nutzer-Einstellung haengt.

       fug1 (#1991, 01.09.2026) — DER DECKEL WIRD ENTSCHIEDEN: `--ctr-band-befehle` 28 -> 32.
       HERLEITUNG, und warum das KEINE Chromhoehe kostet: der Deckel traegt ab jetzt die Kopfluft
       UND das Ziel, statt nur das Ziel plus zwei ungenutzte Pixel. Bis fug1 war
           Chrom = Deckel(28) + Aussenabstand(4)   = 32   · Kopfluft innen 28 − 24 = 4
       ab fug1 ist
           Chrom = Deckel(32) + Aussenabstand(0)   = 32   · Kopfluft innen 32 − 24 = 8.
       Gleiche Chromhoehe, gleiche Inhaltsbox (24 px), gleicher Ziel-Abstand (8 px) — aber der
       Abstand liegt vollstaendig INNEN, und zwischen Reiter-Band und Befehlszeile scheint kein
       Pixel Seiten-Hintergrund mehr durch (Thomas 28.08. mit Bildschirmfoto; UI-Spec §2.3).
       WARUM NICHT PER `calc()` AUS DEM ALTEN DECKEL: die Aufteilung `padding = Deckel − Ziel`
       und `margin = Abstand − padding` kuerzt den Deckel algebraisch heraus — er stand als Token
       da und wirkte doch nicht. Ein Deckel, der sich aus seiner eigenen Formel herauskuerzt, ist
       eine getippte Zahl in Token-Verkleidung. Jetzt treibt er wirklich: `--ctr-band-befehle: 36`
       hebt die Bandhoehe auf 36 (Rot-Beweis ii, `probe_bandfuge`).
       ⚠ `--ctr-band-abstand` bleibt bei 8 und ist NICHT abgeleitet: er ist die gemessene
       WCAG-Grenze (Kipppunkt 6/7), der Deckel ist eine Dichte-Entscheidung. Dass beide heute
       dieselbe Zahl ergeben (32 − 24 = 8), ist ein Ergebnis, keine Definition — waere der Abstand
       aus dem Deckel abgeleitet, verschoebe die naechste Dichte-Runde still eine
       Barrierefreiheits-Zusage.

       bl1 (#2279, 12.09.2026) — DIE KNOEPFE BEKOMMEN LUFT: neuer Token `--ctr-band-luft: 4px`.
       BEFUND aus einer Kundendemo am 12.09.: „die buttons in den menuezeilen haben keinen
       abstand zum oberen und unteren rand. das muss aber im ui-kit geaendert werden wenn es
       daraus kommt." GEMESSEN am Stand davor (Desktop 1920, Layout-px): Band 2 traegt
       `padding: 0` und einen 32-px-Tab unter einem 32-px-Deckel — Luft oben 0, unten 0; Band 3
       traegt die ldn1/fug1-Kopfluft ASYMMETRISCH (`padding: 8px … 0`) — Luft oben 8, unten 0.
       Die Knoepfe klebten also in BEIDEN Baendern an mindestens einer Kante.
       AB HIER traegt jedes der beiden Baender `--ctr-band-luft` oben UND unten, und sein Deckel
       ist die Summe aus Zielhoehe und zweimal Luft:
           --ctr-band-tabs    = --ctr-ziel-maus (32) + 2 x 4 = 40
           --ctr-band-befehle = --ctr-ziel-maus-min (24) + 2 x 4 = 32  (Zahl unveraendert,
                                Herleitung neu: vorher 24 + 8 Kopfluft + 0)
       WARUM DIE 8-px-ZUSAGE TROTZDEM STEHT (und `--ctr-band-abstand` unveraendert 8 bleibt):
       sie ist der FREIE ABSTAND ZWISCHEN den Zielen von Band 2 und Band 3 — nicht die Kopfluft
       EINES Bandes. Bis bl1 kam sie vollstaendig aus Band 3 (8 + 0), ab bl1 kommt sie aus beiden
       (4 + 4). GEMESSEN vorher wie nachher: 8,0 px (analyse_guv/plan_kostenstellen/
       plan_verrechnung, Desktop 1920). Die Aufteilung aendert sich, die Zusage nicht — deshalb
       misst `design_gate` G-Bandabstand(a)/G-Fuge(d) sie ab bl1 als SPALT ZWISCHEN den Baendern
       statt als Kopfluft in einem; eine Zusage an einer Kante darf nicht davon abhaengen, welche
       Seite der Kante sie bezahlt.
       ⚠ `--ctr-band-luft` ist ein PRODUKT-Mass wie die Deckel selbst: dichte-fest, nutzerseitig
       nicht verstellbar, bewusst NICHT `--ctr-gap-1` (der folgt der Dichte-Einstellung und fiele
       bei „Kompakt" auf 4, bei „Komfort" auf 8 — die Bandhoehe haenge dann an einer
       Nutzer-Einstellung). Und `--ctr-band-abstand` bleibt NICHT abgeleitet: dass 2 x Luft heute
       genau den Abstand ergibt, ist ein Ergebnis, keine Definition. */
    --ctr-band-kopf: 48px; --ctr-band-tabs: 40px; --ctr-band-befehle: 32px;
    --ctr-band-abstand: 8px; --ctr-band-luft: 4px;
    --ctr-band-mikro: 30px; --ctr-chrom-max: 150px; --ctr-chip-kompakt: 32px;
    --ctr-zeilenraster-kompakt: 24px; --ctr-zeilenraster-komfort: 32px; --ctr-nav-raster: 34px;
    --ctr-inhalt-anteil: 70; --ctr-inhalt-anteil-voll: 55;
  }
  .app[data-app-theme="dunkel"] {
    --ctr-bg: #101613; --ctr-surface: #18201b; --ctr-surface-2: #1e2822; --ctr-tint: #1f2a23; --ctr-zone: #0e1511; --ctr-side: #172019;
    --ctr-ink: #e6ece8; --ctr-ink-2: #98a79f; --ctr-label: #d6ded9; --ctr-border: #2a332d;
    --ctr-accent: #4cc98a; --ctr-accent-ink: #0c1410; --ctr-accent-soft: #1d3527;
    --ctr-warn: #d99b3e; --ctr-warn-soft: #33290f; --ctr-crit: #e06a5e; --ctr-crit-soft: #381b17;
    --ctr-mark: #6b5a1e;
    --ctr-info: #6aa5dd; --ctr-info-soft: #16283c;
    --ctr-pos: #4cc98a; --ctr-neg: #e06a5e;
    --ctr-shadow: 0 1px 3px rgba(0,0,0,.4);
  }

  /* Schriftgröße (Barrierefreiheit) + Dichte (mehr sehen) — Usermenü „Erscheinungsbild" */
  .app[data-zoom="xs"] { --ctr-fs-0: 9.5px; --ctr-fs-1: 10.5px; --ctr-fs-2: 11.5px; --ctr-fs-3: 13px; --ctr-fs-4: 17px; --ctr-fs-kpi: 22px; --ctr-fs-kpi-name: 12px; }
  .app[data-zoom="s"]  { --ctr-fs-0: 10px; --ctr-fs-1: 11.5px; --ctr-fs-2: 12.5px; --ctr-fs-3: 14px; --ctr-fs-4: 19px; --ctr-fs-kpi: 26px; --ctr-fs-kpi-name: 13px; }
  .app[data-zoom="l"]  { --ctr-fs-0: 12.5px; --ctr-fs-1: 14px; --ctr-fs-2: 16px; --ctr-fs-3: 18px; --ctr-fs-4: 24px; --ctr-fs-kpi: 34px; --ctr-fs-kpi-name: 17px; }
  .app[data-zoom="xl"] { --ctr-fs-0: 14px; --ctr-fs-1: 16px; --ctr-fs-2: 18px; --ctr-fs-3: 20.5px; --ctr-fs-4: 27px; --ctr-fs-kpi: 38px; --ctr-fs-kpi-name: 19px; }
  .app[data-dichte="kompakt"] { --ctr-gap-1: 4px; --ctr-gap-2: 7px; --ctr-gap-3: 11px; --ctr-gap-4: 16px; }
  .app[data-dichte="komfort"] { --ctr-gap-1: 8px; --ctr-gap-2: 13px; --ctr-gap-3: 20px; --ctr-gap-4: 30px; }

  /* Motive (Farbpaletten) — wählbar über Usermenü „Erscheinungsbild" */
  /* IBCS-Regel (Fix 15.07.): Motive ändern NUR den Akzent — die Abweichungs-Semantik
     (--ctr-pos/--ctr-neg, ▲ gut / ▼ schlecht) bleibt in JEDEM Motiv stabil grün/rot. */
  .app[data-motiv="blau"] { --ctr-accent: #2563a8; --ctr-accent-soft: #e2ecf7; --ctr-accent-ink: #ffffff; }
  .app[data-motiv="blau"][data-app-theme="dunkel"] { --ctr-accent: #6aa5dd; --ctr-accent-soft: #16283c; --ctr-accent-ink: #0b1420; }
  .app[data-motiv="graphit"] { --ctr-accent: #45544e; --ctr-accent-soft: #e5eae7; --ctr-accent-ink: #ffffff; }
  .app[data-motiv="graphit"][data-app-theme="dunkel"] { --ctr-accent: #a2b3ac; --ctr-accent-soft: #263029; --ctr-accent-ink: #0f1512; }
