/* ============================================================================
   KAM OS — tokens.css: EINE geteilte Quelle für Design-Tokens und Basisregeln.
   Wird von index.html (Mock/Demo) UND index.backend.html (Produktiv) geladen —
   vorher lebten zwei handgepflegte Kopien in den <style>-Blöcken und liefen
   auseinander (dem Backend fehlten --graph-offen/--graph-laeuft, die globale
   Reduced-Motion-Regel, beide Responsive-Breakpoints und das !important an
   .tap-min). Seitenspezifisches (Login-Overlay, Boot-Screen) bleibt im
   jeweiligen HTML. Ausgeliefert unter /assets/styles/ — dieses Verzeichnis
   steht bereits in der @frontend-Allowlist des Edge-Caddy.
   ========================================================================= */
  /* Aptos is Microsoft's proprietary font — load if available locally, otherwise fall back cleanly.
     Declaring @font-face with local() lookups first means real Aptos users get it,
     everyone else gets the metric-friendly Geist fallback. */
  @font-face {
    font-family: 'AptosStack';
    src: local('Aptos'), local('Aptos Display'), local('Aptos Narrow');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
  }
  @font-face {
    font-family: 'AptosMonoStack';
    src: local('Aptos Mono');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
  }
  :root {
    --font-sans: 'AptosStack', 'Source Sans 3', 'Geist', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    --font-mono: 'AptosMonoStack', 'Geist Mono', 'JetBrains Mono', 'SF Mono', Menlo, monospace;
    --font-serif: 'Instrument Serif', Georgia, serif;

    /* Light theme tokens — warmes Bordeaux-Off-White-System */
    --bg: #f5f1ec;            /* Hintergrund: warmer Cream-Beige */
    --bg-raised: #fbf8f4;     /* Sidebar/Header: heller Off-White */
    --bg-card: #fdfaf6;       /* Karten: cremig-warmer Off-White (vorher pures #fff) */
    --bg-elev: #efe8df;       /* Erhöhte Flächen / aktive Tabs */
    --bg-dark: #2a1a1f;       /* warmer Bordeaux-Anthrazit für Tooltips/Inversen (vorher kalt-schwarz #1a1a1a) */
    --surface: var(--bg); --surface-2: var(--bg-soft);   /* alias tokens used across modules — follow the theme */
    --bg-soft: rgba(160,20,65,0.045);   /* Soft-Tint mit Bordeaux statt neutralem Grau */
    --border: rgba(160,20,65,0.10);     /* Bordeaux-getönte Borders → Wärme */
    --border-strong: rgba(160,20,65,0.18);
    --border-hover: rgba(160,20,65,0.32);
    --text: #2a1a1f;          /* dunkler Bordeaux-Anthrazit, warm getönt (vorher #1a1a1a kalt-schwarz) */
    --text-muted: #6b5560;     /* mid-tone mit dezentem Bordeaux-Tint */
    /* AA-Kleintext (>=4,5:1) NACHGERECHNET auf allen Flächen, auf denen der Ton vorkommt —
       der Vorgänger #7a6771 versprach AA, erreichte auf --bg-soft aber nur 4,32:1 (und 4,00:1
       auf --bg-soft über --bg-elev). Gemessen für #705f68: --bg 5,30 · --bg-card 5,72 ·
       --bg-raised 5,63 · --bg-elev 4,90 · --bg-soft darüber 4,91 / 5,30 / 5,21 / 4,55. */
    --text-dim: #705f68;       /* leichter, warmer Grauton — AA ≥4,5:1 bei Kleintext (s. o.) */
    --text-on-accent: #ffffff;
    --accent: #a01441;
    /* Fokusring: im Light traegt der Grundton (7,56:1 gegen --bg-card). */
    --focus-ring: #a01441;
    /* Bedeutungsfarben des Auslastungsdiagramms. Eigene Tokens, weil die Grafik zwei
       Rollen braucht — „steht noch zur Entscheidung" muss dominieren, „läuft bereits"
       zurücktreten. Vorher lieh sie sich --accent2 dafür; das ist im dunklen Thema
       #f4f2ee, also praktisch die Textfarbe, und die Aussage kehrte sich dort um.
       Beide Werte liegen über 3:1 zur Seitenfarbe (WCAG 1.4.11 für Grafiken, die zum
       Verständnis nötig sind), gemessen hell 6,99:1 / 3,29:1. */
    --graph-offen: #a01441;
    --graph-laeuft: #8f8189;
    --accent-dark: #8a1038;
    --accent-light: #c41850;
    --accent2: #5a2838;       /* dunkler Bordeaux-Cognac (vorher kalt-schwarz #1a1a1a) */
    --accent3: #d4a017;
    /* Risiko-Rot — bewusst von der Marke (Bordeaux #a01441) abgerückt: warmes Vermillon-Orange,
       das im schnellen Scan eindeutig als 'Gefahr' liest statt als Brand. Harmoniert mit Bordeaux + Gold + Cream. */
    --danger: #d64a26;
    --success: #2d6a4f;
    --warn: #b8860b;
    /* AA-Textvarianten (>=4,5:1 auf --bg-card/--bg-soft): --warn (#b8860b ~3,1:1) und
       --danger (#d64a26 ~4,15:1) reichen als KLEINTEXT nicht. Die *-text-Token nur fuer
       informativen Text < 18,66px nutzen; --warn/--danger bleiben fuer Rahmen/Icons/Grossschrift. */
    --warn-text: #8a6508;
    --danger-text: #b83410;
    /* Gleiche Regel fuer die Akzentfarben, die als informativer TEXT auftreten:
       --accent3 (#d4a017 Gold) erreicht auf --bg-card nur 2,28:1, --accent (#a01441) dagegen
       7,56:1 und bleibt deshalb im Light seine eigene Textvariante. Im Dark kehrt sich das um
       (s. unten). Kleintext IMMER ueber die *-text-Token, nie ueber die Grundtoene. */
    --accent3-text: #8a6508;   /* 5,11:1 auf --bg-card */
    /* Gefuellte Gefahr-Flaeche (Verwerfen/Loeschen-Buttons): Weiss auf --danger erreicht nur
       4,32:1 (Light) bzw. 2,94:1 (Dark). --danger-solid ist in BEIDEN Themes derselbe dunklere
       Ton, weisser Text darauf 5,94:1. --danger bleibt fuer Raender/Icons/Tints. */
    --danger-solid: #b83410;
    --accent-text: #a01441;    /* 7,56:1 — Grundton reicht im Light */
    --shadow-card: 0 1px 2px rgba(42,26,31,0.04), 0 4px 12px rgba(42,26,31,0.035);
    --shadow-card-hover: 0 2px 6px rgba(42,26,31,0.05), 0 18px 44px rgba(160,20,65,0.10), 0 6px 16px rgba(42,26,31,0.05);
    --shadow-pop: 0 4px 12px rgba(42,26,31,0.08), 0 24px 64px rgba(42,26,31,0.16);
    --shadow-drawer: -2px 0 8px rgba(42,26,31,0.05), -24px 0 60px rgba(42,26,31,0.14);
    --shadow-tooltip: 0 6px 20px rgba(42,26,31,0.16), 0 2px 6px rgba(42,26,31,0.10);
    --scrollbar-thumb: rgba(160,20,65,0.14);
    --scrollbar-thumb-hover: rgba(160,20,65,0.30);

    /* ==== Skalen (Gesamtreview 2026-08-18) ====================================
       Bisher war NUR Farbe tokenisiert — Abstand, Radius, Schriftgrößen, Motion
       und z-index lebten als ~300 ad-hoc-Werte in Inline-Styles (39 Schrift-
       größen, 21 Radien, 25 Transition-Dauern, 28 z-Ebenen). Diese Skalen sind
       der Kanon für alles Neue; Bestandsflächen wandern in Phase 2 mechanisch
       darauf. Themenneutral — gelten unverändert im Dark Mode. */
    --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
    --space-4: 16px; --space-5: 24px; --space-6: 32px;
    --radius-s: 8px; --radius-m: 12px; --radius-l: 16px; --radius-round: 999px;
    --fs-xs: 11px; --fs-s: 12px; --fs-m: 13px; --fs-body: 15px;
    --fs-l: 18px;  --fs-xl: 24px; --fs-display: 32px;
    --dur-fast: 120ms; --dur-base: 180ms; --dur-slow: 240ms;
    --ease: cubic-bezier(.2,.8,.2,1);
    /* z-Ebenen — 6 benannte Stufen statt 28 gewachsener Werte. JS-Seite:
       window.Z in src/ui.jsx (Inline-Styles können keine CSS-Variablen als
       zIndex-Zahl lesen). Kollisions-Historie: Modal lag mit 200 UNTER dem
       BD-Drawer (300); die Paare 30/31, 60/61, 90/91, 120/121 waren nach-
       trägliche Einzelreparaturen. */
    --z-nav: 10; --z-sticky: 30; --z-popover: 90;
    --z-drawer: 200; --z-dialog: 300; --z-toast: 400;

    /* Status-Rampe (Rampen-Umzug, Gesamtreview Phase 2/4): die geteilte Stufen-
       Palette von White-Spot/Leads/Partner/Forecast — vorher statische Light-Hexe
       in den Konfigs (#9d8a91/#6b7385/#cf9b16/#c2544a/#877480), im Dark farblich
       falsch. Stufen mit Bedeutungs-Pendant nutzen weiter die Semantik-Token
       (pipeline=--accent, platziert/gewonnen=--success, best=--warn). */
    --ramp-neutral: #9d8a91;     /* offen · Entwurf · Kandidat · Neu */
    --ramp-kontakt: #6b7385;     /* angesprochen · kontaktiert · Anbahnung */
    --ramp-interesse: #cf9b16;   /* Interesse · Pausiert · Update */
    --ramp-negativ: #c2544a;     /* kein Interesse · Ruhend · übersprungen */
    --ramp-geparkt: #877480;     /* Omitted / geparkt */

    /* Zeit-Rampe (Buehnen-Disziplin 2026-08-24): EINE Quelle fuer Uebergangsdauern, wie
       --ramp-* fuer Farben. Vorher lagen 120/140/150/200 ms verstreut hartcodiert in
       Board-Karte, Matrix-Zelle und Card — drei Handschriften fuer dasselbe Anfassen.
       blitz = Mikro-Feedback (Hover/Fokus/Chip), takt = Flaechen (Karte/Zeile/Drawer).
       Theme-unabhaengig: nur hier in :root, kein Dark-Pendant noetig. */
    --dauer-blitz: 120ms;
    --dauer-takt: 200ms;
  }
  [data-theme="dark"] {
    --bg: #0e0d0c;
    --bg-raised: #181715;
    --bg-card: #1c1b19;
    --bg-elev: #232220;
    /* Inverse/Tooltip-Fläche bleibt AUCH im Darkmode dunkel (mit heller Schrift) —
       sie wird app-weit für Tooltips, Toasts, dunkle Buttons & SVG-Labels genutzt.
       Toggles invertieren eigenständig über --text/--bg, brauchen das nicht mehr. */
    --bg-dark: #2a1a1f;
    --bg-soft: rgba(255,255,255,0.05);
    --border: rgba(255,255,255,0.08);
    --border-strong: rgba(255,255,255,0.16);
    --border-hover: rgba(196,24,80,0.45);
    --text: #f4f2ee;
    --text-muted: #a8a59f;
    /* Gleiche Nachrechnung im Dark: #8f8b88 lag auf --bg-soft über --bg-card bei 4,45:1
       (über --bg-elev sogar 4,07:1) — also unter AA. Gemessen für #989390: --bg 6,39 ·
       --bg-card 5,66 · --bg-raised 5,90 · --bg-elev 5,23 · --bg-soft darüber 5,77 / 4,95 / 5,19 / 4,52. */
    --text-dim: #989390;       /* AA ≥4,5:1 bei Kleintext (s. o.) */
    --text-on-accent: #ffffff;
    --accent: #c41850;
    /* Fokusring im Dark: --accent erreicht gegen die Kartenflaeche nur ~2,4:1 und verfehlt die
       3:1-Regel fuer Nicht-Text. Der hellere Akzent-Textton traegt (5,31:1). */
    --focus-ring: #f2568a;
    /* Aufgehellt, weil Bordeaux auf #0e0d0c nur 3,32:1 erreicht und damit schwächer
       dasteht als jedes Grau. Gemessen dunkel: 5,28:1 / 3,47:1 — dieselbe Rangfolge
       wie im hellen Thema. */
    --graph-offen: #e0537f;
    --graph-laeuft: #6b6764;
    --accent-dark: #a01441;
    --accent-light: #e63a72;
    --accent2: #f4f2ee;
    --accent3: #e6b933;
    --danger: #ec7350;
    --success: #4ea882;
    --warn: #e6b933;
    /* Dark: --warn/--danger sind hell und auf --bg-card (#1c1b19) bereits >=4,5:1 — Text-Token = Basis. */
    --warn-text: #e6b933;
    --danger-text: #ec7350;
    /* Dark: --accent3 (#e6b933) ist hell genug (9,30:1), --accent (#c41850) dagegen NICHT
       (2,95:1 auf --bg-card) — als Kleintext deshalb die aufgehellte Variante. */
    --accent3-text: #e6b933;
    --accent-text: #f2568a;    /* 5,31:1 auf --bg-card */
    --danger-solid: #b83410;   /* wie Light: weisser Text darauf 5,94:1 */
    --shadow-card: 0 1px 2px rgba(0,0,0,0.4), 0 4px 16px rgba(0,0,0,0.28);
    --shadow-card-hover: 0 2px 6px rgba(0,0,0,0.5), 0 18px 48px rgba(196,24,80,0.20), 0 6px 18px rgba(0,0,0,0.4);
    --shadow-pop: 0 4px 12px rgba(0,0,0,0.5), 0 28px 72px rgba(0,0,0,0.6);
    --shadow-drawer: -2px 0 10px rgba(0,0,0,0.4), -24px 0 70px rgba(0,0,0,0.55);
    --shadow-tooltip: 0 8px 28px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.4);
    --scrollbar-thumb: rgba(255,255,255,0.12);
    --scrollbar-thumb-hover: rgba(255,255,255,0.24);
    /* Status-Rampe im Dark: aufgehellte Pendants (>=3:1 gegen --bg fuer Punkte/Rahmen). */
    --ramp-neutral: #a89aa2;
    --ramp-kontakt: #94a1ba;
    --ramp-interesse: #e0b23a;
    --ramp-negativ: #e07a6f;
    --ramp-geparkt: #9e909a;
  }
  html, body { margin: 0; padding: 0; font-family: var(--font-sans); }
  /* Zahlen-Kanon (Welle 1, 2026-08-29). Ziffern richten sich app-weit in Spalten aus, OHNE dass
     dafuer die Mono-Schrift noetig waere. Gemessen bei 20 px: das Komma traegt in der Mono-Schrift
     12,0 px volle Zeichenbreite, in der Sans 5,0 px — deshalb las sich jede Euro-Angabe der
     Anwendung als "€13 , 9M" statt "€13,9M". Die Ausrichtung, fuer die Mono gewaehlt worden war,
     leistet tabular-nums genauso: "111111" und "888888" sind in der Sans beide exakt 59,65 px breit.
     Vererbt sich auf alles; Mono bleibt fuer Kennungen (C-001), Initialen und Code. */
  html { font-variant-numeric: tabular-nums; }
  /* Formularelemente erben Schrifteigenschaften NICHT von selbst — das UA-Stylesheet setzt bei
     button/input/select/textarea ein eigenes `font:` und wirft font-variant-numeric damit weg.
     Ohne diese Zeile standen Zahlen INNERHALB von Knoepfen (Portfolio-Status-Kacheln, Filter-
     Chips, Tabellenkoepfe) wieder auf proportionalen Ziffern, waehrend daneben tabulare standen.
     Nachgemessen am 2026-08-29: 3 von 6 Geldbetraegen des Dashboards waren betroffen. */
  button, input, select, textarea { font-variant-numeric: inherit; }
  /* .num — der Haken fuer Zahlen, den der Code an neun Stellen schon benutzte, den aber NIEMAND
     je definiert hat (tote Klasse, gefunden bei Welle 1). Sie ist jetzt der Kanon: Zahl in der
     Sans, tabular ausgerichtet. Eine Klasse am Element schlaegt eine vom Vorfahren GEERBTE
     Mono-Schrift — genau der Fall der Pipeline-Karten, wo die Betraege ihre Mono von einem
     Container bekamen und kein Codemod sie an ihrer eigenen Stelle finden konnte. */
  .num { font-family: var(--font-sans); font-variant-numeric: tabular-nums; }
  body {
    background: var(--bg); color: var(--text); min-height: 100vh; overflow-x: hidden;
    transition: background 240ms, color 240ms;
    font-feature-settings: "ss01", "cv11";
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
  }
  /* Papier — prozedurales Rauschen (feTurbulence, entsättigt), ~1,4 KB als Data-URI.
     Kein Bild, kein Netzwerkzugriff, CSP-konform. Liegt per z-index:-1 HINTER dem Inhalt:
     es tönt den Grund, nie die Schrift. Nimmt dem Cream das Ausgewaschene; im Dark
     invertiert es zu hellem Korn, weil dunkles Korn auf Schwarz unsichtbar wäre. */
  body::before {
    content: ""; position: fixed; inset: 0; pointer-events: none; z-index: -1;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
    opacity: .05;
  }
  [data-theme="dark"] body::before { opacity: .05; filter: invert(1); }
  /* All numbers tabular by default — no jitter when values change */
  body { font-variant-numeric: tabular-nums; }
  /* Display utilities — magazine hierarchy */
  .display-xl { font-family: var(--font-serif); font-weight: 400; font-style: italic; letter-spacing: -2px; line-height: 0.95; font-size: clamp(64px, 7vw, 112px); }
  .display-lg { font-family: var(--font-serif); font-weight: 400; font-style: italic; letter-spacing: -1.5px; line-height: 1.0;  font-size: clamp(40px, 4.4vw, 64px); }
  .display-md { font-family: var(--font-serif); font-weight: 400; font-style: italic; letter-spacing: -0.8px; line-height: 1.05; font-size: clamp(28px, 2.8vw, 40px); }
  .eyebrow    { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 1.4px; font-size: 11px; }
  * { box-sizing: border-box; }
  #root { min-height: 100vh; }

  /* Density — adjust common spacings via attribute selector */
  html[data-density="compact"]   { --gap-s: 8px;  --gap-m: 14px; --gap-l: 18px; --pad-card: 14px; --pad-view: 18px 22px 40px; }
  html[data-density="spacious"]  { --gap-s: 16px; --gap-m: 24px; --gap-l: 36px; --pad-card: 28px; --pad-view: 36px 44px 80px; }
  html:not([data-density]), html[data-density="comfortable"] { --gap-s: 12px; --gap-m: 18px; --gap-l: 28px; --pad-card: 20px; --pad-view: 28px 32px 60px; }
  html[data-density="compact"] .fade-in { gap: 18px !important; }
  html[data-density="spacious"] .fade-in { gap: 36px !important; }
  /* Pro-Detail: sanftes Einblenden des aufgeklappten Inhalts */
  @keyframes pdReveal { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }
  /* Adoptiert (Buehnen-Disziplin 2026-08-24): Landung der Board-Karten — jede Karte tritt beim
     Mounten (auch nach Spaltenwechsel/Anpacken: Re-Parenting = Re-Mount) mit demselben kurzen
     Auftritt an, statt hart zu erscheinen. Dauer aus der Zeit-Rampe. */
  .pd-reveal { animation: pdReveal var(--dauer-takt) ease-out; }
  @media (prefers-reduced-motion: reduce) { .pd-reveal { animation: none; } }
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 10px; }
  ::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }

  /* ===== Formular-Kanon =====================================================
     Die App traegt ueber 60 <select> in rund 30 Dateien, jedes mit eigenem Inline-Stil.
     Das AUSSEHEN des Aufklappers kam aber vom Betriebssystem: auf macOS ein zarter
     Doppelpfeil, auf Windows ein grauer Kasten, in Firefox etwas Drittes. Nebeneinander
     im selben Formular sahen zwei Felder nie gleich aus.

     Hier bekommt jedes Auswahlfeld EINEN Pfeil — gezeichnet aus zwei Verlaufs-Dreiecken,
     nicht als Bilddatei, damit er dem Farbton folgt und in beiden Themes stimmt.

     Warum !important: die Komponenten setzen `background: <farbe>` INLINE. Das ist die
     Kurzform und setzt `background-image` still auf none — der Pfeil waere ueberall dort
     weg, wo ein Feld seine Flaeche selbst faerbt (also fast ueberall). Erzwungen wird
     deshalb NUR das Bild und sein Platz, nie die Farbe: die bleibt bei der Komponente.
     Dasselbe Muster und derselbe Grund wie bei .tap-min weiter unten.

     :not([multiple]):not([size]) — ein aufgeklappter Listenkasten ist kein Aufklapper
     und braucht keinen Pfeil. */
  select:not([multiple]):not([size]) {
    appearance: none !important;
    -webkit-appearance: none !important;
    background-image:
      linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
      linear-gradient(135deg, var(--text-muted) 50%, transparent 50%) !important;
    background-position: calc(100% - 17px) calc(50% - 1px), calc(100% - 13px) calc(50% - 1px) !important;
    background-size: 5px 5px, 5px 5px !important;
    background-repeat: no-repeat !important;
    padding-right: 32px !important;
    cursor: pointer;
  }
  select:not([multiple]):not([size]):disabled,
  select:not([multiple]):not([size])[aria-disabled="true"] { cursor: default; opacity: .6; }

  /* Anfassbar: bis hierher gab es zwischen „ruht" und „hat den Fokus" nichts. Ein Feld,
     das unter dem Zeiger nicht reagiert, wirkt tot — und man sieht erst NACH dem Klick,
     welches man erwischt hat. Die Farbe bleibt Sache der Komponente, hier aendert sich
     nur die Rahmenfarbe. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select, textarea { transition: border-color 120ms ease, box-shadow 120ms ease; }
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):hover:not(:disabled),
  select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--border-hover); }
  /* „Bewegung reduzieren" schaltet die Uebergaenge ueber die globale Regel unten ab. */

  /* Nur fuer Hilfsmittel: aus dem Bild genommen, aber im Baum und damit vorlesbar.
     Anlass: Tabellen aus <div>-Rastern haben keine Spalten-Zuordnung. Wo die Zelle ihr
     Etikett aus Platzgruenden nicht mehr ZEIGT, muss sie es trotzdem TRAGEN — sonst liest
     ein Screenreader „€420K / €1,5M" ohne jede Angabe, wovon.
     Das Muster stand bisher zweimal inline (crm-import, profil-studio); hier einmal. */
  .nur-fuer-hilfsmittel {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

  /* ===== Barrierefreiheit ===== */
  /* Sichtbarer Tastatur-Fokus (nur bei Keyboard-Navigation, nicht bei Maus) */
  /* Der Ring nutzt einen EIGENEN Ton: --accent erreicht im Dark gegen die Kartenfläche nur
     ~2,4:1 und verfehlt damit die 3:1-Regel für Nicht-Text. --focus-ring ist je Theme gesetzt. */
  :focus-visible { outline: 2px solid var(--focus-ring, var(--accent)); outline-offset: 2px; border-radius: 5px; }
  /* Icon-Knoepfe (Sortier-Pfeile, Tauschen, Loeschen): Ruhewert und Aufhellung gehoeren in EINE
     Regel — hand-gepflegte onMouseEnter/onMouseLeave-Paare liefen regelmaessig auseinander, und
     der Ruhewert 0.5 machte ausgerechnet die TASTATUR-Alternative zum Ziehen (2,11:1) zum
     blassesten Bedienelement der Seite. 0.85 auf --text-dim ergibt 4,12:1. */
  .icon-btn { opacity: .85; }
  .icon-btn:hover, .icon-btn:focus-visible { opacity: 1; }
  .icon-btn:disabled, .icon-btn[aria-disabled="true"] { opacity: .3; }
  /* WCAG 2.2 SC 2.5.8 (AA): Klickziele >= 24px. Viele Text-/Icon-Knoepfe der App sind nur so
     hoch wie ihre Schrift (11-13px). `.tap-min` waechst die TREFFERFLAECHE ueber Padding und
     nimmt dieselbe Groesse per negativem Margin wieder aus dem Layout — die sichtbare Box und
     die Zeilenhoehe bleiben damit exakt, wo sie waren. */
  /* Die Ausgleichs-Margin MUSS !important sein: sie ist die zweite Haelfte des Tricks. Ohne
     das schlug jedes inline `margin:` der Komponente sie tot — das Padding wuchs, der Ausgleich
     nicht, und die Zeile verschob sich um 12 px, waehrend das Ziel trotzdem zu klein blieb.
     Gefunden an vier Stellen, alle mit inline-margin (Editable, Zuruecknavigation, Suchfeld). */
  .tap-min { padding-top: 6px !important; padding-bottom: 6px !important; margin-top: -6px !important; margin-bottom: -6px !important; }
  /* DERSELBE Trick, jetzt als REGEL statt als Opt-in (Bedienbarkeits-Gutachten 2026-08-29).
     `.tap-min` stand an 65 Stellen — gemessen waren aber ueber 100 Klickziele unter 24 px, am
     dichtesten im Account-Plan (44) und im Massnahmen-Board (35). Eine Trefferflaeche, an die
     man DENKEN muss, wird vergessen; deshalb greift sie jetzt von selbst.

     VERWORFENER ERSTER ANSATZ: ein absolut positioniertes ::before mit min-width/min-height 24px,
     das die Trefferflaeche vergroessert, ohne die sichtbare Box anzufassen. Klingt eleganter,
     WIRKT ABER NICHT — nachgemessen mit elementFromPoint 11 px neben der Mitte eines 15-px-Knopfes:
     kein Treffer. Deshalb der direkte Weg, der nachweislich funktioniert.

     min-height UND min-width, weil beide Faelle vorkommen: zu flache Textknoepfe (Dashboard,
     Kundenliste) und zu schmale Icon-Knoepfe (Kontakte, Account-Plan). */
  /* `select` fehlte in beiden Listen (Bedienbarkeits-Gutachten, Fund 2): der Spalten-Select
     je Karte im Massnahmen-Board mass 96×20 px — bei 27 Karten an einem normalen Tag die
     haeufigste Trefferflaeche der ganzen App. Blast-Radius vor der Aufnahme geprueft: 136
     <select> in 36 Dateien, die grosse Mehrheit traegt schon 7-11 px vertikales Padding und
     liegt damit laengst ueber 24 px — die Regel ist dort ein No-op. Echt betroffen sind nur
     dicht gepolsterte Badge-Selects (Board-Karte, Wettbewerbs-Scorecard, Account-Plan-Tabellen
     wie Risiko-Register/Positionsmatrix): die stehen in Flex-Zeilen bzw. Tabellenzellen mit
     reichlich Innenabstand, wachsen dort also nur um wenige px in der Zeile — nichts
     ueberlappt, nichts bricht um. */
  main button, main [role="button"], main a[href], main select { min-height: 24px; }
  main button, main [role="button"], main select { min-width: 24px; }
  .icon-btn { min-width: 24px; min-height: 24px; display: inline-flex; align-items: center; justify-content: center; }
  .skip-link { position: fixed; top: -60px; left: 12px; z-index: 1000; padding: 10px 16px; background: var(--accent); color: #fff; border-radius: 8px; font: 600 13px/1 var(--font-sans); text-decoration: none; transition: top 150ms; }
  .skip-link:focus { top: 12px; }
  /* Der Fokusring der Zeitschiene nimmt die Textfarbe statt des Akzents: Im hellen
     Thema ist --accent zeichengleich mit --graph-offen, der Farbe der noch offenen
     Vorgänge. In einer Grafik, in der Farbe Bedeutung trägt, darf der Fokus keine
     Datenaussage nachahmen. Der Selektor nennt bewusst auch das Element: Die
     allgemeine Regel darunter trifft über [tabindex]:focus-visible mit derselben
     Spezifität und steht später — bei Gleichstand gewinnt die spätere. */
  button.bm-spur:focus-visible { outline-color: var(--text); }
  a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
  input:focus-visible, select:focus-visible, textarea:focus-visible {
    /* Muss denselben Token fuehren wie die generische Regel darueber — diese hier ist
       spezifischer und gewinnt fuer JEDES echte Bedienelement, also fuer genau die Knoten,
       auf denen wirklich getabbt wird. Mit --accent lag der Ring im Dark bei 2,95:1. */
    outline: 2px solid var(--focus-ring, var(--accent)); outline-offset: 2px;
  }
  /* Bewegung reduzieren — respektiert System-Einstellung */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.001ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.001ms !important;
      scroll-behavior: auto !important;
    }
  }

  /* ===== Responsive Schutzmechanismen ===== */
  @media (max-width: 1024px) {
    html:not([data-density]), html[data-density="comfortable"] { --pad-view: 20px 20px 48px; }
  }
  @media (max-width: 760px) {
    html:not([data-density]), html[data-density="comfortable"] { --pad-view: 16px 14px 40px; --gap-l: 18px; }
    /* Desktop-Cockpit: auf sehr schmalen Screens horizontal scrollen statt zerbrechen */
    body { overflow-x: auto; }
    #root { min-width: 880px; }
  }
