/* ═══ INTER, SELBST GEHOSTET (17.09.2026) ═══════════════════════════════════
   Bis heute stand Inter als erste Schrift im Stapel, OHNE dass je eine
   Schriftdatei geladen wurde. Wer Inter nicht zufaellig lokal installiert hat,
   sah die Systemschrift -- Segoe UI oder SF Pro. Jede Groessen- und
   Gewichtsentscheidung dieses Designs sass damit auf einer Schrift, die
   niemand gewaehlt hatte.

   Das ist keine Kleinigkeit: Segoe UI und Inter unterscheiden sich in
   x-Hoehe, Laufweite und Ziffernbreite. Eine Tabelle, die in Inter fluchtet,
   fluchtet in Segoe UI nicht zwingend.

   EINE VARIABLE DATEI STATT VIER SCHNITTEN. Gemessen benutzt die Suite vier
   Gewichte: 400 (23 Stellen), 500 (25), 600 (83), 700 (107). Vier statische
   woff2 waeren etwa gleich gross wie die eine variable -- aber vier Anfragen
   statt einer, und eine Luecke, sobald ein fuenftes Gewicht dazukommt.

   KORREKTUR ZUR GROESSE (17.09.2026, nachmittags): oben stand von mir rund
   350 kB. Das war geschaetzt und um das Siebenfache zu hoch. Die Datei, die
   jetzt daliegt, hat 47 kB -- Latin-Subset mit NUR der Gewichtsachse. Die
   grossen Fassungen tragen zusaetzlich die optische Groesse (opsz), eine
   Achse, die diese Suite nirgends benutzt. Gemessen mit fontTools: genau
   eine Achse, wght 100 bis 900, 230 Zeichen.

   font-display: swap, nicht optional. Bei optional zeigt der Browser beim
   ERSTEN Besuch die Systemschrift und laedt Inter erst fuer spaeter -- man
   sieht also genau beim ersten Eindruck die falsche Schrift. swap tauscht,
   sobald die Datei da ist; der Sprung dauert Millisekunden und passiert nur
   einmal, danach liegt sie im Cache.

   Die Datei liegt im Repo: assets/schrift/InterVariable-latin.woff2, 47 kB,
   SIL Open Font License 1.1 (Lizenztext daneben). Herkunft und Pruefweg
   stehen in assets/schrift/LIESMICH.md, geprueft von
   tools/check-schriften.mjs Pruefung 4. */
@font-face {
  font-family: "Inter";
  /* Nur EIN Eintrag. Die frueher uebliche Doppelung mit format("woff2-variations")
     als erstem Eintrag stammt aus der Zeit, als Safari die Variationen sonst
     nicht erkannte; seit Safari 14 ist sie ueberfluessig und zwei Eintraege auf
     dieselbe Datei sind nur eine Stelle mehr, die auseinanderlaufen kann. */
  src: url("/assets/schrift/InterVariable-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  /* GEMESSEN an der Datei, nicht geschaetzt (17.09.2026). Der Bereich stammt
     woertlich aus dem Paket, das die Datei liefert -- er beschreibt genau die
     230 Zeichen, die drin sind.

     Mein erster Entwurf nannte hier zusaetzlich U+0100-017F (Latin
     Extended-A). Die Datei enthaelt davon NICHTS. Eine zu weit gefasste
     Angabe ist kein harmloser Ueberschuss: der Browser laedt die Datei dann
     auch fuer ein "ő", findet es nicht und faellt fuer dieses eine Zeichen
     doch zurueck -- also ein Abruf ohne Gegenwert und ein Zeichen, das aus
     der Reihe faellt.

     Geprueft, dass alles Gebrauchte drin ist: ae oe ue ss, Euro, die
     deutschen Anfuehrungszeichen, Mittelpunkt, Geviertstrich, Minus und der
     Chevron aus der Kopfleiste. */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}


/* ═══════════════════════════════════════════════════════════════════════════
   NestAnalysisSuite — geteilte Design-Tokens
   ═══════════════════════════════════════════════════════════════════════════

   EINZIGE geteilte CSS-Datei der Suite. Enthält bewusst NUR Grundwerte
   (Farben, Radien, Schatten, Abstände, Typo-Skala) — KEINE Komponenten-
   Regeln wie .master-frame, .canvas-frame, Buttons oder Tabellen.

   WARUM diese Trennung:
   Die drei Apps (EstateNest, DepotCashNest, InOutNest) sind eigenständige
   Repos mit eigenem styles.css. Ein früherer Versuch, auch Komponenten zu
   teilen, führte zum ".canvas-frame-Bug": eine Änderung in einer App hat
   unbemerkt die anderen beiden zerschossen. Komponenten bleiben deshalb
   dupliziert. Die Drift, die dadurch entsteht, betrifft aber fast immer nur
   die Grundwerte (Farbe X hier .05, dort .045; Radius hier 24, dort 26) —
   und genau die stehen jetzt hier, an einer Stelle.

   EINBINDEN (vor dem eigenen styles.css):
     <link rel="stylesheet" href="../shared/tokens.css" />
     <link rel="stylesheet" href="css/tokens.css" />     <- App-Overrides
     <link rel="stylesheet" href="css/styles.css" />

   App-spezifische Abweichungen gehören in das jeweilige css/tokens.css und
   überschreiben von dort die Werte hier. Diese Datei nie appspezifisch
   verbiegen — sonst ist der Sinn weg.

   Stand: 26.07.2026
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ DIE BASIS  (25.08.2026) ═══════════════════════════════════════════════
   1rem = 13px, nicht die 16px des Browsers.

   Übernommen aus src/components/nest/Shell.tsx des Vorbilds, wo der äußerste
   Container `text-[13px]` trägt und jede weitere Größe davon abgeleitet ist.

   WARUM DAS DER WICHTIGSTE WERT ÜBERHAUPT IST
   Er wirkt auf ALLES, was in rem angegeben ist — jede Schriftgröße, jeden
   Abstand, jedes Label, auf allen elf Seiten. Bis heute standen wir auf 16px
   und haben an Radien, Schatten und Fettgraden gedreht; jede dieser
   Änderungen war für sich richtig und hat nichts gebracht, weil die
   Grundlage um Faktor 1,23 daneben lag.

   Feste Pixelwerte (Innenabstände der Karten, Balkenhöhe, Symbolgrößen)
   schrumpfen NICHT mit. Sie werden getrennt nachgezogen — sonst hätte man
   kleine Schrift in unveränderten Kästen.

   Am :root und nicht am html-Element: :root ist derselbe Knoten, aber die
   Schreibweise sagt, dass hier die Wurzel des Systems liegt und nicht eine
   HTML-Eigenheit gesetzt wird. */
:root {
  font-size: 13px;

  /* ─── Flächen & Text ────────────────────────────────────────────────────
     --bg     Seitenhintergrund (warmes Cream, alle drei Apps identisch)
     --paper  Kartenfüllung innerhalb der Frames (reinweiß)
     --soft   dezente Füllung für Badges, Icon-Kreise, Toggle-Buttons     */
  /* 26.07.2026 dreimal aufgehellt: #f5f3ee → #fbfaf7 → #fdfdfb → #fefefd.
     Die Frames tragen einen leichten Akzent-Wash — je heller und neutraler die
     Seite dahinter, desto deutlicher heben sie sich ab. Ein Hauch Wärme bleibt
     (B einen Punkt unter R/G), damit es nicht klinisch wirkt. */
  --bg:     #fdfcfa;   /* Seite — --v6-canvas */
  --paper:  #fff;
  --ink:    #171717;
  --ink-rgb: 23, 23, 23;
  --muted:  #6a6a6a;   /* 05.09.2026: 3,97 → 4,60 gegen --zone-boden-b */
  --line:   #e2dbcf;   /* Aussenrahmen — .theme-v6 --v6-line */
  --soft:   #eee9df;
  /* ─── Seitenleiste: WEISS seit 01.09.2026 (MWM) ────────────────────────
     Bis dahin #fbf9f5 — eine minimal waermere Flaeche als die Karten, damit
     die Leiste als Rand erkennbar ist, ohne kraeftige Linie.

     Jetzt reines Weiss. Der Rand entsteht ueber --sidebar-marke-linie
     (seitenmenu.css, border-right), und der reicht: die Leiste steht am
     Bildschirmrand, wo ohnehin niemand sie fuer Inhalt haelt.

     Der Seitenmenue-Balken wird aus diesem Weiss und dem neutralen
     Interface-Petrol abgeleitet; er haengt nicht an der warmen Zone.

     Der Kommentar in estate/css/styles.css (Zeile 328) nennt diesen Token
     noch als Bezugspunkt fuer eine Panel-Flaeche. Er bleibt richtig — dort
     geht es um den Kontrast zu einer ANDEREN Flaeche, nicht um den Farbwert. */
  --sidebar-flaeche: #ffffff;

  /* Die Haarlinie neben den Kapitelmarken der Seitenleiste (MODULE, INHALT,
     PROFIL). GRAU seit 01.09.2026 (MWM: "die ist jetzt so beige, mach die
     ruhig etwas dezenter, die Farbe der Haarlinie verändern in grau").

     EIGENER TOKEN, nicht --karten-linie: die trennt Karten auf beigem Grund
     und ist dort mit #e2dbcf richtig. Die Seitenleiste ist seit heute weiss,
     und auf Weiss wirkt derselbe Ton warm und schwer — er zieht Blick auf
     eine Linie, die nur gliedern soll. Wer --karten-linie umfaerbte, um das
     hier zu beheben, veraenderte jede Karte in vier Modulen mit.

     Palettenfest wie --sidebar-flaeche: die Leiste ist Fensterrahmen, nicht
     Inhalt, und soll beim Palettenwechsel stehen bleiben. */
  --sidebar-marke-linie: #e9e9e9;

  /* ─── Scrollbalken (17.09.2026) ────────────────────────────────────────
     Der feste neutrale Petrol-Anker wird mit dem jeweiligen Untergrund
     gemischt. Im hellen POSTER nennt palette.js dieselben Formeln, damit
     alle Paletten dieselben Rollen setzen und der Panel-Balken beim Wechsel
     der Erscheinungs-Presets weiterhin aus --zone-boden-b entsteht.
     POSTER_DUNKEL setzt eigene dunkle Boulder-Stufen. */
  /* Neutrales Interface-Petrol: unabhängig von der gewählten KPI-Farbe.
     Die Daumen werden mit ihrem jeweiligen Untergrund gemischt, nicht mit
     einer Datenserie oder der warmen Übersichts-Zone. */
  --scrollbar-chrome-ton:   #304742;
  --scrollbar-daumen:       color-mix(in srgb, var(--sidebar-flaeche) 80%, var(--scrollbar-chrome-ton));
  --scrollbar-daumen-aktiv: color-mix(in srgb, var(--sidebar-flaeche) 62%, var(--scrollbar-chrome-ton));

  /* Die SEITENLEISTE bekommt einen blasseren Balken (25.08.2026, MWM: "zu
     auffaellig, zu praegnant, braucht kein Mensch dort").
     Der Balken der Seite darf sichtbar sein — dort scrollt man absichtlich.
     In der Leiste ist er ein Nebeneffekt: sie scrollt nur, wenn das Fenster
     kurz ist, und dann soll er nicht mit den Menuepunkten um Aufmerksamkeit
     ringen. Beim Ueberfahren kraeftiger — wer ihn sucht, findet ihn. */
  /* Im Eingabe-Panel leitet sich der Balken vom waehlbaren Modulboden ab. */
  --scrollbar-panel:       color-mix(in srgb, var(--zone-boden-b) 82%, var(--scrollbar-chrome-ton));
  --scrollbar-panel-aktiv: color-mix(in srgb, var(--zone-boden-b) 70%, var(--scrollbar-chrome-ton));

  /* Auf Sidebar-Weiss: heller als der Balken am Fensterrand. */
  --scrollbar-daumen-leiste:       color-mix(in srgb, var(--sidebar-flaeche) 85%, var(--scrollbar-chrome-ton));
  --scrollbar-daumen-leiste-aktiv: color-mix(in srgb, var(--sidebar-flaeche) 70%, var(--scrollbar-chrome-ton));

  /* Immer dunkle Fläche, unabhängig von der aktiven Palette (02.08.2026,
     Rollout dunkle Palette). Ein paar Stellen (primärer Button in
     shared/ui-icons.css, "Überschuss"-Kachel im Hub) benutzten bisher
     var(--ink) als Hintergrund, weil --ink bis dahin IMMER #171717 war --
     ein Zufall, kein Vertrag. Sobald --ink in einer dunklen Palette selbst
     hell wird (siehe shared/palette.js, POSTER_DUNKEL), kippt das: weißer
     Text auf weiß gewordenem "dunklem" Knopf. --flaeche-invers trägt die
     Bedeutung "immer die dunkle Gegenfläche" direkt im Namen und wird
     deshalb bewusst NICHT von einer Palette überschrieben. */
  --flaeche-invers: #171717;

  /* Textfarben AUF --flaeche-invers (03.08.2026, Hardcoding-Audit): dieselbe
     Begründung wie bei --flaeche-invers selbst -- eine Fläche, die immer
     dunkel bleibt, braucht Text, der immer hell bleibt, unabhängig von der
     aktiven Palette. Vorher an drei Stellen als eigenes Literal eingetragen
     (css/styles.css #a3a196/#d8d6cc, estate/css/calculator.css #c8c8c8) --
     drei leicht verschiedene Grautöne für denselben Zweck. Jetzt ein Paar:
     -text für die Hauptzahl/-wert (strong), -text-muted für Label/Nebentext
     (span, small, .hero-label, .hero-copy). */
  --flaeche-invers-text:       #ffffff;
  --flaeche-invers-text-muted: #c8c8c8;
  /* RGB-Tripel dazu, für rgba()-Washes auf/um fest dunkle bzw. fest helle
     Flächen (z.B. der Demo-Banner in shared/seitenmenu.css, ebenfalls
     palettenunabhängig gelb) -- vorher als rgba(23,23,23,X)/rgba(255,255,255,X)
     Literal eingetragen. */
  --flaeche-invers-rgb:      23, 23, 23;
  --flaeche-invers-text-rgb: 255, 255, 255;

  /* ─── Verlauf über dem Seitenhintergrund ────────────────────────────────
     Ein sehr flacher diagonaler Schleier ÜBER --bg (Wunsch 26.07.2026):
     oben links leicht abgetönt, nach unten rechts fast weg. Zweck ist nicht
     Dekoration, sondern Trennung — die Karten sind reinweiß, und auf einem
     gleichmäßig hellen Grund trägt ihre Abgrenzung allein eine Haarlinie.
     Ein Verlauf gibt der Seite eine Tiefe, gegen die sich Weiß überall
     abhebt, ohne dass irgendeine Stelle grau wirkt.

     WARUM EIN TOKEN UND KEINE VIER: der Wert ist die komplette
     linear-gradient()-Zeichenkette. Damit kann jede Palette den Verlauf
     vollständig bestimmen (Richtung, Farbe, Stärke, Anzahl der Stufen), ohne
     dass hier ein Satz Einzelwerte gepflegt werden muss, der zu einer Palette
     passt und zur anderen nicht. shared/palette.js überschreibt ihn.

     WICHTIG bei der Verwendung: NICHT `background:` benutzen — die Kurzform
     setzt background-image mit zurück und löscht den Verlauf still. Immer
     background-color und background-image getrennt setzen.               */
  --bg-verlauf: linear-gradient(155deg,
                  rgba(122, 89, 73, .07) 0%,
                  rgba(122, 89, 73, .035) 45%,
                  rgba(122, 89, 73, .015) 100%);

  /* ─── Semantische Signalfarben ──────────────────────────────────────── */
  --good: #315f4c;   /* positiv: Überschuss, Rendite, Einnahmen           */
  --bad:  #9b3e35;   /* negativ: Defizit, Verlust                        */

  /* ─── EINGEFAERBTE ZAHLEN ─────────────────────────────────────────────
     27.08.2026, MWM: "das Gruen im Text ist kaum als gruen erkennbar, das
     Rot ebenso -- nimm die kraeftigen Farben, die wir in den Grafiken
     benutzen."

     Die Farben stimmten schon ueberein: --good ist Zeichen fuer Zeichen
     dasselbe #315f4c wie farbe("positiv") im Ring. Nur wirkt eine FLAECHE
     anders als eine ZIFFER -- dieselbe Farbe traegt als Tortenstueck und
     verschwindet als 13-px-Zahl fast ins Schwarze. Gemessen:

       --good  #315f4c   Kontrast 7,06   Saettigung 48 %   <- wirkt schwarz
       --bad   #9b3e35   Kontrast 6,47   Saettigung 66 %

     Die Ringfarben direkt zu nehmen geht nicht: das Mint #2EEEB5 kommt als
     Text auf 1,45 -- unlesbar. Gesucht war also nicht "die Grafikfarbe",
     sondern die kraeftigste Fassung, die als Text noch traegt:

       --zahl-positiv #0E7A52  Kontrast 5,17  Saettigung 89 %
       --zahl-negativ #C0392B  Kontrast 5,25  Saettigung 78 %

     Beide ueber 4,5 (WCAG AA fuer Fliesstext), fast doppelt so gesaettigt.
     Sie gelten fuer JEDE eingefaerbte Zahl -- im Text wie im Diagramm.
     --good und --bad bleiben, wo eine FLAECHE eingefaerbt wird.

     ─── NACHTRAG 31.08.2026, MWM ─────────────────────────────────────────
     "nimm im CSS immer das eine Negativ-Rot, was wir in allen Grafiken und
     Charts benutzen."

     Das Chart-Rot ist keine feste Farbe, sondern eine ROLLE: farbe("negativ")
     aus shared/palette.js, die mit der eingestellten Palette wechselt.
     --zahl-negativ haengt jetzt daran. Damit gibt es zu "negativ" genau eine
     Farbe pro Palette -- Balken, Zahl, Tooltip-Punkt und Signalflaeche
     zeigen dasselbe Rot, egal welche Palette laeuft.

     GEMESSEN (Textkontrast auf Papierweiss, WCAG AA = 4,5):
       Palette 1  #9b3e35   6,70   (= --bad, der Rueckfall)
       Palette 2  #C41E1E   5,91
       Palette 3  #E42A2E   4,50   knapp bestanden
       Palette 4  #F5430B   3,69   FAELLT DURCH
     Das alte feste #C0392B lag bei 5,44.

     Palette 4 ist damit der eine Fall, in dem eine rote Zahl unter AA
     rutscht. Das ist eine Eigenschaft JENER Palette, kein Fehler dieser
     Regel -- dieselbe Farbe traegt dort auch als Flaeche schon wenig.

     DAS GRUEN BLEIBT FEST. Derselbe Kniff waere dort unbenutzbar:
       Palette 2  #2EEEB5   1,50   unlesbar
       Palette 3  #43A047   3,30
       Palette 4  #5AC87F   2,10
     Ein helles Mint traegt als Flaeche und verschwindet als Ziffer. */
  --zahl-positiv: #0E7A52;
  --zahl-negativ: var(--serie-negativ, var(--bad));
  --warn: #c9962f;   /* Zwischenstufe: Cashflow-Ampel "warn" (03.08.2026,
                         Hardcoding-Audit -- vorher nur als Fallback-Literal
                         in estate/css/styles.css .cf-ampel-dot.warn, ohne
                         dass --good/--bad ein drittes Gegenstück hatten) */
  --schuld: #c76b3c; /* Restschuld/Zinsanteil/Soll -- stand vorher als eigenes
                         Literal an ca. zehn Stellen in estate/portfolio.html
                         und estate/project.html, immer derselbe Ton, nie
                         benannt (03.08.2026, Hardcoding-Audit). */
  /* RGB-Tripel dazu (03.08.2026, Hardcoding-Audit): für rgba(var(--good-rgb),X)
     statt rgba(49,95,76,X) / rgba(155,62,53,X) -- beide Zahlenpaare standen
     vorher als Literal in inout/css/styles.css und shared/ui-icons.css,
     ohne dass ersichtlich war, dass sie exakt --good/--bad sind. */
  --good-rgb: 49, 95, 76;
  --bad-rgb:  155, 62, 53;

  /* ─── Modul-Akzent ──────────────────────────────────────────────────────
     Seit 26.07.2026 ein einheitliches Orange über alle drei Module — kein
     Modul mehr farblich abgesetzt. Drei Helligkeitsstufen für die Frame-
     Hierarchie (Gesamt / Einnahmen / Ausgaben).

     Farbhistorie InOutNest (nur zur Nachvollziehbarkeit, alle abgelöst):
     Violett #823e98 → Mocha #6e5a47 → Rosé #b06478 → Salbei #6f9678
     → Gold #c7a43d → jetzt dasselbe Orange wie Estate/Depot.            */
  /* 26.07.2026 deutlich ENTSÄTTIGT. Vorher war das ein kräftiges Terrakotta
     (#b0836e, Sättigung ~55 %), das über Frames, Rahmen, Kicker-Badges und
     Hover-Schatten hinweg die ganze Oberfläche orange eingefärbt hat — sie
     wirkte "eingematscht". Jetzt derselbe Farbton, aber auf ~30 % Sättigung
     gezogen: erkennbar warm, aber zurückhaltend genug, dass Zahlen und
     Inhalte vorn stehen statt der Farbe.
     Historie: #b0836e (kräftig) → #b0836e (entsättigt). */
  --accent-dark:      #7a5949;
  --accent-dark-rgb:  122, 89, 73;
  --accent-mid:       #b0836e;
  --accent-mid-rgb:   176, 131, 110;
  /* --accent-light und --accent-light-rgb ENTFERNT am 05.09.2026: null
     Verwendungen. Die dritte Akzentstufe wurde nie gebraucht -- --accent-dark
     traegt die Kanten, --accent-mid die Flaechen. Wer sie zurueckholt,
     braucht einen Ort, an dem sie etwas bedeutet. */

  /* Aktiver Akzent — wird pro Frame/Kontext lokal überschrieben.
     Zeigt auf die mittlere Stufe, statt deren Hexwert ein zweites Mal
     hinzuschreiben (02.09.2026). Es sind zwei Rollen, aber ein Wert: die
     mittlere Stufe ist der Ausgangszustand, den jeder Frame ueberschreiben
     darf. Beide Zeilen hier standen als Literal #b0836e sechs Zeilen unter
     --accent-mid: #b0836e — eine Aenderung an der Stufe haette den
     Ausgangszustand nicht erreicht.
     Innerhalb DERSELBEN Datei ist die var()-Kette unbedenklich; die
     Warnung in depot/css/tokens.css betrifft Ketten ueber Dateigrenzen. */
  --accent:     var(--accent-mid);
  --accent-rgb: var(--accent-mid-rgb);

  /* Hinweis: die großen Karten (master-frame/canvas-frame) rahmen sich über
     rgba(var(--accent-rgb), …) — es gibt bewusst KEIN eigenes Rahmen-Token.
     Ein Versuch damit (dunkles Anthrazit, 26.07.2026) ist wieder raus, weil
     ein Modul sonst optisch aus der Suite ausbricht.                     */

  /* ─── Füllung der Frames ─────────────────────────────────────────────────
     Eine VOLLE Farbe, kein Alphawert (zweite Korrektur 26.07.2026). Ein
     Akzent-Wash auf hellem Grund macht die Karte zwangsläufig DUNKLER als
     die Seite — Karte und Hintergrund liefen dadurch in einen Ton
     zusammen. Als vollwertige Farbe kann die Karte auch HELLER sein als
     der Hintergrund, und genau das trennt sie zuverlässig.
     shared/palette.js überschreibt beide pro Palette.                    */
  --frame-bg-canvas: rgba(var(--accent-rgb), .06);

  /* ─── Zonen-Böden (Board-Untergrund, ab 01.08.2026) ───────────────────────
     Zusätzlich zu den Frame-Füllungen oben: eine deckende Flächenfarbe für
     die Gesamtvermögen-Zone auf dem Hub. Die einzelnen Elemente darin
     bleiben freistehende weiße Karten mit Schatten statt gerahmter Kacheln
     mit Akzent-Oberkante — der Farbboden ersetzt den Rahmen als Signal für
     Zugehörigkeit.
     --zone-boden-a ist ein FLATER Wert (kein Alpha-Mix über --accent-rgb
     mehr) -- 1:1 aus dem Referenz-Mockup asset-nest-clean-v3-board.html
     übernommen. Ein Alpha-Mix über --accent-dark-rgb (122,89,73) kam dem
     Zielton nahe, aber nicht nah genug (Martin, 01.08.2026, im direkten
     Vergleich noch sichtbar blasser/kühler als das Mockup) -- der flate
     Wert trifft ihn exakt, verliert dafür die Kopplung an --accent-rgb
     (zieht also NICHT mehr automatisch mit einer Paletten-Änderung um).
     --zone-boden-b (Modul-Zone) ist das kuehle Blaugrau, das die Zone
     seit dem Referenz-Mockup hatte. War als rgba(92,114,144,.13) ein
     Alpha-Mix UEBER dem Seitenhintergrund -- auf dem alten, leicht
     getoenten --bg (#FBFCFE + Verlauf) ergab das ~#e9edf1 und war als
     eigene Flaeche erkennbar. Seit --bg auf reines #FFFFFF steht (Wunsch
     Martin 01.08.2026), blendete derselbe Alpha-Wert zu #eaedf1 auf
     WEISS -- rechnerisch fast derselbe Ton, aber ohne jeden Kontrast zur
     jetzt ebenfalls weissen Seite dahinter: zwei Flaechen, die identisch
     aussahen, obwohl sie es nicht sein sollen (Fund Martin 01.08.2026,
     "das ist wieder weiss").
     GLEICHER FEHLER WIE BEI --zone-boden-a, DIESELBE LOESUNG: ein
     Alpha-Mix ist von Natur aus vom Grund darunter abhaengig -- aendert
     sich der Grund, aendert sich unbeabsichtigt auch die Zone. Deshalb
     jetzt FLAT wie --zone-boden-a: exakt der Zielton #e9edf1, unabhaengig
     vom Seitenhintergrund. Zwei benannte, feste Werte statt einem Wert,
     der nur zufaellig zum anderen passt. */
  --zone-boden-a: #f4ece4;
  /* ZURUECKGENOMMEN am 26.08.2026, noch am selben Tag.

     Ich hatte diesen Wert entsaettigt, weil Martin sagte "das Blau ist mir
     ein bisschen zu blau" -- und dabei die falsche Flaeche erwischt. Gemeint
     waren die getoenten Felder INNERHALB der Tabellen (Kopfzeile,
     Summenzeile), nicht der Grund der Karten. MWM: "die Karten an sich
     wieder zurueck auf die alte Farbe, nicht die Inhalte der Tabellen".

     Der Unterschied ist wichtig genug fuer diesen Kommentar: --zone-boden-b
     ist die ZONE, auf der die Karten liegen. Sie traegt die Unterscheidung
     warm/kuehl zwischen Gesamtuebersicht und Aufschluesselung und ist seit
     dem 01.08.2026 in allen vier Modulen gleich. Was in einer Tabelle
     getoent ist, haengt dagegen an --tabellen-kopf -- und das bleibt
     entsaettigt. */
  --zone-boden-b: #e9edf1;

  /* ─── Aussenlinien der Zonen (25.08.2026, MWM) ──────────────────────────
     Die Bloecke trugen `border: 1px solid transparent` -- Platz fuer eine
     Linie, aber keine Linie. Sichtbar war nur die Flaeche.

     Der Rahmen ist NIE neutral grau, sondern ein getoenter Verwandter der
     Flaeche, die er umschliesst (Styleguide V6). Deshalb zwei Werte und
     nicht einer: --v6-head-line zum warmen Boden, --v6-module-field-line
     zum kuehlen. Ein Rahmen in der falschen Temperatur sieht aus, als
     gehoere er nicht dazu. */
  --zone-linie-a: #dac9ad;   /* zum warmen --zone-boden-a; 26.08.2026 sechs Prozent dunkler (MWM) */
  --zone-linie-b: #c2d1de;   /* zum kuehlen --zone-boden-b; mit --zone-linie-a nachgezogen */

  /* Struktur-Pillen sitzen auf warmem bzw. kühlem Zonenboden. Ihre Fläche
     ist eine aufgehellte Ableitung dieses Bodens, kein fremdes Weiß. */
  --pille-flaeche-a: color-mix(in srgb, var(--zone-boden-a) 45%, var(--paper));
  --pille-flaeche-b: color-mix(in srgb, var(--zone-boden-b) 45%, var(--paper));

  /* ═══ AUCH DIE GRAUE PILLE BEKOMMT EINE HAARLINIE  (17.09.2026) ═════════
     MWM: "gib den grauen Pillen auch eine dezente Haarlinie, so wie bei den
     farbigen."

     GEMESSEN: die farbigen Pillen tragen eine Kante -- .status-pill steht auf
     --highlight-gelb mit Rand in --highlight-gelb-rand. Die grauen (.brand-
     kicker ohne .thema, .scope-badge) standen ohne. Auf hellem Grund franst
     eine helle Flaeche ohne Kante aus; genau deshalb hatte die gelbe Pille
     ihre bekommen (26.08.2026). Der Grund gilt fuer die graue genauso -- sie
     steht sogar auf noch aehnlicherem Untergrund.

     KEIN --karten-linie: das ist die Kante einer KARTE. Eine Pille ist kein
     Rahmen, ihre Linie darf leiser sein. Deshalb ein eigener Wert aus
     derselben Tinte, nur schwaecher -- so wie --highlight-gelb-rand aus dem
     Gelb kommt und nicht aus der Kartenlinie. */
  /* NACHGESCHAERFT am selben Tag (MWM: "die Haarlinien aus den Pillen
     entfernen oder so einstellen, dass sie kaum noch wahrzunehmen sind").

     Das ist eine Ruecknahme meiner eigenen Umsetzung von heute frueh, und
     sie steht hier, statt den Text darueber zu ersetzen: der Grund fuer die
     Linie gilt weiter -- eine helle Flaeche auf hellem Grund franst ohne
     Kante aus --, nur die STAERKE war falsch gewaehlt. --wash-leicht (.09)
     ist die Stufe fuer "erkennbar getoent"; eine Pillenkante soll aber nicht
     erkannt, sondern nur geahnt werden. --wash-hauch (.04) ist genau dafuer
     da und stand die ganze Zeit eine Zeile darueber.

     Entfernt wird sie NICHT: ohne Kante kippt der Befund von heute frueh
     zurueck, und dann steht in vier Wochen wieder "gib den Pillen eine
     Haarlinie" im Protokoll. Leiser statt weg. */
  --pille-linie: rgba(var(--ink-rgb), var(--wash-hauch));

  /* Tabellenkopf und Summenzeile (25.08.2026, zweite Fassung nach MWM).
     War #f6f4ef -- der warme Ton des Vorbilds. Er stand aber in einem Block,
     der bei UNS kuehl unterlegt ist (--zone-boden-b), waehrend er im Vorbild
     auf warmem Grund liegt. Derselbe Wert, anderer Zusammenhang, falsches
     Ergebnis: beige Streifen in einer blaugrauen Zone.

     Jetzt ein Blaugrau, heller als der Zonenboden (#e9edf1) und dunkler als
     die Karte (#fff) -- dieselbe Familie, dritte Stufe. Kopf und Summe heben
     sich damit von den Datenzeilen ab, ohne aus dem Block auszubrechen. */
  /* Halbe Staerke (26.08.2026, MWM: "vielleicht nur fuenfzig Prozent von dem,
     was wir jetzt sehen"). Gerechnet als Mischung mit --paper, nicht per
     opacity: eine transparente Kopfzeile haette den Zonenboden durch die
     Tabelle scheinen lassen und je nach Block einen anderen Ton ergeben --
     genau der Fehler, den die zweischichtige Pille im August gekostet hat.
       26.08. frueh   #f2f5f8   (aus dem Vorbild)
       26.08. mittag  #f3f5f7   (entsaettigt)
       26.08. jetzt   #f9fafb   (halbe Staerke gegen Weiss) */
  --tabellen-kopf: #f9fafb;
  /* Flaeche des AUFGEKLAPPTEN Bereichs (26.08.2026, MWM: "macht das mal
     bitte in dem Toggle-Bereich etwas graeulicher").

     Gerechnet, nicht verschoben: derselbe Farbton (210°) und dieselbe
     Helligkeit wie --tabellen-kopf, nur die Saettigung noch einmal halbiert.
     Der Bereich liegt UNTER einer Zeile, die schon auf --tabellen-kopf
     antwortet -- er soll sich absetzen, ohne ein zweites Blau einzufuehren.
       --tabellen-kopf   #f3f5f7   S 15 %
       --tabellen-auf    #f4f5f6   S  7 % */
  /* --tabellen-auf ist am 26.08.2026 in --frame-innen aufgegangen: die
     aufgeklappte Zeile und der Rahmen im Rahmen sind dieselbe Rolle --
     "abgesetzte Flaeche innerhalb einer Karte". Sie hatten #fafafa und
     #fbfbfa, ein Unterschied von einem Punkt, den niemand sieht und den
     beide getrennt weitergepflegt haetten. Aliasing statt Loeschen, damit
     kein Modul bricht, das den alten Namen noch benutzt. */
  --tabellen-auf: var(--frame-innen);

  /* ═══ FRAME IM FRAME (26.08.2026, MWM) ══════════════════════════════════
     Ein abgesetzter Bereich INNERHALB eines Blocks -- die Positionsliste
     unter "Ausgaben", die zwei Sonderausgaben-Bloecke, die Kategorie-Karten.

     Sie trugen drei verschiedene Toene, alle als Alpha-Wash ueber einer
     Farbe, die sich je nach Block aendert:
       .expense-table-frame       rgba(--accent-rgb, .02) + .3  Rahmen
       .sonder-block-invest       rgba(--sonderblock-blau-rgb, .05) + .18
       .sonder-block-immobilien   dasselbe Blau
     Der Wash war das eigentliche Problem: --accent ist in InOut je nach
     Block gold-mid oder gold-light, also ergab derselbe Ausdruck in zwei
     Bloecken zwei Farben. Und das Blau der Sonderbloecke gehoerte zu einer
     Zeit, als sie eine eigene Modulfarbe hatten -- die haben sie seit dem
     26.07.2026 nicht mehr.

     Jetzt ein fester Ton, unabhaengig vom umgebenden Block: knapp ueber
     --paper, damit er sich vom Weiss der Karten absetzt, ohne mit dem
     Zonenboden zu konkurrieren. */
  --frame-innen:        #fbfbfa;
  --frame-innen-linie:  #ece9e3;

  /* ═══ WAS AUF DEN ZEIGER ANTWORTET ══════════════════════════════════════
     (26.08.2026, Messlauf ueber alle vierzehn CSS-Dateien)

     Gemessen: 18 verschiedene Werte fuer "Flaeche beim Ueberfahren", davon
     acht als rohes rgba() -- rgba(--ink-rgb, .04), .045, .05, .06, .1 und
     rgba(--accent-rgb, .07), .45, .5. Fuenf Abstufungen desselben Grau,
     entstanden in fuenf Dateien an fuenf Tagen. Keine davon unterscheidet
     sich sichtbar von ihrer Nachbarin; zusammen ergeben sie eine Oberflaeche,
     die je nach Ort anders reagiert.

     Drei Rollen, drei Tokens -- mehr braucht es nicht:
       --hover-flaeche     Zeile oder Kachel hebt sich beim Ueberfahren
       --hover-flaeche-warn dasselbe fuer Loeschen (rot getoent)
       --fokus-linie       Rahmen eines Feldes mit Tastaturfokus */
  /* ═══ DIE WASCH-LEITER (26.08.2026) ═════════════════════════════════════
     Gemessen: rgba(var(--accent-rgb), X) steht 17× im Repo -- mit ELF
     verschiedenen X: .04 .06 .07 .09 .1 .12 .14 .18 .25 .3 .45.

     Niemand hat elf Stufen entworfen. Jede entstand einzeln, als jemand
     einen Wert brauchte und den naechsten plausiblen nahm. Zwischen .06 und
     .07 liegt nichts, was ein Auge trennt -- aber beide muessen gepflegt
     werden, und wer die eine aendert, findet die andere nicht.

     Fuenf Stufen, mit Abstand dazwischen. Wer eine sechste braucht, hat
     wahrscheinlich keinen sechsten Bedarf, sondern die falsche gewaehlt.

     WAS DIESE LEITER NICHT LOEST: --accent selbst wechselt je nach Block
     (in InOut gold-mid bei Einnahmen, gold-light bei Ausgaben). Derselbe
     Ausdruck ergibt damit zwei Farben. Das ist bei einer Modulfarbe GEWOLLT
     -- die Pille soll die Farbe ihres Blocks tragen -- und war heute nur
     dort ein Fehler, wo eine NEUTRALE Flaeche gemeint war (die Rahmen im
     Rahmen, jetzt --frame-innen). Ein Gate kann diese Absicht nicht lesen.
     Es normiert deshalb die STUFEN, nicht die Farbe. */
  --wash-hauch:   .04;   /* kaum sichtbar -- Flaeche, die nur andeutet   */
  --wash-leicht:  .09;   /* erkennbar getoent -- Badge, Pille           */
  --wash-mittel:  .16;   /* deutlich -- Hover auf getoenter Flaeche     */
  --wash-kraeftig:.28;   /* Rahmen, der gesehen werden soll            */
  --wash-voll:    .45;   /* gestrichelte Kante, Fokus                  */
  --wash-satt:    .58;   /* halbdeckend -- Trennlinie auf dunklem Grund */

     /* Die sechste Stufe kam beim Umstellen dazu, nicht beim Entwerfen:
        drei Stellen lagen bei .55/.6, und sie auf .45 zu ziehen haette sie
        um 10-15 % aufgehellt. Eine Vereinheitlichung, die das Aussehen
        aendert, ist keine Vereinheitlichung mehr, sondern eine
        Gestaltungsentscheidung -- und die trifft nicht das Aufraeumskript. */

  /* ═══ HOEHE DER ANTEILSBALKEN (02.09.2026) ════════════════════════════
     Stand als 6px in css/styles.css (.split-bar) und nochmal als 6px in
     shared/modulseite.css (.anteil-balken). Zwei Dateien, dieselbe Zahl,
     kein Zusammenhang -- der naechste Kandidat zum Auseinanderlaufen.

     6 → 10 px: die Leitzahl darueber ist auf 48 px gewachsen, ein 6-px-
     Streifen darunter wirkt daneben wie ein Haar. Mehr Gewicht ohne mehr
     Farbe. Die Luecke von 4 px bleibt -- sie steht in .anteil-balken als
     eigene Variable, weil js/dashboard.js sie mitrechnet. */
  --balken-hoehe:        10px;

  /* ═══ HOEHE EINER LABELZEILE (04.09.2026) ═════════════════════════════
     19 px stand als width/height in shared/ui-icons.css (.info-hint) und
     waere am 04.09. ein zweites Mal in css/styles.css gelandet, als
     `--label-zeile: 19px` mit dem Kommentar "aendert die sich, muss diese
     mit". Eine Regel, die nur im Kopf lebt, ueberlebt keinen Umbau -- also
     eine Quelle.

     WOFUER: die Zeile, in der ein Label und sein Info-Symbol nebeneinander
     stehen. Ihre Hoehe IST die Hoehe des Symbols; alles andere liesse das
     Symbol aus der Zeile ragen und die Zahl darunter tiefer rutschen.

     Die KPI-Kachel reserviert zwei davon (siehe .portfolio-strip in
     css/styles.css) -- nicht als Luxus, sondern damit ein umbrechendes
     Label seine Zahl nicht unter die der Nachbarkacheln schiebt. */
  --label-zeile:         19px;

  /* ═══ HOEHE EINES DIAGRAMMS AUF EINER METRICS-SEITE (04.09.2026) ══════
     MWM: "da haben wir noch kein einheitliches Pixelraster … ausmessen
     zuerst, danach angleichen."

     Gemessen, dieselbe Bauform auf zwei Metrics-Seiten:

       .chart-tall            300px   css/styles.css      entwicklung, steuer
       .line-wrap canvas      320px   calculator.css      estate/portfolio

     Zwanzig Pixel auseinander, beide als Rohwert. Keine Entscheidung — die
     Seiten sind zu verschiedenen Zeiten entstanden.

     300 gewinnt: es ist der Wert der Musterseite, an der die Metrics-Regel
     am 03.09. entwickelt wurde.

     NICHT betroffen: .chart-tall in depot/css/styles.css (280px). Depot ist
     eine Uebersichtsseite, keine Metrics-Seite — dort steht das Diagramm
     neben Karten und darf knapper sein. Eigener Befund, eigene Entscheidung. */
  --diagramm-hoehe:      300px;
  /* ═══ KOMPAKTE FASSUNG FUER SEITEN MIT VIELEN DIAGRAMMEN (16.09.2026) ═════
     MWM zu estate/portfolio.html: "die Grafiken unten drunter sind viel zu
     groß, mach das kompakter."

     GEMESSEN, warum ausgerechnet dort: die anderen drei Metrics-Seiten zeigen
     ein bis zwei Diagramme und koennen sich 300 px leisten. Diese hier zeigt
     ACHTZEHN -- sechs Ringe allein im Beleihungs-Block, dazu vier Linien-
     diagramme und zwei Mietkurven. Bei 300 px und 220 px Ringen ist die Seite
     ueber zehn Bildschirme lang, und man scrollt an allem vorbei, was man
     gerade nicht sucht.

     Die Hoehe ist damit keine Geschmacksfrage, sondern haengt an der ANZAHL.
     Deshalb ein eigener Wert statt einer kleineren Grundhoehe: Seiten mit
     einem Diagramm sollen gross bleiben.

     200 px statt 300: zwei Drittel, und es ist die Stufe, auf der eine
     Kurve ueber 20 Jahre noch lesbar bleibt (.chart-mid steht seit jeher auf
     190 px und wird auf den Modulseiten genau dafuer benutzt).
     150 px statt 220 fuer die Ringe: sie tragen eine Prozentzahl in der
     Mitte, und die braucht bei --fs-kpi rund 60 px Durchmesser. */
  --diagramm-hoehe-kompakt: 200px;

  /* ═══ MINDESTHOEHE DER OBJEKTKARTE  (17.09.2026) ═════════════════════════
     Die Karte einer Immobilie (estate/index.html) hatte `min-height:310px`
     als Rohwert. Der Inhalt ist nachgerechnet rund 514 px hoch, die Grenze
     greift also im Normalfall gar nicht -- sie ist ein Boden, keine Vorgabe.

     310 → 280: die drei grossen Luecken der Karte sind auf die Abstands-
     skala gekommen (30→20, 26→16, 26→16), das sind genau 30 px weniger
     Inhalt. Der Boden zieht mit, damit er dieselbe Reserve bedeutet wie
     vorher und nicht stillschweigend strenger wird.

     Wozu eine Mindesthoehe ueberhaupt: steht nur EINE Karte in einer Reihe,
     hat das Raster nichts, woran es sie ausrichtet. Sie soll dann nicht
     merklich flacher sein als eine volle Reihe. */
  --karte-hoehe-projekt: 280px;
  --ring-groesse:           220px;
  --ring-groesse-kompakt:   150px;

  /* ═══ POLSTER EINER ZONE (02.09.2026) ═════════════════════════════════
     Der Innenabstand der Zonenboeden stand als `var(--sp-5) var(--sp-5)
     var(--sp-5)` in SECHS Regeln in vier Dateien -- dreimal derselbe Wert
     pro Regel, weil irgendwann jemand oben, seitlich und unten getrennt
     halten wollte und es nie gebraucht hat.

     Jetzt eine Rolle statt einer Stufe: --zone-polster sagt WOFUER der
     Abstand da ist, --sp-6 sagt, WIE GROSS er ist. Wer ihn aendern will,
     aendert eine Zeile statt sechs Regeln zu finden.

     20 → 24 px: der Vorschlag aus dem Figma-Durchlauf. Die Leitzahl ist auf
     48 px gewachsen, die Balken auf 10 -- der Rand darf mitwachsen, sonst
     wird die Zone eng um einen Inhalt, der lauter geworden ist. */
  --zone-polster:        var(--sp-6);

  /* ═══ ZEILENWECHSEL IN TABELLEN (02.09.2026) ══════════════════════════
     Vorschlag aus dem Figma-Durchlauf, uebernommen: bei elf Zeilen
     untereinander ist die dezente Abwechslung der groesste Lesegewinn --
     das Auge haelt die Zeile, ohne dass eine Linie sie einsperrt.

     #fafaf9 ist absichtlich fast Papier. Was man als Streifen ERKENNT, ist
     schon zu stark: dann liest man das Muster statt der Zahlen. Es soll
     nur verhindern, dass zwei Zeilen ineinanderlaufen.

     NICHT uebernommen wurde der warme Tabellenkopf (#f4f1ec) aus demselben
     Vorschlag: die Tabellen stehen in der KUEHLEN Zone. Warm und kuehl
     trennen bei uns Vermoegen von Aufschluesselung -- ein warmer Kopf
     mitten in der kuehlen Zone bricht die Regel fuer einen Effekt, den man
     kaum sieht. */
  --tabellen-zeile-wechsel: #fafaf9;

  --hover-flaeche:       rgba(23, 23, 23, .045);
  --hover-flaeche-warn:  rgba(226, 75, 74, .08);
  /* KORREKTUR 02.09.2026: hier stand --fokus-linie: var(--fokus-linie) --
     der Token verwies auf sich selbst. Eine solche Definition ist zur
     Laufzeit ungueltig, die ganze Deklaration faellt aus, und der einzige
     Nutzer (.entity-list input:hover in inout/css/styles.css) bekam keine
     Randfarbe. Dieselbe Bauform wie der unsichtbare Klapp-Chevron am
     31.08. -- Gate 29 findet sie nicht, weil eine Definition ja da IST.
     Wert aus dem Bestand: alle acht anderen Fokus-Regeln der Suite nehmen
     --accent. */
  --fokus-linie:         var(--accent);
  /* ─── Radien ────────────────────────────────────────────────────────────
     ═══ VIER STUFEN STATT FUENF  (17.09.2026) ═══════════════════════════════
     MWM bringt eine Skala aus einem anderen Projekt mit und fragt: "koennen
     wir ALLE Kachelkanten im gesamten Projekt hiernach anpassen?"

       10 px   alle grossen Formen — Kacheln, Rahmen, Arbeitsflaechen
        8 px   Bedienelemente, eine Stufe darunter
        4 px   Bilder innerhalb einer Karte
        2-3 px Miniaturbalken

     WAS SICH AENDERT: die drei grossen Stufen fallen zusammen. Vorher
     20 (Zone) / 18 (Rahmen) / 14 (Karte), jetzt alle drei 10.
     118 von 167 Selektoren bekommen einen anderen Wert.

     WAS DAS KOSTET, und warum es trotzdem richtig ist.
     Die absteigende Treppe 20 → 18 → 14 war das dritte Signal fuer die
     Verschachtelung: aussen weich, nach innen knapper. Mit einem einzigen
     Wert traegt der Radius diese Aussage nicht mehr. Sie bleibt trotzdem
     lesbar, weil zwei staerkere Signale sie schon tragen:
       FARBE    beiger Traeger, blauer Block, weisse Karte
       POLSTER  20 → 20 → 12, seit heute frueh sauber absteigend
     Der Radius war der schwaechste der drei -- 20 gegen 18 ist ein
     Unterschied, den niemand ohne Lineal sieht. Genau das steht seit dem
     04.08.2026 zwei Absaetze weiter unten: "zwei Radien, die nur 2 px
     auseinanderliegen, behaupten einen Unterschied, den das Auge nicht
     aufloesen kann". Die alte Skala hat gegen ihre eigene Begruendung
     verstossen; die neue nicht mehr.

     DREI NAMEN WERDEN EINER. --r-zone, --r-frame und --r-card haetten
     denselben Wert getragen -- drei Namen fuer eine Zahl sind keine Rollen,
     sondern eine Einladung, sie irgendwann auseinanderlaufen zu lassen.

     WAS BLEIBT: --r-pill und --r-kreis. Beide sind keine Groessen, sondern
     Formen -- 999 px macht eine Pille, 50 % macht einen Kreis. Wer einen
     Punkt will, muss 50 % nehmen, sonst wird er bei jeder Breitenaenderung
     oval.

     VORGESCHICHTE, damit niemand sie zweimal macht: am 04.08.2026 standen
     im Projekt 17 verschiedene Rohradien (3, 6, 7, 8, 9, 10, 12, 13, 14, 16,
     18, 20, 22, 50 %, 999 px und zwei asymmetrische Formen). Sie wurden auf
     fuenf Tokens zusammengefasst, am 25.08.2026 um ein Drittel verkleinert
     (28/26/20/14/8 → 20/18/14/10/6), und heute auf vier gebracht.
     tools/check-tokens.mjs (Pruefung 15) haelt die Skala.                */
  --r-gross:  10px;   /* Kacheln, Rahmen, Arbeitsflaechen                  */
  --r-bedien:  8px;   /* Eingabe, Auswahl, Knopf                           */
  --r-bild:    4px;   /* Bilder und kleine Bloecke in einer Karte          */
  --r-strich:  3px;   /* Miniaturbalken, Vorschauen                        */

  /* ═══ POP-UP — EINE FORM FUER ALLES, WAS BEIM UEBERFAHREN ERSCHEINT ═══════
     Angelegt 26.08.2026 auf Ansage MWM: "dafuer muesste man doch irgendwie
     eine Form anlegen koennen, eine universelle an einer Stelle, wo man sagt,
     Pop-ups sehen so aus."

     ES GAB DREI FORMEN, und keine wusste von den anderen:
       1. .global-tooltip in shared/ui-icons.css -- HELL (--paper auf --ink)
       2. Chart.js -- DUNKEL, aus dessen eingebauten Vorgaben
       3. die native title-Blase des Betriebssystems -- grau, verzoegert,
          in jedem System anders
     Welche man sah, hing davon ab, woran man haengenblieb. Die dunkle aus
     den Diagrammen ist die, die Martin will -- also gilt sie fuer alle.

     WER DIESE TOKENS BENUTZT
       shared/ui-icons.css   .global-tooltip  (Erklaerungen im Markup)
       shared/popup.js       Chart.defaults   (alle Diagramme, alle Module)
     Beide lesen DIESELBEN Werte. Eine Aenderung hier bewegt beide; es gibt
     keinen Weg mehr, nur die eine Haelfte zu treffen.

     Bewusst eigene Tokens und nicht --ink/--paper direkt: ein Pop-up liegt
     UEBER der Seite, nicht in ihr. Wuerde die Palette den Seitengrund
     dunkler ziehen, muesste das Pop-up nicht mitwandern -- es hat seine
     eigene Ebene und deshalb seine eigenen Werte. */
  --popup-flaeche:  #304742;   /* tiefes Interface-Petrol, wie die Info-Kreise */
  --popup-schrift:  #ffffff;
  --popup-gedaempft: #d4e2de;  /* Zweitzeile, Einheiten, Datumsangaben */
  --popup-linie:    rgba(255, 255, 255, .10);
  /* Aus der Radius-Skala, nicht daneben. Der Name --popup-radius bleibt:
     shared/popup.js liest ihn, und "welchen Radius hat ein Pop-up" soll man
     an einer Stelle beantworten koennen.

     Zeigte bis zum 17.09.2026 auf --r-mini (6px). Diese Stufe war beim
     Skalen-Umbau am selben Tag eigentlich entfallen -- der Kopfkommentar von
     check-tokens sagte bereits "--r-mini heisst --r-bild" -- sie stand aber
     weiter in tokens.css und hielt die Skala damit bei fuenf Stufen statt
     vier. Ein Pop-up ist ein Bedienelement, also --r-bedien (8px).

     Nebenbei aufgeloest: shared/popup.js liest das Token mit einem eigenen
     Rueckfall von 8px -- der WIDERSPRACH dem Token (6px). Faellt das Token
     aus, sprang das Pop-up also auf einen anderen Wert als den gemeinten.
     Jetzt sagen beide dasselbe. */
  --popup-radius:   var(--r-bedien);
  --popup-polster:  9px 11px;
  --popup-schatten: 0 4px 16px rgba(30, 28, 24, .22);
  --r-pill:  999px;
  --r-kreis: 50%;

  /* Legacy-Alias --r (24px) ist am 04.08.2026 ENTFALLEN. Er hatte zuletzt
     noch zwei Leser (.card und .hero in estate/css/calculator.css), beide
     große Karten mit Schatten — also genau das, was --r-frame meint. Ein
     Alias, der eine sechste Radius-Größe zwischen --r-frame (26) und
     --r-card (20) einführt, ist keine Kompatibilität, sondern eine
     heimliche Zwischenstufe. tools/check-tokens.mjs meldet jede
     Neuverwendung von var(--r). */

  /* ─── Schatten ──────────────────────────────────────────────────────── */
  /* ─── Schatten: absetzen, nicht anheben (25.08.2026) ────────────────────
     Vorher 50 px Weichzeichnung — das ist keine Kante mehr, sondern Tiefe.
     Eine Karte, die 50 px weit ausstrahlt, schwebt; auf einer Seite mit
     zwanzig Karten summiert sich das zu einem grauen Schleier, der alles
     weicher aussehen lässt als es ist.

     Jetzt zwei Lagen, beide fast unsichtbar: eine harte 2-px-Kante, die
     die Karte vom Untergrund trennt, und eine 12-px-Lage, die ihr Gewicht
     gibt. Zusammen ergibt das eine sichtbare Grenze ohne Nebel.

     Werte aus dem Styleguide von /entwurf-6, auf unsere Schattenfarbe
     umgerechnet. */
  --shadow:      0 1px 2px rgba(30, 28, 24, .045),
                 0 4px 12px rgba(30, 28, 24, .035);   /* ruhende Kachel   */
  --shadow-soft: 0 1px 2px rgba(30, 28, 24, .035);    /* leichte Erhebung */

  /* ─── Haarlinien ────────────────────────────────────────────────────────
     Zwei Stärken, nicht eine:
       --line       Außenrahmen einer Karte oder eines Blocks
       --line-soft  Trennung INNERHALB — zwischen Tabellenzeilen, unter
                    einer Legendenzeile, über einer Fußzeile

     Bis heute gab es nur --line, und innen wurde gar nicht getrennt. Die
     Legende unter dem Balken war dadurch ein Block aus drei Zeilen statt
     drei einzelnen Angaben. Eine Linie, die man kaum sieht, ordnet mehr
     als ein Abstand, den man sieht. */
  --line-soft: #ece6dc;   /* Trennung innen — --v6-line-soft */

  /* ─── Die sichtbare Linie (25.08.2026, Entscheidung MWM: Variante B) ─────
     WARUM NICHT EINFACH --line
     --line wird von der aktiven Palette überschrieben: shared/palette.js
     setzt für POSTER "--line": "#E4E9EF" — ein kühles Blaugrau. Der Wert in
     dieser Datei (#e2dbcf, warm) kam nie an. Am 25.08.2026 habe ich rund
     zwanzig Kartenrahmen auf var(--line) umgestellt in der Annahme, sie
     würden warm — sie wurden blaugrau. Der Fehler war, den Wert hier zu
     lesen und nicht zu prüfen, wer ihn überschreibt.

     WAS DIESES TOKEN ANDERS MACHT
     Der Ton stammt aus .theme-v6 --v6-line, dem Vorbild.

     KORREKTUR 05.09.2026 — "palettenfest" stand hier und war zu kurz gedacht.
     Es sollte heißen: die ROLLE ist fest, der WERT nicht. Am 25.08. war das
     dasselbe, weil alle Paletten hell waren. Im Dunkelmodus lag dieser helle
     warme Ton als grelles Gitter über 98 Stellen. Seit heute nennt jede
     Palette ihren eigenen Wert (flaechen-Block in shared/palette.js,
     Entscheidung MWM). Was fest bleibt, ist die Bedeutung: eine Linie, die
     man SIEHT — nicht die Zahl dahinter.

     ARBEITSTEILUNG mit --line
       --karten-linie  jede Linie, die man SIEHT: Kartenrahmen, Trennstriche,
                       Eingabefelder, Tabellenränder. Immer warm.
       --line          nur noch Gitterlinien in Diagrammen (token("--line")
                       in den Chart-Dateien). Die dürfen mit der Palette
                       wandern — ein Diagramm ist eine eigene Fläche.

     Zwei Namen für zwei Aufgaben. Der alte Name behält seine, statt beide
     zu tragen und in der einen davon falsch zu sein.

     NACHTRAG 04.09.2026
     "nur noch Gitterlinien in Diagrammen" war zu eng formuliert. Zwei Tage
     nach dieser Entscheidung kam eine begründete Gegenentscheidung dazu
     (27.08.2026, MWM): die Unterkante der .kopfleiste bleibt auf --line,
     weil sie NAVIGATION vom Inhalt trennt und im Ton an die Seitenleiste
     anschließen soll — nicht zwei gleichrangige Flächen voneinander. Dieser
     Satz hier wusste davon nichts und behauptete weiter Ausschließlichkeit.

     Die Arbeitsteilung steht seit 04.09. in design/contract.json unter
     "linienrolle", samt Ausnahmen, und wird von tools/check-rollen.mjs
     geprüft. Dort gehört sie hin: dieser Kommentar prüft nichts. Er hat
     drei Tage nach seiner Entstehung 21 Verstöße nicht bemerkt, die in
     <style>-Blöcken standen, wo kein Wächter liest. */
  --karten-linie: #e2dbcf;

  /* ─── Wie eine Karte auf den Zeiger antwortet (25.08.2026, MWM) ──────────
     EIN Satz Werte für ALLE drei Kartenarten: Leitzahl-Karte, Wegweiser und
     Modulkarten. Vorher hatte jede ihre eigenen — 1,2 % Skalierung hier,
     2 px Versatz dort, 4 px und 3,5 % bei den Modulkarten — und alle drei
     einen Glow in --accent, der SEITENfarbe. Auf einer türkisen Karte ergab
     das einen orangefarbenen Hof: zwei Farbwelten übereinander.

     Jetzt: ein Pixel Hebung, ein grauer Schatten, keine Skalierung. Eine
     Karte, die beim Zeigen ihre Größe ändert, verschiebt ihre Nachbarn im
     Blick des Lesers mit — sichtbar soll sein, DASS sie antwortet, nicht wie
     laut. Der Schatten ist bewusst grau und bleibt es, egal welche Farbe
     darunter liegt.

     Etwa halb so stark wie vorher (0 20px 44px .09 → 0 6px 14px .05). */
  --hebung: -1px;
  --shadow-hover: 0 1px 2px rgba(30, 28, 24, .05),
                  0 6px 14px rgba(30, 28, 24, .05);
  --hover-linie: #cfc4b1;   /* dezent dunkler als --karten-linie, für Karten ohne Modulfarbe */

  /* Kleine Zeichen — Öffnen-Pfeile, Zurück-Links, Quellverweise — rücken
     statt sich zu heben. Eigener Wert, weil es eine andere Aussage ist: die
     Fläche sagt "ich bin anklickbar", das Zeichen sagt "es geht dorthin".
     Die RICHTUNG bleibt am Ort (ein Zurück-Link rückt nach links, ein
     Öffnen-Pfeil nach rechts oben) — nur die Weite steht hier. */
  --zeichen-weg: 2px;

  /* ─── Hoehe aller Bedienelemente ────────────────────────────────────────
     25.08.2026, nach dem dritten Mal, dass in einer Kopfzeile ein Knopf
     hoeher stand als das Auswahlfeld daneben.

     Der Kommentar in shared/ui-icons.css sagte schon "muessen exakt gleich
     hoch sein -- sonst tanzt die Zeile". Die Absicht war da, die
     Durchsetzung nicht: .canvas-actions setzte 40 px, .sort-select 32, und
     .primary-btn stand in keiner der beiden Listen.

     Jetzt EIN Wert. Wer ein neues Bedienelement baut, setzt keine Hoehe,
     sondern var(--knopfhoehe). check-tokens Punkt 18 weist alles andere ab. */
  --knopfhoehe: 32px;
  /* ZWEITE STUFE fuer Bedienelemente AN einer Tabelle (26.08.2026, MWM: "das
     Plus-Symbol und der Sortierer sind sehr praegnant, einfach ein bisschen
     kleiner ziehen").

     Ein Knopf in der Werkzeugleiste eines Blocks (32 px) und ein Knopf im
     Kopf einer Tabelle sind nicht dasselbe: der eine gehoert zur Seite, der
     andere zur Liste darunter, deren Zeilen 12,5 px Schrift tragen. Bei
     gleicher Hoehe wirkt der Tabellenknopf zu laut fuer das, was er tut.

     26 px ist derselbe Wert wie die Eingabefelder IN einer Zeile
     (.spar-betrag, .annahmen-zeile input) -- eine Groesse fuer alles, was
     sich einer Tabelle unterordnet, statt einer dritten Zahl. */
  --knopfhoehe-tabelle: 26px;

  /* Dauer und Kurve, ebenfalls einmal. Vorher standen .18s ease an neun
     Stellen und .2s ease an einer — ein Unterschied, den niemand gewollt,
     aber auch niemand bemerkt hat. */
  --hover-dauer: .16s;
  --hover-kurve: ease;
  /* RGB-Tripel dazu (03.08.2026, Hardcoding-Audit): für eigene, individuell
     abgestufte Schatten/Washes im selben Ton, z.B. rgba(var(--shadow-rgb),.06)
     -- vorher stand (30,28,24,X) an mehreren Stellen (shared/ui-icons.css)
     als eigenes Literal, ohne erkennbaren Bezug zu --shadow. */
  --shadow-rgb: 30, 28, 24;

  /* ─── Gelb-Highlight (seit 01.08.2026) ──────────────────────────────────
     EIN Signal für "verändert das Gesamtergebnis, nicht nur einen Wert" --
     Ist/Soll/Ist+Soll-Selects in allen drei Modulen UND der Demo-Banner
     (shared/seitenmenu.css #profilBanner). Bewusst NICHT Teil von flaechen{}
     in shared/palette.js und damit palettenunabhängig, aus demselben Grund
     wie --flaeche-invers: ein Warnsignal muss in jeder Palette gleich
     auffallen, sonst verliert es seine Funktion. Vorher an drei Stellen
     (estate/css/calculator.css, estate/css/styles.css, shared/seitenmenu.css)
     als identisches Literal kopiert. */
  --highlight-gelb:        #f7ea6e;
  --highlight-gelb-rand:   #d9a441;
  --highlight-gelb-fokus:  #b8842a;
  --highlight-gelb-schein: rgba(217, 164, 65, .25);

  /* ─── Abstände ──────────────────────────────────────────────────────────
     Vielfache von 4px. Frame-Innenabstand und Frame-Außenabstand sind
     eigene Tokens, weil sie am häufigsten auseinandergelaufen sind.     */
  /* ═══ ABSTÄNDE NACH ENTWURF 6  (25.08.2026) ═════════════════════════════
     Belegstelle: src/components/nest/Shell.tsx des Vorbilds.

         Element              dort                    px
         Inhaltsspalte        px-4 sm:px-6            16 / 24
         oben                 pt-4                    16
         Blöcke untereinander space-y-3               12
         Karten im Raster     gap-2                    8
         Seitenleiste         px-3 py-4               12 / 16
         Navigationszeile     px-2 py-1.5              8 / 6

     WARUM DAS ZUR BASIS GEHÖRT
     Diese Werte sind FESTE Pixel und schrumpfen nicht mit der Umstellung
     von 16 auf 13 px mit. Ohne sie stünde kleine Schrift in unveränderten
     Kästen — eine Seite, die weder wie vorher noch wie das Vorbild aussieht.
     Beides gehört in einen Schritt.

     Unsere Werte lagen durchweg beim Anderthalbfachen: Frame-Innenabstand
     32 px gegen 20, Seitenrand 48 gegen 16, Frame-Abstand 56 gegen 12. */
  --sp-1: 4px;
  --sp-2: 8px;    /* Karten im Raster                                     */
  --sp-3: 12px;   /* Blöcke untereinander                                 */
  --sp-4: 16px;   /* Innenabstand einer Karte, Seitenrand mobil           */
  --sp-5: 20px;   /* Innenabstand eines Blocks/Panels ab sm               */
  --sp-6: 24px;   /* Seitenrand ab sm                                     */

  /* ═══ ZWEI INNENMASSE (05.09.2026, Hardcoding-Audit #141) ══════════════════
     Die Skala oben ist eine 4er-Skala und deckte 224 Stellen. 247 lagen
     genau dazwischen: 6px (69x), 10px (65x), 14px (46x), 18px (46x),
     22px (21x) -- ueber padding, gap und margin verteilt, nicht in einer
     Ecke. Eine Skala, an der die Haelfte vorbeigeht, schraenkt nichts ein.

     Drei Wege standen zur Wahl: fuenf Halbstufen ergaenzen (dann ist jeder
     Wert "auf der Skala" und die Skala sagt nichts mehr), alles runden
     (247 Stellen bewegen sich), oder unterscheiden.

     GEWAEHLT: unterscheiden. 6 und 10 sind keine Layoutabstaende, sondern
     INNENMASSE kleiner Bauteile -- die Polsterung einer Pille, einer
     Tabellenzelle, eines Chips. Dafuer bekommen sie einen Namen, der die
     Sache nennt. 14, 18 und 22 sind Abstaende ZWISCHEN Elementen; dort sind
     zwei Pixel unsichtbar, sie ruecken auf die naechste Stufe (16/20/24).

     Damit bleibt die 4er-Skala das Layoutraster, und die zwei Innenmasse
     sagen, wofuer sie da sind. Rolle statt Zahl -- dieselbe Logik wie bei
     den Schriftrollen und den Farbbedeutungen. */
  --sp-innen:  6px;   /* Polsterung kleiner Bauteile: Pille, Chip, Knopf   */
  --sp-zelle: 10px;   /* Polsterung einer Tabellenzelle oder eines Feldes  */

  /* ── Feldmasse (17.09.2026) ───────────────────────────────────────────────
     Wie hoch ist ein Eingabefeld? Bis heute gab es darauf ZWEI Antworten,
     und welche galt, haengt davon ab, in welchem Raster das Feld stand:

       --feld-hoehe: 53px   in einem :root INNERHALB von calculator.css,
                            wirksam nur fuer .tax-grid
       padding: 15px …      an der generischen input-Regel, ergibt 50px,
                            wirksam fuer alle uebrigen 53 Felder der Objektseite

     Beide Werte standen neben der Abstands-Skala (4/8/12/16/20/24), beide
     waren zu hoch: bei 13px Grundschrift ist 50px fast die vierfache
     Zeilenhoehe. Gemessen auf estate/project.html gab es SIEBEN verschiedene
     Feldhoehen -- 24, 31, 32, 34, 44, 45, 50 px -- fuer dieselbe Sache.

     Jetzt eine Antwort, und sie steht hier statt in einem Modul:
       Zeile 13 × 1.4 = 18.2  +  2 × --sp-2 (8)  +  2 × Rand  =  36 px      */
  --feld-hoehe:        36px;
  --feld-polster-y:    var(--sp-2);   /* 8px — senkrecht im Feld            */
  --feld-polster-x:    var(--sp-3);   /* 12px — waagerecht im Feld          */
  --feld-polster-einheit: 52px;       /* rechts, wo €/m²/% steht            */
  --feld-label-hoehe:  19px;          /* eine Zeile Label, damit Raster fluchten */
  /* --frame-pad ENTFERNT am 05.09.2026: null Verwendungen. Die Polsterung
     der Rahmen steht in shared/modulseite.css bei der Bauform selbst. */
  /* Die Rahmenabstaende sind KEINE eigene Leiter, sondern zwei Sprossen der
     Leiter darueber mit einem Namen, der ihre Aufgabe nennt. Bis 02.09.2026
     standen hier die Zahlen 12px und 16px noch einmal ausgeschrieben --
     dieselben Werte wie --sp-3 und --sp-4, aber ohne dass eine Stelle von
     der anderen wusste. Wer die Leiter enger stellt, hat sonst zwei Systeme:
     eines, das mitgeht, und eines, das stehenbleibt. */
  --frame-gap:    var(--sp-3);   /* Abstand zwischen zwei canvas-frames   */
  --frame-gap-lg: var(--sp-4);   /* Abstand unter dem master-frame        */

  /* ─── Typografie ────────────────────────────────────────────────────────
     Eine Familie für alles, Überschrift wie Fließtext wie Zahlen (tabellar-
     ische Ziffern). Bis 01.08.2026 gab es hier zwei getrennte Stacks
     (--font-head: Georgia für Überschriften, --font-body: Inter für den
     Rest) -- Georgia wurde aber nirgends mehr im echten Board-CSS
     verwendet, nur noch in diesem Token selbst und im eigenen Vorschau-Text
     von js/farben.js.

     --font-head ENTFERNT am 05.09.2026. Es blieb "als Alias erhalten, damit
     nichts bricht, das ihn noch referenziert" -- gemessen referenziert ihn
     nichts: null var(--font-head) in der ganzen Suite. Ein Alias, der keinen
     Aufrufer hat, sichert nichts ab; er behauptet nur, es gaebe noch zwei
     Schriften.                                                          */
  /* ═══ ERSCHEINUNG — drei unabhaengig waehlbare Farbebenen (17.09.2026) ═════
     Eine Ebene UNTER der Palette und UEBER den Grundwerten. Sie beantwortet
     drei Fragen, die bisher keine eigene Antwort hatten:

       Flaechen     welchen Ton haben die grossen Zonen
       KPI          welches Dunkel tragen die hervorgehobenen Kennzahlen
       Innenkarten  welches Weiss haben die Karten in diesen Zonen

     WARUM EIGENE TOKENS UND KEINE UMFAERBUNG DER VORHANDENEN.
     Gemessen am 17.09.2026, bevor eine Zeile geschrieben wurde:

       --flaeche-invers  12 Stellen -- davon nur DREI KPI-Kacheln. Die uebrigen
                         neun sind Primaerknopf, gedrueckter Perspektive-
                         Schalter, ausgewaehltes Choice-Label, Profilbanner
                         und zwei Utility-Klassen. Wer das Token auf Petrol
                         setzt, bekommt petrolfarbene Knoepfe.
       --paper           83 Stellen -- 27 Karten, 19 Eingabefelder, 10 Chrom
                         (Seitenmenue, Kopfleiste, Kontextmenue), Rest
                         Rechenzeilen und Pillen INNERHALB von Karten. Eine
                         Umfaerbung traefe die Eingabefelder mit.

     Deshalb: neue, semantische Tokens, und die 27+3 Kartenstellen einzeln
     umgehaengt. Die Felder bleiben, wo sie sind. Die Vorgabewerte hier sind
     exakt der Zustand von vorher -- wer nichts waehlt, sieht nichts anders. */
  --kpi-flaeche:        var(--flaeche-invers);
  --kpi-text:           var(--flaeche-invers-text);
  --kpi-text-leise:     rgba(var(--flaeche-invers-text-rgb), .72);
  /* Statuswerte AUF einer KPI-Kachel. Getrennt von --zahl-positiv/-negativ
     (die gelten auf hellen Flaechen) und von den Diagrammfarben (die tragen
     Bedeutung im Balken, nicht auf dunklem Grund). Gemessen 17.09.2026:
     der bisherige Rueckfallwert #d9695a haelt auf Schwarz (5,22:1), faellt
     aber auf Graphit (2,79) und Petrol (2,91) durch AA. */
  --kpi-gut:      #A6E0B6;
  --kpi-schlecht: #FFB3A7;
  --innenkarte-flaeche: var(--paper);
  --innenkarte-linie:   var(--karten-linie);

  --font-body: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Zweite Schrift der Suite, und die einzige neben Inter: eine Monospace
     fuer Dinge, die KEIN Fliesstext sind, sondern Kennungen -- Klassennamen,
     Tokennamen, Hex-Werte, Kuerzel, Feldnamen, Baumdarstellungen. Sie
     markiert "das hier ist woertlich zu lesen", nicht "das hier ist schoen".
     Sie stand bis zum 17.09.2026 an 17 Stellen als Rohwert, in ZWEI
     Schreibweisen: "SF Mono" (16x) und SFMono-Regular (1x, shared/historie.css).
     Beide meinen dieselbe Schrift -- Apples Systemmonospace -- aber nur die
     zweite trifft sie auch dann, wenn der Nutzer sie nicht separat
     installiert hat. Kein sichtbarer Unterschied auf Windows: dort greift
     in beiden Faellen ui-monospace (Cascadia Mono). Trotzdem zwei
     Schreibweisen fuer eine Schrift, also eine zu viel. */
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* ═══ SCHRIFTLEITER NACH ENTWURF 6  (25.08.2026) ═══════════════════════
     Übernommen aus dem QUELLTEXT des Vorbilds, nicht aus Messungen am
     gerenderten Bild. Belegstellen: src/components/nest/Shell.tsx (Basis
     und Layout), src/styles.css .theme-v6 (Farben und Linien).

     DIE BASIS IST 13 px, NICHT 16.
     Shell.tsx setzt `text-[13px]` am äußersten Container; jede weitere
     Größe ist ein Vielfaches davon. Wir standen auf dem Browserstandard
     16 px — ein Faktor 1,23 auf ALLES, was in rem angegeben ist. Das war
     der Grund, warum unsere Seite durchgehend größer wirkte, obwohl
     einzelne Werte angeglichen waren. An Radien und Schatten zu drehen,
     während die Grundlage abweicht, konnte nicht funktionieren.

     Die Umstellung geschieht am :root weiter oben in DIESER Datei
     (Zeile 51, `font-size: 13px`). Bis 02.09.2026 stand hier
     "in css/basis.css (html { font-size })" -- diese Datei existiert nicht
     und hat nie existiert. Wer den Hinweis befolgte, suchte an einem Ort,
     den es nicht gibt, und schloss daraus, die Basis sei nie umgestellt
     worden. Nachgemessen im Browser: 1rem = 13 px. Die
     Leiter hier ist bereits darauf gerechnet: 1rem = 13 px.

         Rolle                    Entwurf 6      hier
         Leitzahl Panel              26 px       2rem
         Seitentitel                 22 px       1.7rem
         Ergebnis einer Herleitung   20 px       1.54rem
         KPI-Wert                    18 px       1.38rem
         Blocktitel                  17 px       1.31rem
         Teilwert, Operator          15 px       1.15rem
         Kartentitel, Feldwert       13 px       1rem
         Zelltext, Navigation      12.5 px       0.96rem
         Untertitel, Randnotiz     11.5 px       0.88rem
         Label, Ringbeschriftung     11 px       0.85rem
         Fußzeile, Hinweis         10.5 px       0.81rem

     Verhältnis grob 26 : 18 : 13 : 11 — vier Stufen, dazwischen nichts. */
  --fs-h1:     1.7rem;   /* Seitentitel                          22 px    */
  --fs-h4:     1.15rem;  /* Chart-/Block-Überschrift             15 px    */

  /* ═══ KENNZAHL — EINE STUFE STATT ZWEI (02.09.2026) ═══════════════════
     Hier standen zwei Grade nebeneinander:

         --fs-h2      1.31rem = 20,96 px    Kennzahl in einer Kachel
         --fs-figure  1.38rem = 22,08 px    grosse Summe auf einer Kachel

     1,12 px auseinander. Ein paar Zeilen tiefer steht seit Wochen unser
     eigener Satz dazu, ueber die Radien: "zwei Radien, die nur 2 px
     auseinanderliegen, behaupten einen Unterschied, den das Auge nicht
     aufloesen kann". Fuer die Schrift hat das nie jemand angewandt.

     Aufgefallen ist es beim Figma-Durchlauf am 02.09.2026 -- ein fremdes
     Werkzeug hat beide auf denselben Wert gesetzt, ohne zu wissen, dass es
     zwei waren. Das ist die ehrlichste Art, eine Scheinunterscheidung zu
     finden: jemandem zeigen, der die Geschichte nicht kennt.

     1.5rem = 19,5 px, also die naechste runde Stufe ueber beiden.

     KORREKTUR 02.09.2026: hier stand zuerst "1.5rem = 24 px". 24 px waeren
     1.5rem auf 16-px-Basis -- die Basis dieses Projekts ist aber 13 px
     (:root oben in dieser Datei). Ein Kommentar, der gegen die falsche
     Wurzel gerechnet hat. Gefunden von tools/check-drift.mjs, Pruefung 5. */
  --fs-kpi:    1.5rem;   /* Kennzahl, grosse Summe             19.5 px    */

  /* Die KLEINE Kennzahl -- die Zahl in einer schmalen Kachel der
     .portfolio-strip, nicht die grosse Leitzahl darueber.

     Stand bis 05.09.2026 als Rohwert 1.25rem in VIER Modul-Stylesheets
     (css/, estate/, depot/, inout/) -- dieselbe Zahl viermal, ohne dass eine
     Stelle von den anderen wusste. Exakt dasselbe Muster wie bei --fs-sektion
     am 25.08.2026, nur eine Ebene tiefer.

     Warum eine eigene Stufe und kein Runden: sie liegt zwischen --fs-h4
     (14,95 px) und --fs-sektion (17,03 px), zu beiden mehr als 0,7 px
     Abstand -- und sie steht viermal fuer DIESELBE Sache. Das ist eine
     Rolle, keine Streuung. */
  --fs-kpi-klein: 1.25rem;  /* Kennzahl in schmaler Kachel        16.25 px */

  /* Sektionstitel (h2 im .section-heading). Stand bis 25.08.2026 als
     fester Rohwert `font-size: 2rem` in vier CSS-Dateien — dieselbe Zahl
     viermal, ohne dass eine Stelle von den anderen wusste.
     32 px → 28 px: der Sprung von der Leitzahl herunter war der grösste
     der ganzen Seite. */
  --fs-sektion: 1.31rem;   /* 17 px */
  --fs-body:   1rem;     /* Kartentitel, Feldwert                13 px    */
  --fs-sm:     .96rem;   /* Zelltext, Navigation               12.5 px    */
  --fs-xs:     .88rem;   /* Untertitel, Randnotiz              11.5 px    */
  /* Die Themen-Pille ist bewusst kleiner als --fs-kicker: sie steht UEBER
     einer Ueberschrift und soll sie nicht ueberstimmen. Der Wert .72rem stand
     bis zum 26.08.2026 als Rohwert in VIER Stylesheets -- dreimal mit
     font-weight 700, in Depot mit 600. Genau diese eine Abweichung war
     sichtbar. */
  /* Unterhalb der Pille: die Seitenleiste. Ihre Beschriftungen stehen neben
     dem Inhalt, nicht darin -- sie duerfen leiser sein. Bis zum 26.08.2026
     standen dort ACHT verschiedene Grade als Rohwerte (.6 .64 .68 .72 .76
     .78 .82 .86 .96 rem), von denen keiner in der Skala stand. Niemand hat
     acht Stufen entworfen; jede entstand einzeln.
     Eine reicht: alles unter --fs-pille ist Beiwerk. */
  --fs-mini:   .66rem;
  /* ALIAS AUF --fs-fuss (17.09.2026). Vorher .72rem = 9,36 px.

     GEMESSEN auf acht Seiten: 33 Pillen standen auf 10,53 px (--fs-fuss),
     7 auf 9,36 px (--fs-pille) -- sechs davon auf farben.html, eine auf
     entwicklung.html. Zwei Pillengroessen also, und welche gilt, hing davon
     ab, in welchem Rahmen die Pille steht: zwei Kontextregeln in
     shared/modulseite.css setzten --fs-fuss und schlugen damit die
     Grundform, die --fs-pille sagt.

     Entschieden hat das nie jemand. Es ist der Zustand, den man bekommt,
     wenn eine Grundform und ihre Kontextregeln zu verschiedenen Zeiten
     geschrieben werden -- dieselbe Sorte wie die Kante, die zweimal in
     derselben Datei definiert war.

     ALIAS statt Loeschen, und alias statt zweitem Zahlenwert:
       - Loeschen waere falsch, weil die Rolle "Pille" existiert und einen
         Namen verdient. Wer spaeter alle Pillen aendern will, sucht
         --fs-pille und nicht --fs-fuss.
       - Ein zweiter .81rem-Wert waere zwei Tokens mit identischer Zahl --
         genau das Muster, das bei den Radien aufgeraeumt wurde.
     Dieselbe Loesung wie --fs-abschnittstitel, das heute frueh Alias auf
     --fs-h1 geworden ist: eigener Name fuer eine eigene Rolle, EIN Wert.

     Die 7 kleineren Pillen wachsen damit um 1,2 px. Das ist der Preis und
     er ist beabsichtigt: eine Pille ist eine Bauform, keine zwei. */
  --fs-pille:  var(--fs-fuss);
  --fs-kicker: .85rem;   /* Label, versal, +0.12em Laufweite      11 px    */
  --fs-fuss:   .81rem;   /* Fußzeile einer Karte, Hinweis      10.5 px    */

  /* ─── Mitwachsende Grade (25.08.2026) ───────────────────────────────────
     Die Werte oben sind feste Größen. Die großen Überschriften und
     Leitzahlen wachsen dagegen mit der Fensterbreite — sie standen bis
     heute als clamp()-Rohwerte in fünf CSS-Dateien und waren dadurch weder
     auffindbar noch gemeinsam änderbar.

     Gemessen am 25.08.2026 auf dem Hub: die Leitzahl steht bei 68 px,
     der Seitentitel bei 32 px, der kleinste Text bei 15 px. Eine Spanne
     von 4,5-fach. Zum Vergleich derselbe Entwurf in Lovable: 26 px zu
     12 px, also 2,2-fach — und dadurch deutlich ruhiger.

     DIESE FASSUNG ÄNDERT NICHTS. Die Tokens bilden die vorhandenen Werte
     eins zu eins ab, damit die Umstellung für sich prüfbar bleibt: erst
     die Skala einführen und nachweisen, dass sich kein Pixel bewegt hat,
     dann in einem zweiten Schritt die Werte anfassen. Zwei Änderungen auf
     einmal wären hinterher nicht auseinanderzuhalten.

     WARUM clamp() UND KEINE MEDIA-QUERY: clamp(min, gewünscht, max) wächst
     stufenlos mit der Breite statt in Sprüngen. Bei einer Zahl, die die
     halbe Karte füllt, sieht man jeden Sprung. */

  /* Die Leitzahl einer Seite — der größte Text überhaupt.
     25.08.2026: von 4.25rem (68 px) auf 3rem (48 px). Sie war eine
     Plakatgröße auf einer Seite voller Zahlen; der Sprung von dort zum
     nächsten Grad war mehr als doppelt. Sie bleibt der größte Text und
     hört auf zu schreien. */
  --fs-leitzahl:       clamp(1.7rem, 2.6vw, 2rem);   /* 22.1 → 26 px */

  /* ═══ DIE LEITZAHL DES HUB (02.09.2026) ═══════════════════════════════
     ACHTUNG BEIM LESEN DES KOMMENTARS DARUEBER: er sagt "von 4.25rem
     (68 px) auf 3rem (48 px)". Der Wert daneben ist aber 2rem.
     Es gab also eine zweite Reduktion, die niemand aufgeschrieben hat --
     ein Kommentar, der seine Entscheidung ueberlebt hat. Der dritte Fall
     dieser Art in diesem Projekt.

     Die px-Angaben in jenem Kommentar stammen zudem aus der 16-px-Zeit:
     4.25rem und 3rem sind auf der heutigen 13-px-Basis 55 px und 39 px,
     nicht 68 und 48. Der Kommentar ist als Chronik richtig und als
     Massangabe falsch -- deshalb bleibt er stehen und wird hier eingeordnet,
     statt still umgerechnet zu werden.

     Der Hub bekommt die groesste Stufe zurueck, die dort einmal stand. Er
     ist die einzige Seite mit genau EINER Zahl, auf die alles zulaeuft; die
     Modulseiten haben je drei bis vier gleichrangige. Deshalb nicht
     dasselbe Token, sondern ein eigenes -- und deshalb bleibt
     --fs-leitzahl fuer .modul-leitzahl unveraendert.

     clamp: 26 px auf schmalen Fenstern, 39 auf breiten. Eine feste
     Plakatgroesse waere auf einem Laptop die halbe Zeile. */
  --fs-leitzahl-hub:   clamp(2rem, 3.4vw, 3rem);     /* 26 → 39 px */

  /* Dieselbe Rolle in Real Estate — seit 25.08.2026 auch derselbe Wert.
     Vorher clamp(2.3rem, 5.5vw, 4.25rem) gegen clamp(2.7rem, 5.8vw, 4.25rem)
     im Hub: gleiches Maximum, verschiedene Minima. Auf breiten Fenstern
     sah man nichts, auf schmalen schrumpfte die Estate-Zahl früher. Das
     war Drift, keine Absicht — der Alias bleibt nur, damit die Stellen im
     Estate-CSS nicht mit angefasst werden mussten.

     31.08.2026, MWM: "die Zahlen in den schwarzen Kacheln sollen die gleiche
     Schriftgröße haben wie die Überschrift [Objektadresse], nicht
     größer." Gemessen 26 px gegen 22 px.

     Der Grund für den Unterschied ist entfallen: solange EIN Hero-Kasten je
     Karte stand, war seine Zahl die Leitzahl der Seite und durfte über dem
     Objekttitel liegen. Seit dem 31.08. stehen drei nebeneinander — drei
     Zahlen in Titelgröße sind kein Blickfang mehr, sondern eine zweite
     Überschriftenzeile, die mit der echten konkurriert.

     Der Alias zeigt jetzt auf --fs-titel-gross und bleibt damit an denselben
     Wert gebunden wie der Objektname darüber: ändert sich der eine, zieht
     die Kachel mit. Zwei feste Zahlen wären wieder Drift. */
  /* ZWEI STUFEN, NICHT DREI (02.09.2026, Entscheidung MWM).
     Hier stand var(--fs-titel-gross) -- also 22 bis 27,2 px, eine dritte
     Stufe zwischen der Leitzahl des Hub (48) und der der Modulseiten (32).
     Ein Werkzeug hatte 36 px als vierte vorgeschlagen.

     Drei oder vier Grade fuer "die grosse Zahl" sind wieder die
     Unterscheidung, die niemand aufloest -- derselbe Fall wie --fs-h2 gegen
     --fs-figure, den wir heute Vormittag zusammengefuehrt haben. Zwei
     Stufen reichen: eine fuer die Seite mit EINER Zahl, eine fuer die
     Seiten mit mehreren. */
  --fs-leitzahl-estate: var(--fs-leitzahl);

  /* Objekttitel: der Name einer Immobilie, auch als Eingabefeld. */
  --fs-titel-gross:    clamp(1.38rem, 2.2vw, 1.7rem);  /* bis 22 px */

  /* Seitentitel im Kopf jeder Modulseite. Einziger Grad, der schon vorher
     in allen vier Modulen denselben Wert hatte. */
  --fs-titel:          clamp(1.31rem, 2vw, 1.7rem);    /* bis 22 px */

  /* Wortmarke im Kopf — bewusst klein, sie konkurriert nicht mit dem
     Seitentitel. */
  --fs-marke:          1rem;                            /* 13 px */

  /* ═══ ABSCHNITTSTITEL — FESTE REGEL, 22 PX  (17.09.2026) ══════════════════
     MWM: "setze auch auf den Unterseiten die Ueberschriften in 22 px:
     Real Estate · Bestand & Vorhaben und Immobilien - Uebersicht. Mach das
     zur festen Regel, fuer alle Modulseiten, Analyseseiten und Steuer."

     DIE REGEL: jede Ueberschrift, die einen Rahmen benennt, ist 22 px --
     unabhaengig davon, ob der Rahmen die ganze Seite traegt (.master-frame)
     oder ein Block darin ist (.canvas-frame.zone). Beide Beispiele oben sind
     genau diese zwei Faelle; sie standen bis heute gleich gross, aber zu
     klein (17 px). Gemessen betrifft das 33 Ueberschriften auf 10 Seiten.

     WARUM EIN EIGENES TOKEN UND NICHT --fs-sektion HOCHGESETZT:
     --fs-sektion haengen ausser dem Abschnittstitel noch zwei Dinge an, die
     keine Ueberschrift sind --
       .steuer-teaser h3               eine Teaser-Zeile in Georgia
       .expense-bottom-tile .tile-value  eine ZAHL auf einer Kachel
     Haette ich den Wert dort gehoben, waeren die beiden stillschweigend
     mitgewachsen. Dieselbe Falle wie bei --fs-kpi, die Depot sich am
     09.09. fuer eine Ueberschrift geborgt hatte (#147). Die Rolle bekommt
     ihr eigenes Mass; dass --fs-sektion jetzt zwei fremde Rollen bedient,
     ist ein offener Befund, kein Teil dieser Aenderung.

     Durchgesetzt von tools/check-rollen.mjs, Pruefung 4. Der Wert steht im
     Vertrag unter schriftrollen.rollen.abschnittstitel.groesse. */
  --fs-abschnittstitel: var(--fs-h1);                   /* 22 px */

  /* ═══ DER ABSTAND UNTER EINER UEBERSCHRIFT IST EIN VERHAELTNIS  (17.09.2026)
     MWM: "die Abstaende von der Ueberschrift zum Frame darunter springen auf
     jeder Seite. Kann man daraus auch eine dynamische Regel ableiten, so dass
     es optisch passt?"

     GEMESSEN ueber 38 Ueberschriften (tools/miss-ueberschriften.mjs --abstand):
       20 px  32x   .section-heading            der Normalfall
       16 px   2x   Hub                          von mir am selben Tag gesetzt
       12 px   4x   .section-heading.eng         Depots enge Variante
     Drei Zahlen fuer eine Beziehung, keine davon aus der anderen abgeleitet.

     WARUM VERHAELTNIS STATT PIXEL: der Abstand unter einer Ueberschrift hat
     nur eine Aufgabe -- sie vom Inhalt zu trennen, ohne sie davon abzuloesen.
     Wieviel dafuer noetig ist, haengt an der GROESSE der Ueberschrift: eine
     22-px-Zeile braucht mehr Luft als eine 13-px-Zeile. Ein fester Pixelwert
     merkt davon nichts. Heute frueh ist die Ueberschrift von 17 auf 22 px
     gewachsen und der Abstand blieb auf 20 -- genau deshalb wirkt es eng.
     Als Faktor zieht er mit, wenn der Grad wechselt. Eine Entscheidung
     weniger beim naechsten Mal.

     DIE FAKTOREN, und warum gerade diese:
       0.75  Der Hub stand auf 16 px, und MWM nennt ihn als Vorbild
             ("orientiere dich am Main Frame"). 16 / 22,1 = 0,72 -- auf drei
             Viertel gerundet, weil ein glattes Verhaeltnis sich merken laesst.
       0.50  Enge Variante. Steht eine Unterzeile zwischen Ueberschrift und
             Inhalt (der Speicherstand, .tabellen-stand), trennt SIE bereits.
             Der volle Abstand darunter waere dann doppelt gesetzt.
             Depots .eng stand auf 12 px = 0,54 -- dieselbe Absicht, jetzt
             derselbe Ausdruck.
       0.25  Ueberschrift zu ihrer eigenen Unterzeile. Die beiden gehoeren
             zusammen und duerfen sich beruehren. */
  --titel-abstand:            calc(var(--fs-abschnittstitel) * .75);  /* ≈ 17 px */
  --titel-abstand-eng:        calc(var(--fs-abschnittstitel) * .5);   /* ≈ 11 px */
  --titel-abstand-unterzeile: calc(var(--fs-abschnittstitel) * .25);  /* ≈  6 px */

  /* ═══ GEWICHT, LAUFWEITE, ZEILENHOEHE (05.09.2026) ═════════════════════════
     ANLASS MWM: "ein Style Guide, damit alles konsistenter ist auch mit den
     Schriften".

     Bis heute war von fuenf Typografie-Eigenschaften genau EINE geregelt: die
     Groesse (17 --fs-Tokens, geprueft von check-tokens). Gewicht, Laufweite,
     Versalien und Zeilenhoehe standen roh im CSS -- 428 Stellen.

     Die Erhebung (tools/erhebe-schriftrollen.mjs, 05.09.2026) hat gezaehlt,
     was tatsaechlich vorkommt, statt eine fremde Skala abzuschreiben:

       Gewicht        700 x99   600 x66   500 x23   400 x21   750 x7   900 x3
       Laufweite      elf verschiedene Werte, keiner benannt
       Versalien      uppercase x40
       Zeilenhoehe    1 x23, danach acht Werte zwischen 1.08 und 1.75

     Vier Gewichte tragen 209 der 219 Stellen -- dafuer braucht es vier Namen.
     750 und 900 sind die zehn Stellen, die niemand entschieden hat; sie
     stehen als offener Punkt, nicht als fuenfte Stufe.
     ═════════════════════════════════════════════════════════════════════════ */
  --fw-normal:    400;   /* Fliesstext, Tabellenzelle                        */
  --fw-mittel:    500;   /* leichte Hervorhebung, Untertitel                 */
  --fw-halbfett:  600;   /* Kennzahl, Kicker, Schalter -- der Normalfall     */
  --fw-fett:      700;   /* Titel und Leitzahlen                             */

  /* Laufweite folgt der Groesse, nicht dem Geschmack: grosse Schrift wird
     enger gesetzt, versale Kleinschrift weiter. Zwei Werte reichen dafuer,
     der dritte ist die ausdrueckliche Null. */
  --ls-titel:   -.02em;  /* ab --fs-sektion aufwaerts                        */
  --ls-null:         0;  /* Fliesstext                                       */
  --ls-versal:   .08em;  /* Versalien bis --fs-kicker: klein braucht Luft    */
  --ls-versal-eng: .04em; /* Versalien darueber: gross braucht weniger      */

  /* Zeilenhoehe: eine Zahl steht auf sich allein (1), ein Titel darf eng
     laufen, ein Absatz braucht Luft. */
  --lh-zahl:      1;
  --lh-titel:  1.08;
  --lh-eng:    1.35;
  --lh-text:    1.6;

  /* ═══ STAPELEBENEN (05.09.2026, Hardcoding-Audit #6) ════════════════════
     Vorher zehn verschiedene Zahlen: 2 5 15 20 40 48 49 50 1000 9999. Die
     48/49/50 in der Seitenleiste sind ein Kampf, den jemand mit +1 gewonnen
     hat. Jetzt sechs benannte Ebenen; die Feinordnung INNERHALB der Leiste
     bleibt als calc() relativ zur Leiste, damit der Abstand lesbar ist. */
  --z-inhalt:     5;    /* schwebende Elemente im Inhalt (Griffe, Marker) */
  --z-schweben:  20;    /* Ausklapplisten, Popover ueber dem Inhalt        */
  --z-kopfleiste: 40;
  --z-leiste:    50;    /* Seitenleiste -- ueber der Kopfleiste            */
  --z-dialog:  1000;    /* modale Schicht, Banner                          */
  --z-tooltip: 9999;    /* immer zuoberst                                  */

  /* ═══ FOKUSRING (05.09.2026, Hardcoding-Audit #7) ══════════════════════
     Acht verschiedene Fokusringe im Bestand, in Breite und Deckkraft alle
     verschieden, alle in --accent. Ein Ring reicht. Wer abweicht, sagt warum.
     (Die alten Zahlen stehen absichtlich nicht hier: check-drift Pruefung 5
     liest eine Zahl im Kommentar als Vorgabe und meldete 6px gegen 3px.) */
  --fokus-ring: 0 0 0 3px rgba(var(--accent-rgb), .3);

  /* ═══ RECHNER-NEUTRALE (umgezogen 05.09.2026 aus estate/css/calculator.css) ══
     Sechs Farben fuer die Zins/Tilgung/Steuer-Aufschluesselung, dort am
     03.08.2026 aus neun Literalen vereinheitlicht. Sie standen in einem
     ZWEITEN :root -- ein Token-System neben diesem. Jetzt hier, Werte
     unveraendert.

     --kalk-kategorie-blau ist am 05.09.2026 entfallen: es bedeutete
     "wirklich bezahlt", und das ist eine Palettenrolle. Sie traegt jetzt
     selbst das Blau. */
  --kalk-neutral-dunkel: #222222;
  --kalk-neutral-mittel: #9b9b9b;
  --kalk-fill-grau:      #96938c;
  --kalk-kategorie-a:    #3a372f;
  --kalk-steuer-grau:    #6e7886;

  /* ─── Interaktion ───────────────────────────────────────────────────── */
  --transition: .15s;
}
