/* DASHBOARD-APP DESIGN-SYSTEM (0.1.40).
   Semantische Token-Ebene (docs/DASHBOARD_THEME.md). Dark = neutrales Anthrazit mit
   nur leichtem Blauanteil; Light = kühles Off-White. Türkis als gezielter Akzent.
   Theme via data-theme (dark|light); prefers-color-scheme als JS-freier Fallback.
   Keine komponentenspezifischen festen Dark-Farben — nur diese Tokens + Legacy-Aliase.
   Keine externen Fonts/CDNs (CSP self). */

/* ===== DARK (Basis, = data-theme="dark") ===== */
:root, :root[data-theme="dark"] {
  color-scheme: dark;
  /* Grundflächen */
  --canvas: #030812; --canvas-subtle: #050d19;
  --surface-1: #071220; --surface-2: #0a1827; --surface-3: #102234;
  --surface-elevated: #091725; --surface-interactive: #10283a;
  --overlay: rgba(3,8,18,0.78); --backdrop: rgba(0,3,9,0.72);
  /* Text */
  --text-primary: #eef5ff; --text-secondary: #9babc1; --text-muted: #65778e;
  --text-inverse: #031015; --text-disabled: #465970;
  /* Grenzen */
  --border-subtle: #10283a; --border-default: #173a4e; --border-strong: #24546b; --divider: #10283a;
  /* Akzent (Türkis) */
  --accent: #19cee2; --accent-hover: #48deeb; --accent-active: #0faabd;
  --accent-soft: rgba(25,206,226,0.13); --accent-border: rgba(25,206,226,0.44); --accent-text: #031519;
  /* Semantik */
  /* GEFUELLTE Akzentflaechen, auf denen TEXT steht (aktiver Reiter, Segment,
     Primaerknopf). Im Hellmodus reicht --accent dafuer NICHT: weisser Text auf
     #0f9e91 ergibt 3,3:1 und verfehlt AA. --accent bleibt fuer Linien, Raender,
     Fokusringe und Flaechen OHNE Text unveraendert. */
  --accent-solid: var(--accent);
  --positive: #37c58b; --positive-soft: rgba(55,197,139,0.15);
  --negative: #ff5c6c; --negative-soft: rgba(255,92,108,0.15);
  --warning: #f2b53d; --warning-soft: rgba(242,181,61,0.15);
  --info: #4c8dff; --info-soft: rgba(76,141,255,0.15);
  --neutral: #7c8698; --neutral-soft: rgba(124,134,152,0.15);
  --observe: #a78bfa; --observe-soft: rgba(167,139,250,0.15);   /* rein beobachtende KI / Challenger */
  /* Reine Identitätsfarben: niemals als Erfolg/Warnung/Fehler auswerten. */
  --venue-mexc: #1dd6d1; --venue-kraken: #9684ff; --venue-okx: #6aa7ff;
  --venue-bitpanda: #e879f9; --venue-ibkr: #62c7f5;
  --mode-total: #6aa7ff; --mode-evaluation: #1dd6d1; --mode-validation: #9684ff;
  --mode-validation-b: #668cff; --mode-trend: #c084fc; --mode-native-paper: #62c7f5;
  --mode-live: #22d3ee; --mode-shadow: #a78bfa; --mode-spot: #e879f9;
  /* Charts */
  --chart-1: #19cee2; --chart-2: #5578ff; --chart-3: #f2b53d; --chart-4: #37c58b;
  --chart-5: #ff5c6c; --chart-6: #a78bfa; --chart-7: #38bdf8; --chart-8: #f472b6;
  --chart-grid: var(--border-subtle); --chart-axis: var(--text-muted);
  --chart-tooltip: var(--surface-elevated); --chart-selection: var(--accent-soft);
  --chart-confidence: rgba(76,141,255,0.16); --chart-missing: var(--text-disabled);
  --shadow: 0 8px 24px rgba(0,0,0,0.28);
  /* 0.5.36 Mission-Control-Look: Karten-/Panelflächen bekommen eine eigene Ebene
     (Verlauf + Kantenlicht) statt einer flachen Füllung, und der Akzent darf am
     Rand EINER Karte leuchten. Bewusst als Token, damit Hell den Effekt kippen
     kann statt ihn zu erben — auf Weiß wird aus „Leuchten" ein weicher Schatten. */
  --card-sheen: linear-gradient(160deg, rgba(255,255,255,0.045), rgba(255,255,255,0) 42%);
  --card-edge: inset 0 1px 0 rgba(255,255,255,0.05);
  --glow-strength: 0.30;            /* Hell setzt das auf 0 → identische Regeln, kein Leuchten */
  --chart-line-glow: 3px;           /* Radius des Linien-Glows; Hell = 0 */
  /* Legacy-Aliase → semantische Tokens (bestehende Komponentenregeln bleiben gültig) */
  --bg: var(--canvas); --bg-elev: var(--surface-1); --bg-elev-2: var(--surface-2);
  --fg: var(--text-primary); --fg-muted: var(--text-secondary); --fg-dim: var(--text-muted);
  --accent-fg: var(--accent-text); --ok: var(--positive); --warn: var(--warning); --err: var(--negative);
  --border: var(--border-default); --border-soft: var(--border-subtle);
  /* Struktur */
  --header-h: 52px;                 /* §5: EINZEILIGER, sticky Kopf mit fester Höhe */
  --sidebar-w: 232px;
  --safe-top: env(safe-area-inset-top, 0px);   /* iOS-Kerbe: sticky Elemente rutschen nie darunter */
  --radius: 10px; --radius-sm: 6px;
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* ===== LIGHT ===== */
:root[data-theme="light"] {
  color-scheme: light;
  --canvas: #f3f6fa; --canvas-subtle: #eaeef5;
  --surface-1: #ffffff; --surface-2: #f2f5fb; --surface-3: #e8edf6;
  --surface-elevated: #ffffff; --surface-interactive: #eef2f8;
  --overlay: rgba(255,255,255,0.82); --backdrop: rgba(18,26,42,0.34);
  --text-primary: #172231; --text-secondary: #45526a; --text-muted: #6a7688;
  --text-inverse: #ffffff; --text-disabled: #9aa4b4;
  --border-subtle: #e5eaf2; --border-default: #d2dae7; --border-strong: #b5c0d1; --divider: #e5eaf2;
  --accent: #0f9e91; --accent-hover: #0c8b80; --accent-active: #0a776d;
  --accent-soft: rgba(15,158,145,0.12); --accent-border: rgba(15,158,145,0.42); --accent-text: #ffffff;
  --accent-solid: #0a776d;   /* weisser Text darauf: 5,1:1 statt 3,3:1 */
  --positive: #12996b; --positive-soft: rgba(18,153,107,0.12);
  --negative: #d92d3c; --negative-soft: rgba(217,45,60,0.12);
  --warning: #b8770a; --warning-soft: rgba(184,119,10,0.12);
  --info: #2563eb; --info-soft: rgba(37,99,235,0.12);
  --neutral: #6a7688; --neutral-soft: rgba(106,118,136,0.12);
  --observe: #7c3aed; --observe-soft: rgba(124,58,237,0.12);
  --chart-1: #0f9e91; --chart-2: #2563eb; --chart-3: #b8770a; --chart-4: #12996b;
  --chart-5: #d92d3c; --chart-6: #7c3aed; --chart-7: #0284c7; --chart-8: #db2777;
  --chart-confidence: rgba(37,99,235,0.14);
  --shadow: 0 1px 4px rgba(16,32,64,0.10);
  /* Hell kippt den Effekt, statt ihn zu erben: Kantenlicht wird zu einer feinen
     Trennlinie, Glow auf 0. Die Komponentenregeln bleiben identisch. */
  --card-sheen: linear-gradient(160deg, rgba(255,255,255,0.9), rgba(255,255,255,0) 46%);
  --card-edge: inset 0 1px 0 rgba(255,255,255,0.9);
  --glow-strength: 0;
  --chart-line-glow: 0px;
}

/* JS-freier Fallback: Systemmodus ohne data-theme folgt prefers-color-scheme.
   (theme-init setzt data-theme normalerweise vor dem Paint; dies deckt No-JS ab.) */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    color-scheme: light;
    --canvas: #f3f6fa; --canvas-subtle: #eaeef5;
    --surface-1: #ffffff; --surface-2: #f2f5fb; --surface-3: #e8edf6;
    --surface-elevated: #ffffff; --surface-interactive: #eef2f8;
    --overlay: rgba(255,255,255,0.82); --backdrop: rgba(18,26,42,0.34);
    --text-primary: #172231; --text-secondary: #45526a; --text-muted: #6a7688;
    --text-inverse: #ffffff; --text-disabled: #9aa4b4;
    --border-subtle: #e5eaf2; --border-default: #d2dae7; --border-strong: #b5c0d1; --divider: #e5eaf2;
    --accent: #0f9e91; --accent-hover: #0c8b80; --accent-active: #0a776d;
    --accent-soft: rgba(15,158,145,0.12); --accent-border: rgba(15,158,145,0.42); --accent-text: #ffffff;
    --accent-solid: #0a776d;
    --positive: #12996b; --positive-soft: rgba(18,153,107,0.12);
    --negative: #d92d3c; --negative-soft: rgba(217,45,60,0.12);
    --warning: #b8770a; --warning-soft: rgba(184,119,10,0.12);
    --info: #2563eb; --info-soft: rgba(37,99,235,0.12);
    --neutral: #6a7688; --neutral-soft: rgba(106,118,136,0.12);
    --observe: #7c3aed; --observe-soft: rgba(124,58,237,0.12);
    --chart-1: #0f9e91; --chart-2: #2563eb; --chart-3: #b8770a; --chart-4: #12996b;
    --chart-5: #d92d3c; --chart-6: #7c3aed; --chart-7: #0284c7; --chart-8: #db2777;
    --chart-confidence: rgba(37,99,235,0.14);
    --shadow: 0 1px 4px rgba(16,32,64,0.10);
    --card-sheen: linear-gradient(160deg, rgba(255,255,255,0.9), rgba(255,255,255,0) 46%);
    --card-edge: inset 0 1px 0 rgba(255,255,255,0.9);
    --glow-strength: 0;
    --chart-line-glow: 0px;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Canvas auf html UND body → keine hellere UA-Fläche in Overscroll/Safe-Area (§2). */
html { background: var(--canvas); min-height: 100%; }
body { background: var(--canvas); color: var(--text-primary); font-family: var(--font); font-size: 14px; line-height: 1.5; min-height: 100vh; }
/* §12: kein horizontaler Body-Overflow (breite Inhalte scrollen in ihren
   Containern). `clip` erzeugt anders als `hidden` keinen Zwischen-
   Scrollcontainer und hält dadurch den fixierten Sticky-Header am Viewport. */
html, body { overflow-x: clip; }
body.app-scroll-locked { overflow: hidden; overscroll-behavior: none; }

.app-root {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  grid-template-rows: auto auto 1fr;
  grid-template-areas: "nav authbar" "nav header" "nav main";
  min-height: 100vh;
  background: var(--canvas);
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
/* --text-inverse statt #fff: reines Weiss auf --err ergibt im Dunkelmodus nur
   3,0:1 und verfehlt AA. Das Token ist in beiden Themes auf den jeweiligen
   Grund abgestimmt. */
.app-authbar { grid-area: authbar; background: var(--err); color: var(--text-inverse); padding: var(--space-2) var(--space-4); font-weight: 600; }
.app-authbar[hidden] { display: none; }

/* ===== §5 KOPFZEILE — Desktop einzeilig, mobil exakt zwei feste Zeilen =====
   Links bleibt der Ort, rechts stehen Suche · System · Vollbild · Börse · Modus ·
   Steuerung in dieser DOM-Reihenfolge. Status und Sitzung leben nur im Drawer. */
.app-header {
  grid-area: header; position: sticky; top: var(--safe-top); z-index: 25;
  display: flex; align-items: center; flex-wrap: nowrap; gap: var(--space-3);
  height: var(--header-h); min-height: var(--header-h);
  padding: 0 var(--space-4); border-bottom: 1px solid var(--border-soft);
  background: color-mix(in srgb, var(--surface-1) 94%, transparent);
  backdrop-filter: blur(14px);
}
.app-header-left { display: flex; align-items: center; gap: var(--space-3); min-width: 0; flex: 0 1 auto; }
.app-globals { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
/* position: relative traegt den Such-Popover (.app-globals) — dessen linke Kante
   faellt mit der des Suchknopfs zusammen, weil dieser das erste Kind ist. */
.app-header-right { position: relative; display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); min-width: 0; margin-left: auto; flex: 0 0 auto; }
/* Bereichstitel und optionaler Unterbereich bleiben auch auf Desktop sichtbar;
   die Wort-/Bildmarke hat dort bereits ihren festen Platz in der Sidebar. */
.app-titlewrap { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.app-header .app-brand { display: none; }
.app-brand { font-weight: 700; letter-spacing: 0.02em; color: var(--accent); flex: none; }
.app-title { margin: 0; font-size: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Breadcrumb des aktiven Unterbereichs — nur wenn Platz ist (§5). */
.app-crumb { font-size: 13px; color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.app-crumb[hidden] { display: none; }
.app-crumb::before { content: '/ '; color: var(--fg-dim); }
/* Kurzfassung der globalen Filter (mobil im Kopf, Bedienung in der Offcanvas). */
.app-filter-chip {
  display: none; align-items: center; max-width: 34vw; padding: 3px 8px;
  background: var(--surface-1); color: var(--text-secondary); border: 1px solid var(--border-default);
  border-radius: 999px; font: inherit; font-size: 11px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; cursor: pointer;
}
.app-filter-chip:hover { background: var(--surface-interactive); color: var(--text-primary); }
.app-filter-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.app-nav {
  --nav-footer-clearance: 72px;
  grid-area: nav; display: flex; flex-direction: column; gap: 2px;
  padding: env(safe-area-inset-top) var(--space-2) calc(var(--space-2) + env(safe-area-inset-bottom));
  border-right: 1px solid var(--border-soft); background: var(--bg-elev);
  position: fixed; inset: 0 auto 0 0; z-index: 28; width: var(--sidebar-w);
  /* 27.07.: Die Seitenleiste füllt IMMER die volle Höhe. Vorher war sie am oberen
     Rand ausgerichtet und nur nach oben begrenzt — dadurch endete ihre Fläche mit
     dem letzten Menüpunkt und der Trennstrich brach mittendrin ab. Feste Höhe
     statt Maximalhöhe hält ihn durchgehend; längere Menüs scrollen innerhalb. */
  align-self: stretch; height: 100vh; height: 100dvh;
  overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; scrollbar-width: thin;
  scroll-padding-block: 64px calc(var(--nav-footer-clearance) + var(--space-3) + env(safe-area-inset-bottom));
}
.app-navlink {
  display: block; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  color: var(--fg-muted); text-decoration: none; font-weight: 500;
}
.app-navlink:hover { background: var(--bg-elev-2); color: var(--fg); }
.app-navlink[aria-current="page"] { background: var(--accent-solid); color: var(--accent-fg); }
.app-navlink:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ===== §6 UNTERMENÜS — die Reiter jedes Bereichs als aufklappbare Navigation ===== */
.nav-group { display: flex; flex-direction: column; margin-bottom: 2px; }
.nav-item { display: flex; align-items: center; gap: 2px; }
.nav-item .app-navlink { flex: 1 1 auto; min-width: 0; }
.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; padding: 0; background: none; color: var(--fg-dim);
  border: 0; border-radius: var(--radius-sm); cursor: pointer;
}
.nav-toggle:hover { background: var(--bg-elev-2); color: var(--fg); }
.nav-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.nav-toggle svg { transition: transform 0.15s ease; }
.nav-toggle[aria-expanded="false"] svg { transform: rotate(-90deg); }
.nav-sub { list-style: none; margin: 10px 0 var(--space-2); padding: 0 0 0 var(--space-3); border-left: 1px solid var(--border-subtle); }
.nav-sub[hidden] { display: none; }
.nav-sub-item { margin: 0; }
.app-subnavlink {
  display: block; padding: 5px var(--space-3); border-radius: var(--radius-sm);
  color: var(--fg-dim); text-decoration: none; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.app-subnavlink:hover { background: var(--bg-elev-2); color: var(--fg); }
.app-subnavlink[aria-current="page"] { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.app-subnavlink:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.app-navlink, .app-subnavlink, .nav-toggle { scroll-margin-block-end: calc(var(--nav-footer-clearance) + var(--space-3)); }
@media (prefers-reduced-motion: reduce) { .nav-toggle svg { transition: none; } }

/* ---- Alphorix-Branding (Original-Asset, unverändert; kein CSS-Glow, keine
   Umfärbung — Wirkung kommt aus dem Logo selbst; Light-Theme ohne Invertierung) ---- */
.nav-brand {
  display: flex; align-items: center; gap: var(--space-3);
  position: sticky; top: 0; z-index: 2;
  padding: var(--space-3) var(--space-3) var(--space-4);
  margin-bottom: var(--space-2); border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-elev);
}
.nav-brand-logo { width: 40px; height: 40px; display: block; flex: none; }
.nav-brand-word { font-weight: 700; font-size: 16px; letter-spacing: 0.02em; color: var(--text-primary); }
.nav-footer {
  position: sticky; bottom: calc(var(--space-2) + env(safe-area-inset-bottom)); z-index: 2; margin-top: auto;
  display: grid; gap: 4px; padding: 11px 12px;
  background: color-mix(in srgb, var(--bg-elev) 96%, transparent);
  border: 1px solid var(--border-default); border-radius: var(--radius);
  box-shadow: 0 -10px 22px color-mix(in srgb, var(--canvas) 82%, transparent);
}
.app-nav > .nav-group:nth-last-child(2) { margin-bottom: var(--nav-footer-clearance); }
.nav-footer-kicker { color: var(--text-muted); font-size: 9px; font-weight: 700; letter-spacing: .12em; }
.nav-footer-product { color: var(--accent); font-size: 12px; font-weight: 700; }
.app-brand { display: inline-flex; align-items: center; gap: var(--space-2); }
.brand-signet { width: 26px; height: 26px; display: block; flex: none; }
.app-authbar { display: flex; align-items: center; gap: var(--space-2); }
.app-authbar[hidden] { display: none; }
.app-authbar .brand-signet { width: 20px; height: 20px; }
/* Startzustand der Shell: dezent, wird beim Mount ersetzt — kein Layout-Shift,
   kein Splashscreen, keine Animation. */
.boot-brand { min-height: 70vh; display: grid; place-items: center; opacity: 0.55; }

.app-main { grid-area: main; padding: 18px 20px; min-width: 0; }
.app-main:focus { outline: none; }

.app-panel {
  background: var(--bg-elev); border: 1px solid var(--border-soft); border-radius: var(--radius);
  padding: var(--space-6); box-shadow: var(--shadow); max-width: 960px;
}
.app-panel-title { margin: 0 0 var(--space-2); font-size: 16px; }
.app-panel-note { margin: 0; color: var(--fg-muted); }

/* ---- Header-Filter (global sichtbar: Börse · Zeitraum · Linse) ---- */
.app-filters { display: flex; gap: var(--space-3); align-items: center; flex: 0 1 auto; min-width: 0; }
.app-filter { display: flex; align-items: center; gap: var(--space-2); font-size: 12px; color: var(--fg-muted); white-space: nowrap; }
.app-choice { --choice-accent: var(--accent); position: relative; flex: 0 0 auto; }
.app-choice-trigger {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 32px; padding: 4px 11px; color: var(--choice-accent);
  background: color-mix(in srgb, var(--choice-accent) 14%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--choice-accent) 48%, var(--border-default));
  /* 09.08.: dieselbe Kantenrundung wie die Nachbarn im Kopf (.app-iconbtn).
     Vorher 999px — die Vollrundung wirkte neben den eckigen Icon-Knöpfen
     wie ein Fremdkörper. */
  border-radius: var(--radius-sm); font: inherit; font-size: 12px; font-weight: 700; cursor: pointer;
}
.app-choice-trigger::after { content: ''; width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .16s ease; }
.app-choice.is-open .app-choice-trigger::after { transform: translateY(2px) rotate(225deg); }
.app-choice-trigger:hover { background: color-mix(in srgb, var(--choice-accent) 20%, var(--surface-1)); }
.app-choice-trigger:focus-visible { outline: 2px solid var(--choice-accent); outline-offset: 2px; }
.app-venue-choice .app-choice-trigger { min-width: 86px; }
.app-mode-choice .app-choice-trigger { min-width: 42px; padding-inline: 10px; }
.app-choice-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 65;
  display: grid; gap: 3px; min-width: 190px; max-height: min(360px, 70vh); overflow-y: auto;
  padding: 5px; background: var(--surface-elevated); border: 1px solid var(--border-default);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.app-choice-menu[hidden] { display: none; }
.app-choice-option { width: 100%; min-height: 34px; padding: 6px 10px; color: var(--text-secondary); background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm); font: inherit; font-size: 13px; text-align: left; cursor: pointer; }
.app-choice-option:hover, .app-choice-option:focus-visible { color: var(--text-primary); background: var(--surface-interactive); outline: none; }
.app-choice-option.is-active { color: var(--choice-accent); background: color-mix(in srgb, var(--choice-accent) 14%, var(--surface-1)); border-color: color-mix(in srgb, var(--choice-accent) 42%, transparent); font-weight: 700; }
.app-venue-choice[data-value='mexc'] { --choice-accent: var(--venue-mexc); }
.app-venue-choice[data-value='kraken'] { --choice-accent: var(--venue-kraken); }
.app-venue-choice[data-value='okx'] { --choice-accent: var(--venue-okx); }
.app-venue-choice[data-value='bitpanda'] { --choice-accent: var(--venue-bitpanda); }
.app-venue-choice[data-value='ibkr'] { --choice-accent: var(--venue-ibkr); }
.app-mode-choice[data-value='gesamt'] { --choice-accent: var(--mode-total); }
.app-mode-choice[data-value='evaluation'] { --choice-accent: var(--mode-evaluation); }
.app-mode-choice[data-value='validation_ki'] { --choice-accent: var(--mode-validation); }
.app-mode-choice[data-value='validation_ki_b'] { --choice-accent: var(--mode-validation-b); }
.app-mode-choice[data-value='trend'] { --choice-accent: var(--mode-trend); }
.app-mode-choice[data-value='native_paper'] { --choice-accent: var(--mode-native-paper); }
.app-mode-choice[data-value='live'] { --choice-accent: var(--mode-live); }
.app-mode-choice[data-value='shadow'] { --choice-accent: var(--mode-shadow); }
.app-mode-choice[data-value='spot'] { --choice-accent: var(--mode-spot); }
/* 27.07.: Im KOPF stehen die Auswahlfelder ohne sichtbare Beschriftung — der
   Klartext bleibt als aria-label und title erhalten (Screenreader und Hover
   verlieren nichts). In der Kontext-Offcanvas, wo derselbe Knoten mobil
   einzieht, bleiben die Beschriftungen ausgeschrieben stehen. */
.app-header .app-filter-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.app-context .app-filter-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
.app-select {
  /* --surface-1 statt --bg: `--bg` ist per Legacy-Alias die SEITENfarbe. Das Feld
     sass damit auf demselben Ton wie der Hintergrund und wirkte in der Kopfzeile
     (die auf --surface-1 liegt) wie eine Vertiefung statt wie ein Bedienelement. */
  background: var(--surface-1); color: var(--fg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 5px 9px; font: inherit; font-size: 13px;
}
.app-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Engere Desktops: Beschriftungen weichen zuerst — die Bedienelemente bleiben. */
@media (max-width: 1180px) {
  .app-filter-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .app-search { min-width: 120px; }
  .app-crumb { display: none; }
}

/* ---- Header-Aktionen: drei Kontextöffner + Desktop-Vollbild ---- */
.app-iconbtn {
  display: inline-flex; align-items: center; justify-content: center; position: relative;
  width: 32px; height: 32px; padding: 0; background: var(--surface-1); color: var(--text-secondary);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm); cursor: pointer;
}
.app-iconbtn:hover { background: var(--surface-interactive); color: var(--text-primary); }
.app-iconbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.app-iconbtn[aria-pressed="true"] { background: var(--accent-solid); color: var(--accent-text); border-color: var(--accent-border); }
.app-menu-btn { display: none; }
/* Warn-Punkt der Glocke (Legacy .belldot): erscheint bei Kill-Switch oder
   nicht-gesunder Systemlage. Reine Statusanzeige, kein Zaehler. */
.app-bell-dot { position: absolute; top: 5px; right: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--err); pointer-events: none; }
.app-bell-dot[hidden] { display: none; }

/* ---- Globale Statusleiste (§11): nur im gemeinsamen Kontextdialog. ---- */
.app-statusbar { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); font-size: 12px; color: var(--fg-muted); min-width: 190px; }
/* 27.07.: Ampel + Statuszeile leben jetzt in der Kontext-Offcanvas (Abschnitt
   „Status") statt im Kopf. Dort wird linksbündig umbrochen, nicht rechtsbündig
   auf eine Zeile gedrängt. Die Regeln stehen bewusst NACH den Grundregeln. */
.ctx-status { gap: var(--space-3); }
.app-conn-text { font-variant-numeric: tabular-nums; white-space: nowrap; min-width: 88px; text-align: right; }
.app-conn-errors { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.app-conn-errors[hidden] { display: none; }

/* ---- §20 B3d: globale Status-Badges (ruhig, ohne Glow — kein Banner) ---- */
.app-health { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; flex: none; }
.app-health-text { font-size: 12px; color: var(--text-secondary); min-width: 74px; }
/* In der Offcanvas darf die Statuszeile umbrechen statt rechtsbündig auf eine
   Zeile gedrängt zu werden — die festen Mindestbreiten gelten dem Kopf. */
.ctx-status .app-statusbar { justify-content: flex-start; flex-wrap: wrap; min-width: 0; row-gap: var(--space-2); }
.app-gate-badge { color: var(--negative); border-color: color-mix(in srgb, var(--negative) 40%, transparent); }
.app-version-badge, .app-fx-badge { font-variant-numeric: tabular-nums; white-space: nowrap; }
.app-version-badge { font: inherit; }
.app-version-badge:disabled { cursor: default; opacity: 1; }
.app-version-badge.is-update { cursor: pointer; color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.app-fx-badge.is-stale { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.app-gate-badge[hidden], .app-version-badge[hidden], .app-fx-badge[hidden] { display: none; }

/* Globales, ruhendes Laufband: horizontal scrollbar statt Animation (lesbar,
   reduced-motion-unabhaengig). Daten sind Runtime-Peeks mit sichtbarem Alter. */
.app-ticker-tape {
  position: fixed; left: var(--sidebar-w); right: 0; bottom: 0; z-index: 22;
  display: flex; align-items: center; gap: var(--space-3); min-height: 34px;
  padding: 4px var(--space-4) calc(4px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border-default); background: var(--surface-elevated);
  /* Tinte aus dem Token: --shadow faellt nach unten, das Laufband braucht den
     Schatten nach OBEN — deshalb eigene Geometrie, aber Token-Farbe. */
  box-shadow: 0 -1px 4px color-mix(in srgb, var(--backdrop) 22%, transparent); overflow-x: auto; overflow-y: hidden;
  white-space: nowrap; scrollbar-width: thin; font-size: 11px;
}
.app-ticker-tape[hidden] { display: none; }
.ticker-market, .ticker-live { display: flex; align-items: center; gap: var(--space-3); flex: none; }
.ticker-market { padding-right: var(--space-3); border-right: 1px solid var(--border-default); }
.ticker-item { display: inline-flex; align-items: baseline; gap: 4px; color: var(--text-secondary); }
.ticker-item strong { color: var(--text-primary); font-weight: 650; }
.ticker-item.is-up .ticker-change { color: var(--positive); }
.ticker-item.is-down .ticker-change { color: var(--negative); }
.ticker-item.is-unavailable { color: var(--text-muted); }
.app-main { padding-bottom: calc(var(--space-8) + 34px + env(safe-area-inset-bottom)); }

/* ---- §20 B3d: globale Symbol-Suche (aufklappende Trefferliste) ----
   Seit 05.08.2026 haengt die Suche im Kopf statt in der Steuerung: als Popover
   unter dem Suchknopf (Desktop) bzw. als vollbreiter Streifen unter dem
   fixierten Kopf (mobil, siehe 768er-Block). Geometrie und Ebene sind exakt die
   des bestehenden Kopf-Auswahlmenues .app-choice-menu. */
.app-globals {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 65;
  width: min(360px, calc(100vw - 32px));
  padding: var(--space-2);
  background: var(--surface-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
/* Pflicht: die Basisregel setzt display:flex und schlaegt sonst das UA-[hidden]. */
.app-globals[hidden] { display: none; }
.app-globals .app-search { margin-left: 0; width: 100%; min-width: 0; }
.app-globals .app-search-results { min-width: 0; width: 100%; }
.app-search { position: relative; margin-left: var(--space-3); min-width: 160px; }
.app-search-input { width: 100%; min-height: 32px; }
.app-search-results {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 40;
  min-width: 260px; max-height: 320px; overflow-y: auto;
  background: var(--surface-1); border: 1px solid var(--border-default); border-radius: var(--radius-sm);
}
.app-search-results[hidden] { display: none; }
.app-search-hit {
  display: flex; justify-content: space-between; gap: var(--space-3); width: 100%;
  padding: 6px 10px; background: none; border: 0; border-bottom: 1px solid var(--border-subtle);
  color: var(--text-primary); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.app-search-hit:hover, .app-search-hit:focus-visible { background: var(--surface-interactive); }
.app-search-hit .hit-meta { color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.app-search-note { padding: 6px 10px; color: var(--fg-muted); font-size: 11px; }

/* ---- Off-Canvas-Backdrop (linke Navigation mobil · rechte Kontext-Steuerung
   auf JEDER Breite). Sichtbarkeit steuert ausschließlich das hidden-Attribut. ---- */
.app-backdrop { display: block; position: fixed; inset: 0; z-index: 30; background: var(--backdrop); }
.app-backdrop[hidden] { display: none; }

/* Gemeinsame Vollhoehen-Offcanvas-Basis. Links und rechts unterscheiden sich
   nur durch die horizontale Spiegelung; Fokus/Overlay steuert main.ts. */
.app-offcanvas {
  position: fixed; top: 0; bottom: 0; height: 100vh; height: 100dvh;
  display: flex; flex-direction: column; overflow: hidden; overscroll-behavior: contain;
}
/* 10.08. — WARUM DIESE ZEILE HIER STEHT UND NICHT OBEN BEI .app-nav:
   Die linke Navigation traegt BEIDE Klassen (`app-nav app-offcanvas`, main.ts:1741).
   `.app-nav` setzt weiter oben `overflow-y: auto`, der Block direkt darueber
   `overflow: hidden` — GLEICHE Spezifitaet (0,1,0), also entschied allein die
   Dokumentreihenfolge, und `hidden` gewann. Folge: die Seitenleiste scrollte auf
   dem Desktop nicht, sie SCHNITT AB; mit drei aufgeklappten Bereichen waren
   Strategien, KI & Learning, Intelligence, System und Einstellungen unerreichbar.
   Mobil fiel es nie auf, weil der Mobil-Block noch spaeter `overflow-y: auto`
   zuruecksetzt. Die rechte Schublade BRAUCHT ihr `hidden` (runde Ecken; dort
   scrollt `.ctx-body`) — deshalb hebt diese Regel es gezielt nur links auf. */
.app-nav.app-offcanvas { overflow-y: auto; overflow-x: hidden; }

/* ===== §6 RECHTE KONTEXT-OFFCANVAS — kontextabhängige Steuerung =====
   Filter (auf schmalen Geräten der echte Steuerungsknoten), Live-/Risiko-Status
   inkl. Kill-Switch (wiederverwendete liveControl-Ansicht). Nichts liegt
   außerhalb des Viewports; mobil vollflächig. */
.app-context {
  top: 16px; right: 16px; bottom: 16px; height: auto; z-index: 40;
  width: min(440px, calc(100vw - 32px)); max-width: calc(100vw - 32px);
  background: var(--surface-1); border: 1px solid var(--border-default); border-radius: var(--radius); box-shadow: var(--shadow);
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
  transform: translateX(calc(100% + 16px));
  transition: transform 0.2s ease, visibility 0s linear 0.2s;
  pointer-events: none; visibility: hidden;
}
.app-root.ctx-open .app-context { transform: translateX(0); pointer-events: auto; visibility: visible; transition-delay: 0s; }
.ctx-head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border-subtle);
}
.ctx-title { margin: 0; font-size: 14px; font-weight: 600; flex: none; }
.ctx-route { font-size: 12px; color: var(--fg-muted); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-close { flex: none; }
/* Legacy-Kopf: das API-Licht sitzt direkt hinter dem Titel (p50:2290). */
.ctx-head .app-health { flex: none; margin-right: auto; }
.ctx-head .app-health-text { min-width: 0; }
/* Legacy-Konto-Reihe (#rdAccount): Benutzer + Abmelden nebeneinander, oben. */
/* Sitzung: EINE kompakte Zeile — Name · Status · Rolle · Abmelden.
   Vorher ein dreizeiliger Kasten plus Knopf darunter; das kostete oben in der
   Schublade rund 90 px, bevor die erste Einstellung sichtbar wurde. Der Name
   kürzt zuerst, Status und Rolle bleiben lesbar. */
.ctx-section.ctx-account { flex-direction: row; align-items: center; gap: var(--space-2); flex-wrap: nowrap; min-width: 0; }
.ctx-section.ctx-account .user-session {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: row; align-items: baseline; gap: 6px;
  padding: 6px var(--space-3);
}
.ctx-section.ctx-account .user-panel-name { flex: 0 1 auto; min-width: 0; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ctx-section.ctx-account .user-panel-status, .ctx-section.ctx-account .user-panel-role { flex: 0 0 auto; font-size: 11px; white-space: nowrap; }
.ctx-section.ctx-account .user-panel-status::before, .ctx-section.ctx-account .user-panel-role::before {
  content: '·'; margin-right: 6px; color: var(--fg-muted);
}
.ctx-section.ctx-account .user-panel-role[hidden] { display: none; }
.ctx-section.ctx-account .user-logout { flex: 0 0 auto; padding-inline: var(--space-3); }
/* Live-Risiko-Regler (Legacy-Rueckbau): Regler + Zahlenfeld nebeneinander,
   mehrere Felder in einer umbrechenden Reihe wie in der alten .llrow. */
.lr-panel .panel-content { gap: var(--space-3); }
.lr-row { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); align-items: flex-end; }
.lr-field { display: flex; flex-direction: column; gap: 4px; flex: 1 1 190px; min-width: 160px; }
.lr-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-muted); }
.lr-inputs { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.lr-range { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.lr-num { flex: 0 0 74px; width: 74px; padding: 4px 6px; font-variant-numeric: tabular-nums;
  background: var(--surface-2); color: var(--text-primary); border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
.lr-motor-value { flex: 0 0 54px; text-align: right; font-size: 12px; font-weight: 700; }
.lr-actions { display: flex; justify-content: flex-end; }

/* ---- Motor-Steuerung (Legacy-Rückbau: Auto-Gate, Live-Freigabe, Motor, Boost) ---- */
.ec-root { display: flex; flex-direction: column; gap: var(--space-3); }
.ec-panel .panel-content { display: flex; flex-direction: column; gap: var(--space-3); }
.ec-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ec-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-muted); }
.ec-row { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.ec-row-check { cursor: pointer; }
.ec-range { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.ec-check { accent-color: var(--accent); width: 16px; height: 16px; }
.ec-value { flex: 0 0 auto; min-width: 78px; text-align: right; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ec-status { font-size: 11px; line-height: 1.4; overflow-wrap: anywhere; }
.ec-status.is-ok { color: var(--positive); }
.ec-status.is-err { color: var(--negative); }
.ec-status.is-busy { color: var(--warning); }
.ec-status.is-muted { color: var(--fg-muted); }
/* Gate-Raster: eine Zeile je Börse, eine Spalte je Gate — Kopfzeile beschriftet. */
.ec-gate-grid { display: grid; grid-template-columns: minmax(56px, auto) repeat(3, minmax(0, 1fr)); gap: 6px var(--space-2); align-items: center; }
.ec-gate-head { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-muted); text-align: center; }
.ec-gate-cell { display: flex; justify-content: center; }
.ctx-body { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.ctx-section { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
/* Ohne diese Zeile ueberstimmt die display:flex-Regel oben das hidden-Attribut
   und ein ausgeblendeter Abschnitt bliebe sichtbar (gemessen: 507 px hoch). */
.ctx-section[hidden] { display: none; }
.ctx-section-title { margin: 0; font-size: 11px; font-weight: 600; color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.ctx-filter-summary { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.ctx-filter-summary[hidden] { display: none; }
.ctx-filter-slot:empty { display: none; }
/* Globale Filter: EINE kompakte Reihe statt gestapelter Vollbreiten-Bloecke.
   Zeitraum und Linse stehen nebeneinander. Die Symbolsuche ist seit 05.08.2026
   im Kopf; ihre beiden Regeln hier sind damit entfallen. Die Beschriftungen
   bleiben ausgeschrieben (im Kopf sind sie nur fuer Screenreader da). */
.ctx-filter-slot .app-filters { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.ctx-filter-slot .app-filter { flex: 1 1 150px; min-width: 0; display: flex; align-items: center; gap: 6px; justify-content: flex-start; }
.ctx-filter-slot .app-select { flex: 1 1 auto; min-width: 0; }
.ctx-filter-slot .app-filter-label {
  position: static; width: auto; height: auto; clip: auto; overflow: visible;
  flex: 0 0 auto; font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-muted);
}
.ctx-live-slot .panel { max-width: none; }
.ctx-live-slot .live-control-body { grid-template-columns: minmax(0, 1fr); }
@media (prefers-reduced-motion: reduce) { .app-context { transition: none; } }

.live-balance-history { display: grid; gap: var(--space-3); margin-top: var(--space-4); min-width: 0; }
.live-balance-history h4 { margin: 0; font-size: 13px; }
.live-balance-series-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); min-width: 0; }
.live-balance-series { display: grid; gap: 4px; min-width: 0; padding: var(--space-3); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--surface-2); }
.live-balance-series-label, .live-balance-single-point { color: var(--text-muted); font-size: 11px; }
.live-balance-series .spark { width: 100%; max-width: 100%; }
.live-balance-table-fallback summary { cursor: pointer; color: var(--text-secondary); font-size: 12px; }

/* Benutzer/Sitzung ist der letzte Abschnitt desselben Kontextdialogs. */
.ctx-user { margin-top: auto; padding-top: var(--space-4); border-top: 1px solid var(--border-subtle); }
.user-session { display: grid; gap: 5px; padding: var(--space-4); background: var(--surface-2); border: 1px solid var(--border-subtle); border-radius: var(--radius); }
.user-panel-name { color: var(--text-primary); font-size: 16px; overflow-wrap: anywhere; }
.user-panel-status, .user-panel-role { color: var(--text-muted); font-size: 12px; }
.user-panel-status.is-active { color: var(--accent); }
.user-logout { align-self: stretch; min-height: 40px; }
@media (prefers-reduced-motion: reduce) { .app-choice-trigger::after { transition: none; } }

/* ---- Theme-Schalter (Einstellungen → Anzeige; NICHT mehr in der Kopfzeile) ---- */
.theme-toggle { display: inline-flex; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; }
.theme-opt { background: var(--surface-1); color: var(--text-secondary); border: 0; border-left: 1px solid var(--border-subtle); padding: 4px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.theme-opt:first-child { border-left: 0; }
.theme-opt:hover { background: var(--surface-interactive); color: var(--text-primary); }
.theme-opt.is-active { background: var(--accent-solid); color: var(--accent-text); font-weight: 600; }
.theme-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---- Reiter (Tabs) ---- */
.tabbed { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.tabbar {
  display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; min-width: 0;
  border-bottom: 1px solid var(--border-subtle); -webkit-overflow-scrolling: touch;
  /* 02.09.: Die Pillen sassen direkt auf der Trennlinie und wirkten dadurch
     angeklebt — vor allem die aktive mit ihrer vollen Fuellung. Der Abstand
     laesst die Leiste atmen, ohne die Linie zu verschieben. */
  padding-bottom: 10px;
}
.tabbar::-webkit-scrollbar { display: none; }
/* 27.07.: Die OBERSTE Reiterleiste eines Bereichs war eine reine Dopplung — die
   Seitenleiste listet dieselben Unterbereiche bereits als zweite Ebene. Auf
   Desktop wird sie deshalb ausgeblendet; VERSCHACHTELTE Reiterleisten (Reiter
   innerhalb eines Reiters) bleiben sichtbar, denn die stehen NICHT im Menü.
   Mobil bleibt sie sichtbar — dort ist die Seitenleiste eine Offcanvas. */
@media (min-width: 769px) {
  .app-main > .tabbed > .tabbar { display: none; }
}
/* Reiter als Pillen (Zielbild) statt Unterstrich-Reiter. */
.tab {
  background: transparent; border: 1px solid transparent; border-radius: 999px;
  color: var(--text-secondary);
  padding: 7px 14px; font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
  white-space: nowrap; flex: 0 0 auto;
}
.tab:hover { background: var(--surface-interactive); color: var(--text-primary); }
.tab.is-active { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--accent-text); font-weight: 600; }
/* Fokusring innen (der Reiterstreifen scrollt waagerecht und wuerde einen
   aeusseren Ring am Rand kappen); auf dem gefuellten Reiter waere Akzent auf
   Akzent unsichtbar, deshalb dort die Gegenfarbe. */
.tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; border-radius: 999px; }
.tab.is-active:focus-visible { outline-color: var(--accent-text); }
.tabpanel { min-width: 0; }
.tabpanel:focus { outline: none; }
.tabpanel > .area { margin: 0; }

/* ---- Panel-Hierarchie (§19; Türkis nur gezielt) ---- */
/* Der Schatten stand hier wirkungslos: das Elevation-System weiter unten setzt
   .panel { box-shadow: … } bei gleicher Spezifitaet und spaeter. Er wandert
   deshalb dorthin (zwei Klassen, damit er die Grundregel schlaegt). */
.panel--primary { border-color: var(--border-default); }
.panel--diagnostic { background: var(--canvas-subtle); border-style: dashed; }
.panel--warn { border-color: color-mix(in srgb, var(--warning) 45%, transparent); }
.panel--action { border-color: var(--accent-border); }

/* ---- Layout: KPI-Reihe + Panel-Grid ---- */
.area { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.kpi-row { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); }
.kpi-row-secondary { grid-template-columns: repeat(6, minmax(0, 1fr)); opacity: 0.95; }
.panel-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); align-items: start; }
/* Pflicht: die Basisregel setzt `display: grid` und schlaegt sonst das
   UA-`[hidden] { display: none }`. Ohne diese Zeile blieb die per `hidden`
   weggeschaltete Ebene im Fluss — auf „Intelligence → Weltkarte" stand die
   Wirtschaftskalender-Karte deshalb dauerhaft UNTER der Ereignis-Karte, sobald
   der Unterreiter einmal geoeffnet worden war (Betreiber-Meldung 13.08.2026).
   Gleiches Muster wie bei .app-authbar, .seg und .performance-filter-active. */
.panel-grid[hidden] { display: none; }
.panel-grid > .panel { width: 100%; }
/* 0.5.67 — KINDSELEKTOR statt Nachfahre. `.panel-grid .span-2` traf auch das
   Hauptpanel INNERHALB der Performance-Surface und zwang deren implizites
   Raster in zwei Spalten: die Filterleiste landete in einer Phantom-Spalte
   und kollabierte je nach Inhalt bis auf ~272 px (Betreiber-Screenshot
   24.08., Validation-Linse) — die eigentliche Filterleisten-Reparatur vom
   13.08. war damit unsichtbar. */
.panel-grid > .span-2 { grid-column: span 2; }
/* 0.5.67 — ein alleinstehendes letztes Panel fuellt die Reihe, statt eine
   leere rechte Haelfte zu hinterlassen (Betreiber: „auf Desktop alles auf
   die gesamte Breite"). Trifft exakt das ungerade Schlusselement des
   Zweispalters; volle Reihen bleiben unveraendert. */
.panel-grid > .panel:last-child:nth-child(odd) { grid-column: 1 / -1; }
/* 0.5.67 — EXPLIZIT einspaltig. Das Raster war implizit; jede versehentlich
   zutreffende span-Regel eines Kindes erzeugte Phantom-Spalten. Filter oben
   in voller Breite, Hauptinhalt darunter in voller Breite. */
.performance-surface { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); min-width: 0; }
.performance-surface > * { grid-column: 1 / -1; }
.performance-filter-bar { max-width: none; }
/* VOLLE BREITE statt Inhaltsbreite (Betreiber-Meldung 13.08.2026). Die zehn
   Felder lagen als Flex-Kette mit 128–220 px Breite links an; rechts blieb eine
   leere Spur, auf dem Telefon passten genau zwei Felder je Zeile. Als
   auto-fit-Raster teilen sie die verfuegbare Breite gleichmaessig auf und
   brauchen dafuer keinen einzigen zusaetzlichen Breakpoint.
   Die Klasse `chip-row` traegt der Container bewusst NICHT mehr: sie steht
   weiter unten im Stylesheet bei gleicher Spezifitaet und ihr `gap: 4px` /
   `align-items: center` gewann bisher gegen die Absicht dieser Regel. */
.performance-filter-controls {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: var(--space-3); align-items: end; margin-bottom: var(--space-3);
}
.performance-filter-bar .app-filter { flex-direction: column; align-items: stretch; gap: 4px; min-width: 0; white-space: normal; }
.performance-filter-bar .app-filter-label {
  position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: nowrap;
}
.performance-filter-bar .app-select { width: 100%; min-width: 0; max-width: none; }
.performance-filter-bar .performance-filter-footer {
  justify-content: space-between; align-items: center; gap: var(--space-3);
  margin: 0; padding-top: var(--space-3); border-top: 1px solid var(--border-subtle);
}
.performance-filter-active[hidden] { display: none; }
/* Aktive Filter als entfernbare Chips. `.app-filter-chip` ist global auf
   `display: none` gesetzt (das ist die Kurzfassung in der Kopfzeile) — ohne
   diese Gegenregel blieb die Zeile leer, obwohl der Container korrekt aufging. */
.performance-filter-active .app-filter-chip { display: inline-flex; }
@media (max-width: 420px) { .performance-filter-controls { grid-template-columns: minmax(0, 1fr); } }
.performance-main { display: grid; gap: var(--space-3); min-width: 0; }
.performance-mode-controls { overflow-x: auto; padding-bottom: 2px; scrollbar-width: thin; }
.performance-mode-controls .seg { min-width: max-content; }
.performance-main-content { display: grid; gap: var(--space-3); min-width: 0; }
.stat-list.performance-summary-list {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: auto auto;
  grid-auto-flow: column; gap: 0 var(--space-2);
}
.stat-list.performance-summary-list dt,
.stat-list.performance-summary-list dd { background: var(--surface-1); border-inline: 1px solid var(--border-subtle); padding-inline: 9px; min-width: 0; }
.stat-list.performance-summary-list dt { padding-top: 6px; border-top: 1px solid var(--border-subtle); border-radius: var(--radius-sm) var(--radius-sm) 0 0; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
.stat-list.performance-summary-list dd { padding-bottom: 7px; border-bottom: 1px solid var(--border-subtle); border-radius: 0 0 var(--radius-sm) var(--radius-sm); text-align: left; }
.stat-list.performance-summary-list .stat-value { font-size: 14px; font-weight: 700; }
.stat-list.performance-detail-list { grid-template-columns: repeat(4, minmax(90px, auto) minmax(0, 1fr)); gap: 5px var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--border-subtle); }
.stat-list.performance-detail-list dt { font-size: 11px; }
.stat-list.performance-detail-list dd { min-width: 0; text-align: left; overflow-wrap: anywhere; }
.performance-export-actions { justify-content: flex-end; margin-top: 0; padding-top: var(--space-2); border-top: 1px solid var(--border-subtle); }
.performance-main .chart { min-height: 300px; }
.evaluation-trade-flow { border-color: var(--border-default); }
.evaluation-trade-flow .panel-content { min-width: 0; }
.eval-flow-stack { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; }
.eval-flow-headline { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; flex-wrap: wrap; }
.eval-flow-trades { color: var(--text-primary); font-size: 24px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.eval-flow-context { color: var(--text-secondary); font-size: 12px; }
.eval-flow-stack > .seg { justify-self: end; }
.eval-flow-stack > .chart, .eval-flow-footer, .eval-flow-stack > .ui-state-note { grid-column: 1 / -1; }
.eval-flow-stack > .chart { min-height: 300px; }
.eval-flow-footer .stat-list { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-template-rows: auto auto; grid-auto-flow: column; gap: 0 var(--space-2); }
.eval-flow-footer dt, .eval-flow-footer dd { min-width: 0; padding-inline: 9px; background: var(--surface-1); border-inline: 1px solid var(--border-subtle); }
.eval-flow-footer dt { padding-top: 6px; border-top: 1px solid var(--border-subtle); border-radius: var(--radius-sm) var(--radius-sm) 0 0; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
.eval-flow-footer dd { padding-bottom: 7px; border-bottom: 1px solid var(--border-subtle); border-radius: 0 0 var(--radius-sm) var(--radius-sm); text-align: left; }
@media (max-width: 1200px) {
  .stat-list.performance-summary-list { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: repeat(4, auto); grid-auto-flow: column; }
  .stat-list.performance-detail-list { grid-template-columns: repeat(2, minmax(90px, auto) minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .stat-list.performance-summary-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(8, auto); }
  .stat-list.performance-detail-list { grid-template-columns: minmax(90px, auto) minmax(0, 1fr); }
  .performance-main .chart { min-height: 240px; }
  .eval-flow-stack { grid-template-columns: minmax(0, 1fr); }
  .eval-flow-stack > .seg { justify-self: stretch; overflow-x: auto; }
  .eval-flow-stack > .chart, .eval-flow-footer, .eval-flow-stack > .ui-state-note { grid-column: 1; }
  .eval-flow-footer .stat-list { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(6, auto); }
}

/* ---- KPI-Karte (0.5.36 Mission-Control-Look) ----
   Aufbau wie im Entwurf: Icon-Kachel links, Textblock rechts. Der farbige
   2-px-Streifen am linken Rand entfällt — die Karte selbst trägt jetzt die
   Zustandsfarbe (Rahmen + Kachel + dezenter Randschein). Ohne `tone` bleibt sie
   neutral; Farbe ist nie das einzige Signal, der Wert steht immer daneben. */
.kpi-card {
  background-color: var(--surface-1); background-image: var(--card-sheen);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: 14px; box-shadow: var(--card-edge); min-width: 0;
}
.kpi-card.has-icon { display: flex; align-items: flex-start; gap: var(--space-3); }
.kpi-body { min-width: 0; flex: 1; }
.kpi-icon {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px;
  color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-border);
}
.ui-icon { display: block; }
.kpi-label { font-size: 12px; color: var(--fg-muted); text-decoration: none; border: 0; cursor: help; }
abbr.kpi-label[title] { text-decoration: underline dotted var(--border); text-underline-offset: 3px; }
.kpi-value { font-size: 25px; font-weight: 700; margin-top: 3px; line-height: 1.12; letter-spacing: -0.015em; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.kpi-change { display: flex; align-items: baseline; gap: 4px; font-size: 12px; margin-top: 4px; }
.kpi-change-text { color: var(--fg-muted); }
.kpi-age { font-size: 11px; color: var(--fg-dim); margin-top: 6px; }
/* Die Sparkline hatte eine feste 96-px-Breite und stand dadurch als kurzer Strich
   am linken Rand einer mehrere hundert Pixel breiten Karte — der Rest blieb leer
   (Betreiber-Meldung 13.08.2026: „rechts ist alles frei"). Das SVG hat
   `preserveAspectRatio="none"`, es füllt die Breite also ohne Verzerrung der
   Höhe; nur die Breitenregel fehlte. */
.kpi-spark { margin-top: 8px; height: 28px; }
.kpi-spark .spark { width: 100%; }
.kpi-status-text { font-size: 16px; font-weight: 600; }
.kpi-card.is-skeleton .kpi-value { color: transparent; background: var(--bg-elev-2); border-radius: 4px; }

/* Zustandsfarben. `--glow-strength` ist im Hellmodus 0 → dieselben Regeln
   erzeugen dort nur den Rahmen, kein Leuchten. */
.kpi-card.tone-accent   { --kpi-tone: var(--accent); }
.kpi-card.tone-positive { --kpi-tone: var(--positive); }
.kpi-card.tone-negative { --kpi-tone: var(--negative); }
.kpi-card.tone-warning  { --kpi-tone: var(--warning); }
.kpi-card.tone-observe  { --kpi-tone: var(--observe); }
.kpi-card.tone-neutral  { --kpi-tone: var(--neutral); }
.kpi-card[class*="tone-"] {
  border-color: color-mix(in srgb, var(--kpi-tone) 46%, var(--border-subtle));
  background-image: var(--card-sheen), linear-gradient(150deg, color-mix(in srgb, var(--kpi-tone) 9%, transparent), transparent 58%);
  box-shadow: var(--card-edge), 0 6px 22px color-mix(in srgb, var(--kpi-tone) calc(var(--glow-strength) * 34%), transparent);
}
.kpi-card[class*="tone-"] .kpi-icon {
  color: var(--kpi-tone);
  background: color-mix(in srgb, var(--kpi-tone) 14%, transparent);
  border-color: color-mix(in srgb, var(--kpi-tone) 42%, transparent);
}
.kpi-card[class*="tone-"] .kpi-value { color: var(--kpi-tone); }
.kpi-card.tone-neutral .kpi-value { color: var(--text-primary); }

/* ---- Panel ---- */
.panel {
  display: flex; flex-direction: column;
  background-color: var(--bg-elev); background-image: var(--card-sheen);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: 14px; min-width: 0; position: relative;
  /* KEIN `box-shadow` hier: das Elevation-System weiter unten in dieser Datei
     fuehrt ihn fuer alle vier Stufen (inkl. `--card-edge`) und wuerde eine
     Angabe an dieser Stelle ohnehin ueberschreiben. */
}
.panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }
.panel-title { margin: 0; font-size: 14px; font-weight: 650; letter-spacing: -0.005em; }
abbr.panel-title[title] { text-decoration: underline dotted var(--border); text-underline-offset: 3px; cursor: help; }
.panel-subtitle { font-size: 12px; color: var(--fg-muted); margin-top: 2px; }
.panel-badges { display: flex; gap: 4px; flex-wrap: wrap; }
/* Zeitraum-Streifen im Panel-Kopf. Der Wrapper haelt Streifen UND Badges als EIN
   rechtes Kind zusammen — ein drittes direktes Kind wuerde die Badges bei
   `justify-content: space-between` aus der rechten Kante in die Mitte ziehen. */
.panel-head-side { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.panel-head-controls { overflow-x: auto; scrollbar-width: none; }
.panel-head-controls .seg { min-width: max-content; }
.panel-stand { font-size: 11px; color: var(--fg-dim); margin: 2px 0 var(--space-3); }
.panel-content { flex: 1; min-width: 0; }
.panel-overlay { position: relative; }
.panel-overlay[hidden] { display: none; }
.app-panel-title { margin: 0 0 var(--space-2); font-size: 16px; }
.app-panel-note { margin: 0; color: var(--fg-muted); }

/* ---- Zustände ---- */
.ui-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ui-state { padding: var(--space-4) 0; }
.ui-state-title { font-weight: 600; margin-bottom: 2px; }
.ui-state-note { color: var(--fg-muted); font-size: 13px; }
.ui-skel { height: 12px; margin: 8px 0; border-radius: 4px; background: linear-gradient(90deg, var(--bg-elev-2), var(--border-soft), var(--bg-elev-2)); background-size: 200% 100%; animation: ui-shimmer 1.4s ease-in-out infinite; }
.ui-skel:nth-child(3) { width: 70%; } .ui-skel:nth-child(4) { width: 85%; }
@keyframes ui-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .ui-skel { animation: none; } }
.ui-error .ui-state-title { color: var(--err); }
.ui-btn { background: var(--bg-elev-2); color: var(--fg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 4px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.ui-btn:hover { background: var(--border-soft); }
.ui-btn:disabled { opacity: 0.5; cursor: default; }
.ui-btn-retry { margin-top: var(--space-2); }
/* 09.08.: `white-space: nowrap` — „Teildaten · 4" brach im schmalen Panel-Kopf
   auf ZWEI Zeilen um und wurde dadurch doppelt so hoch wie der Rest der Zeile.
   Das war der eigentliche Grund für die Klobigkeit, nicht die Polsterung. */
.ui-badge { font-size: 11px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border); white-space: nowrap; }
.ui-badge-stale { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.ui-badge-partial { color: var(--fg-muted); }
.ui-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; margin-right: 6px; vertical-align: middle; background: var(--fg-dim); }
.ui-dot.ok { background: var(--ok); } .ui-dot.warn { background: var(--warn); } .ui-dot.err { background: var(--err); } .ui-dot.neutral { background: var(--fg-dim); }

/* ---- Trend-Farben (immer mit Text/Pfeil, nie Farbe allein — a11y §15) ---- */
.is-up, .is-up .stat-value, .kpi-change.is-up { color: var(--ok); }
.is-down, .is-down .stat-value, .kpi-change.is-down { color: var(--err); }
.is-flat, .kpi-change.is-flat { color: var(--fg-muted); }

/* ---- Kennzahlen-Liste ---- */
.stat-list { display: grid; grid-template-columns: minmax(110px, 200px) minmax(0, 1fr); gap: 6px var(--space-3); margin: 0; }
.stat-list dt { color: var(--fg-muted); font-size: 13px; }
/* Kontenschluessel, Commit- und Config-Hashes sind EIN Token ohne Umbruchstelle.
   Ohne overflow-wrap sprengt ihre min-content-Breite die 1fr-Spalte und damit den
   Scrollcontainer der rechten Offcanvas (gemessen: 214 px Ueberlauf bei 390 px
   Viewport). `anywhere` bricht sie um, statt sie rechts abzuschneiden. */
.stat-list dd { margin: 0; text-align: left; font-variant-numeric: tabular-nums; min-width: 0; overflow-wrap: anywhere; }
.stat-value { font-weight: 600; }
.stat-sub { display: block; font-size: 11px; color: var(--fg-dim); font-weight: 400; }

/* SCHMALE KARTEN — Werte brachen ZEICHENWEISE um (Betreiber-Screenshots 12.08.2026).
   Betroffen: "Go-Live-Reifegrad je Börse" (.rd-card, Raster ab 210 px),
   "Champion & Challenger je Komponente" (.mini-card, ab 230 px) und
   "Strategie-Karten (wirksame Instanzen)" (.strat-card, ab 240 px). Dort stand
   "0,00 R" als Buchstabensäule, und JSON-Werte wie ["backtest","paper","live"]
   zerfielen über ein Dutzend Zeilen.
   URSACHE ist das Zusammenspiel zweier je für sich richtiger Regeln: Die
   Beschriftungsspalte oben darf bis 200 px wachsen, und lange Beschriftungen
   ("Σ R (KI-Kohorte)", "Challenger · v2-2026-08-11T15-24-19", "Blockierte Regime")
   schöpfen das aus. Abzüglich Polsterung und Spalten-Lücke bleibt der Wertspalte
   dann fast nichts — und das direkt darüber BEWUSST gesetzte
   `overflow-wrap: anywhere` bricht dann Zeichen für Zeichen um.
   `anywhere` bleibt: es verhindert den dort dokumentierten 214-px-Überlauf der
   mobilen Seitenleiste. Stattdessen entfällt in schmalen Karten die zweite
   Spalte — Beschriftung ÜBER den Wert, der bekommt die volle Kartenbreite.
   CONTAINER-Abfrage statt Media-Abfrage, weil die KARTENBREITE das Problem ist,
   nicht die Fensterbreite: dieselbe Karte ist im Zwei-Spalten-Panel schmal und
   im vollbreiten Panel weit — ein Fensterschwellwert träfe beide gleich falsch.
   Ohne @container-Unterstützung bleibt es unverändert beim bisherigen Verhalten. */
.rd-card, .mini-card, .strat-card { container-type: inline-size; }
@container (max-width: 360px) {
  .stat-list { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .stat-list dt { font-size: 11px; line-height: 1.35; }
  .stat-list dd { margin-bottom: 6px; }
  .stat-list dd:last-of-type { margin-bottom: 0; }
}
.exit-list { margin-top: var(--space-4); border-top: 1px solid var(--border-soft); padding-top: var(--space-3); }

/* ---- Charts ---- */
.chart { position: relative; }
.chart-figure { position: relative; width: 100%; }
.chart-svg { width: 100%; display: block; }
.chart-grid { stroke: var(--border-soft); stroke-width: 1; }
.chart-zero { stroke: var(--border); stroke-width: 1; }
/* --text-secondary statt --fg-dim (= --text-muted): letzteres erreicht auf der
   Panelflaeche nur 4,1:1 und verfehlt AA fuer Kleintext. Achsenbeschriftungen
   sind kein Beiwerk — sie tragen den Massstab. */
.chart-axis-label { fill: var(--text-secondary); font-size: 10px; }
/* Wertbeschriftung am Balkenende (opt-in via showValues): der Messwert selbst
   darf kraeftiger stehen als die Achsenbeschriftung daneben. */
.chart-bar-value { fill: var(--text-primary); font-size: 11px; font-variant-numeric: tabular-nums; }
.chart-axis-title { fill: var(--fg-muted); font-size: 11px; }
/* RSI-Unterflaeche im Kerzen-Chart (opt-in ueber den Drawer-Schalter). */
.chart-rsi-line { stroke: var(--accent); fill: none; stroke-width: 1.5; }
.chart-rsi-guide { stroke: var(--border-soft); stroke-dasharray: 3 3; }
/* 0.5.37: `.chart-rsi-label` hatte NIE eine Regel — die Marken 30/50/70 und die
   Beschriftung "RSI(14)" fielen auf die SVG-Vorgabe `fill: black` zurueck und
   waren auf dunklem Grund unsichtbar. Gleiche Stufe wie `.chart-vol-label`.
   candles.ts setzt an diesen Texten weder fill noch font-size — kein Konflikt
   zwischen CSS und Praesentationsattribut. */
.chart-rsi-label { fill: var(--fg-dim); font-size: 10px; font-variant-numeric: tabular-nums; }
/* Volumen-Unterflaeche im Kerzen-Chart (opt-in ueber den Drawer-Schalter).
   Balken bewusst gedaempft: die Menge ist Beiwerk zum Kursverlauf, nicht dessen
   Konkurrenz. Richtungsfarbe wie bei den Kerzen darueber. */
.chart-vol-bar { fill: color-mix(in srgb, var(--accent) 45%, transparent); }
.chart-vol-bar.is-up { fill: color-mix(in srgb, var(--ok) 45%, transparent); }
.chart-vol-bar.is-down { fill: color-mix(in srgb, var(--err) 45%, transparent); }
.chart-vol-guide { stroke: var(--border-soft); }
.chart-vol-label { fill: var(--fg-dim); font-size: 10px; }
/* 0.5.36: dezenter Schein auf der Linie. `--chart-line-glow` ist im Hellmodus 0px,
   dort bleibt exakt dieselbe Regel wirkungslos — kein zweiter Regelsatz noetig. */
.chart-line { stroke: var(--accent); filter: drop-shadow(0 0 var(--chart-line-glow) color-mix(in srgb, var(--accent) calc(var(--glow-strength) * 100%), transparent)); }
.chart-line.series-1 { stroke: var(--warn); filter: none; } .chart-line.series-2 { stroke: var(--ok); filter: none; }
/* KEIN `fill` hier: die Flaeche traegt `fill="url(#…)"` als Praesentationsattribut,
   jede CSS-Deklaration wuerde den Verlauf wieder ueberschreiben (lineArea.ts). */
.chart-grad .chart-grad-top { stop-color: var(--accent); stop-opacity: 0.34; }
.chart-grad .chart-grad-bottom { stop-color: var(--accent); stop-opacity: 0.015; }
.chart-grad.series-1 .chart-grad-top { stop-color: var(--warn); stop-opacity: 0.28; }
.chart-grad.series-1 .chart-grad-bottom { stop-color: var(--warn); stop-opacity: 0.015; }
.chart-grad.series-2 .chart-grad-top { stop-color: var(--ok); stop-opacity: 0.28; }
.chart-grad.series-2 .chart-grad-bottom { stop-color: var(--ok); stop-opacity: 0.015; }
.chart-bar { fill: var(--accent); }
.chart-bar.is-up { fill: var(--ok); } .chart-bar.is-down { fill: var(--err); } .chart-bar.is-neutral { fill: var(--accent); }
.chart-point { fill: var(--accent); opacity: 0.75; }
.chart-point.is-up { fill: var(--ok); } .chart-point.is-down { fill: var(--err); }
.chart-guide { stroke: var(--border); stroke-dasharray: 3 3; }
.chart-dot { fill: var(--accent); stroke: var(--bg-elev); stroke-width: 1.5; }
.chart-dot.series-1 { fill: var(--warn); } .chart-dot.series-2 { fill: var(--ok); }
.chart-capture { cursor: crosshair; }
.chart-tip { position: absolute; pointer-events: none; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 8px; font-size: 11px; box-shadow: var(--shadow); transform: translate(8px, -50%); z-index: 5; white-space: nowrap; }
.chart-tip-head { font-weight: 600; margin-bottom: 2px; }
.chart-actions { text-align: right; margin-top: 4px; }
.chart-table-toggle { background: none; border: 0; color: var(--fg-dim); font-size: 11px; cursor: pointer; text-decoration: underline; }
.chart-datatable, .data-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.chart-datatable th, .chart-datatable td { padding: 3px 6px; border-bottom: 1px solid var(--border-soft); text-align: right; font-variant-numeric: tabular-nums; }
.chart-table { overflow-x: auto; max-height: 260px; overflow-y: auto; }
.spark { display: block; overflow: visible; }
/* 0.5.37: Die Sparkline wird auf 100 % Breite gedehnt (.kpi-spark .spark,
   .live-balance-series .spark), ihre viewBox ist aber nur 96 Einheiten breit und
   `preserveAspectRatio` steht auf `none` (sparkline.ts:25): der Strich wurde in X
   um denselben Faktor mitgedehnt — in einer 300-px-Karte gut 3x, senkrechte
   Abschnitte also ~4,7 px dick, waagerechte 1,5 px. `non-scaling-stroke` rechnet
   die Strichstaerke erst im Geraeteraum aus und haelt sie ueberall bei 1,5 px. */
.spark-line { stroke: var(--accent); vector-effect: non-scaling-stroke; }
.spark-line.is-up { stroke: var(--ok); } .spark-line.is-down { stroke: var(--err); }
/* Verlaufsfuellung unter der Sparkline (Zielbild). KEIN `fill` fuer `.spark-area`:
   die Flaeche traegt `fill="url(#…)"` als Praesentationsattribut, jede
   CSS-Deklaration wuerde den Verlauf ueberschreiben (gleiche Falle wie
   `.chart-area`, app.css:870). */
.spark-grad .spark-grad-top { stop-color: var(--accent); stop-opacity: 0.30; }
.spark-grad .spark-grad-bottom { stop-color: var(--accent); stop-opacity: 0.02; }
.spark-grad.is-up .spark-grad-top { stop-color: var(--ok); stop-opacity: 0.30; }
.spark-grad.is-up .spark-grad-bottom { stop-color: var(--ok); stop-opacity: 0.02; }
.spark-grad.is-down .spark-grad-top { stop-color: var(--err); stop-opacity: 0.26; }
.spark-grad.is-down .spark-grad-bottom { stop-color: var(--err); stop-opacity: 0.02; }

/* ---- Kerzen-Chart (§20 B3b) — Tokens, keine Glows ---- */
/* 0.5.37 Zielbild "kraeftige Koerper, duenne Dochte": der Koerper traegt die
   Richtungsfarbe VOLL (vorher 70 % transparent = ausgewaschen ueber der
   Panelflaeche), der Docht tritt als gedaempfte Haarlinie zurueck.
   KEIN Rahmen mehr am Koerper: bei dichten Reihen ist er nur 1-2 px breit
   (candles.ts:189, w = Breite/Anzahl * 0.68); ein zentrierter 1-px-Rahmen
   verbreiterte ihn dort um bis zu 100 % und liess Nachbarkerzen verschmelzen.
   Der Doji bleibt sichtbar: die Geometrie klemmt die Koerperhoehe auf min. 1 px
   (candles.ts:195) — 1 px Vollton statt 1 px 70-%-Ton.
   candles.ts:293-297 setzt an Koerper und Docht KEIN fill/stroke/stroke-width
   als Attribut, das CSS ist also allein zustaendig. */
.chart-candle.is-up { fill: var(--ok); stroke: none; }
.chart-candle.is-down { fill: var(--err); stroke: none; }
.chart-candle-wick.is-up { stroke: color-mix(in srgb, var(--ok) 78%, transparent); stroke-width: 1; }
.chart-candle-wick.is-down { stroke: color-mix(in srgb, var(--err) 78%, transparent); stroke-width: 1; }
.chart-ovl { stroke-dasharray: 4 3; stroke-width: 1; }
.chart-ovl.ovl-entry { stroke: var(--accent); }
.chart-ovl.ovl-stop { stroke: var(--err); }
.chart-ovl.ovl-stop-initial { stroke: var(--err); opacity: 0.45; }
.chart-ovl.ovl-tp { stroke: var(--ok); }
.chart-ovl.ovl-neutral { stroke: var(--border); }
.chart-ovl-label { font-size: 9px; fill: var(--fg-muted); }
.chart-ovl-label.ovl-stop { fill: var(--err); }
.chart-ovl-label.ovl-tp { fill: var(--ok); }
.chart-ovl-label.ovl-entry { fill: var(--accent); }
.chart-marker-line { stroke-width: 1; stroke-dasharray: 2 3; opacity: 0.72; }
.chart-marker-dot { stroke: var(--bg); stroke-width: 1.5; }
.chart-marker-label { font-size: 9px; font-weight: 650; }
.chart-marker-line.marker-entry, .chart-marker-dot.marker-entry { stroke: var(--accent); fill: var(--accent); }
.chart-marker-label.marker-entry { fill: var(--accent); }
.chart-marker-line.marker-exit, .chart-marker-dot.marker-exit { stroke: var(--warn); fill: var(--warn); }
.chart-marker-label.marker-exit { fill: var(--warn); }
.chart-marker-line.marker-signal, .chart-marker-dot.marker-signal { stroke: var(--fg-muted); fill: var(--fg-muted); }
.chart-marker-label.marker-signal { fill: var(--fg-muted); }

/* ---- Symbol-Drawer / Position-Explorer (§20 B3b) ---- */
.drawer-backdrop { position: fixed; inset: 0; z-index: 35; background: var(--backdrop); display: flex; justify-content: flex-end; }
.drawer { width: min(560px, 100%); height: 100%; overflow-y: auto; background: var(--bg); border-left: 1px solid var(--border); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
.drawer.is-fullscreen { width: 100%; max-width: none; border-left: 0; }
.drawer.is-fullscreen .drawer-chart .chart-svg { min-height: min(68vh, 720px); }
.drawer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.drawer-head-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: flex-end; }
.drawer-titlewrap { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.drawer-title { margin: 0; font-size: 16px; }
.drawer-tfs { display: flex; gap: 4px; flex-wrap: wrap; }
.tf-btn { padding: 2px 8px; font-size: 11px; }
.tf-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 20%, transparent); border-color: var(--accent); }
.drawer-section-title { margin: var(--space-2) 0 var(--space-1); font-size: 12px; color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.data-table tr.is-clickable { cursor: pointer; }
.data-table tr.is-clickable:hover td, .data-table tr.is-clickable:focus-visible td { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.chip-row { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: var(--space-2); }
.chip-btn { padding: 2px 8px; font-size: 11px; }
.chip-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 20%, transparent); border-color: var(--accent); }
.market-tools { display: flex; gap: var(--space-2); align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.market-search { max-width: 200px; }
.cursor-more { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }

/* ---- Treemap ---- */
/* Kachel = getoente Flaeche + Farbkante aus DERSELBEN Quelle, nicht Vollfarbe.
   Grund: Vollfarbe zwingt die Schrift auf --text-inverse, und das ist im
   Hellmodus weiss auf --chart-1 = 3,3:1 (durchgefallen). Mit der Toenung traegt
   --text-primary in BEIDEN Themes.
   Der Vorgabewert faengt ausserdem Kuerzel ohne eigene Reihenklasse ab: der
   Narrativ-Cluster liefert die Klasse is-flat, fuer die es keine Regel gab —
   diese Kacheln liefen auf SVG-Schwarz. */
.tree-cell {
  --tree-color: var(--neutral);
  fill: color-mix(in srgb, var(--tree-color) 45%, var(--surface-2));
  stroke: color-mix(in srgb, var(--tree-color) 80%, transparent); stroke-width: 1;
}
.tree-cell.series-0 { --tree-color: var(--chart-1); } .tree-cell.series-1 { --tree-color: var(--chart-2); } .tree-cell.series-2 { --tree-color: var(--chart-3); }
.tree-cell.series-3 { --tree-color: var(--chart-4); } .tree-cell.series-4 { --tree-color: var(--chart-6); } .tree-cell.series-5 { --tree-color: var(--chart-7); }
.tree-cell.series-6 { --tree-color: var(--chart-8); } .tree-cell.series-7 { --tree-color: var(--neutral); }
.tree-label { fill: var(--text-primary); font-size: 11px; font-weight: 600; pointer-events: none; }
.tree-value { fill: var(--text-primary); font-size: 10px; opacity: 0.85; pointer-events: none; }

/* ---- Gauge / Tacho ---- */
.gauge-track { stroke: var(--surface-3); }
.gauge-zone.is-up { stroke: color-mix(in srgb, var(--positive) 55%, transparent); }
.gauge-zone.is-down { stroke: color-mix(in srgb, var(--negative) 55%, transparent); }
.gauge-zone.is-flat { stroke: color-mix(in srgb, var(--neutral) 45%, transparent); }
/* Wertbogen (0.5.36): gefuellter Verlauf bis zum Messwert, Farbe = die Zone, in
   der der Wert liegt. Volle Deckkraft, damit er sich vom Zonenstreifen abhebt. */
.gauge-fill { stroke: var(--accent); }
.gauge-fill.is-up { stroke: var(--positive); }
.gauge-fill.is-down { stroke: var(--negative); }
.gauge-fill.is-flat { stroke: var(--neutral); }
.gauge-needle { stroke: var(--text-primary); }
.gauge-hub { fill: var(--text-primary); }
/* KEIN `font-size` hier: der Renderer setzt ihn als Attribut, damit die Schrift
   mit dem Tacho waechst — eine CSS-Deklaration schluege das Attribut. */
.gauge-value { fill: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums; }
.gauge-subtitle { fill: var(--text-muted); }

/* ---- Gauge-Grid + Segment-Umschalter (Intelligence) ---- */
.gauge-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); }
.gauge-cell { text-align: center; }
.gauge-cell-label { font-size: 12px; color: var(--text-secondary); font-weight: 600; margin-bottom: 2px; }
/* Pillengruppe (Zielbild) statt eckigem Kasten mit Trennstrichen. */
.seg {
  display: inline-flex; gap: 2px; padding: 1px;
  background: var(--surface-2); border: 1px solid var(--border-subtle);
  border-radius: 999px; overflow: hidden;
}
/* 09.08.: kompakter — vorher 4px/12px bei 12px Schrift. Die Umschalter im
   Chart (Zeitraum, Kontostand/Netto-PnL/…) dominierten die Panel-Köpfe.
   Diese Betreiber-Vorgabe gilt weiter: die Pillenform von 0.5.36 aendert die
   FORM, nicht die Groesse. Polsterung und Schriftgrad bleiben dort, wo
   test/dashboardKompakteSchalter sie festhaelt — die Form wurde an die Vorgabe
   angepasst, nicht der Test an die Form. */
.seg-btn { background: transparent; color: var(--text-secondary); border: 0; border-radius: 999px; padding: 3px 9px; font: inherit; font-size: 11px; cursor: pointer; }
.seg-btn:hover { background: var(--surface-interactive); color: var(--text-primary); }
.seg-btn.is-active { background: var(--accent-solid); color: var(--accent-text); font-weight: 600; }
.seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* BARRIEREFREIHEITSFEHLER behoben: das aktive Feld ist mit `--accent` gefuellt,
   der Fokusring war ebenfalls `--accent` — Kontrast 1:1, der Tastaturfokus war
   dort unsichtbar. Gegenfarbe. Gleiches Problem beim Theme-Umschalter. */
.seg-btn.is-active:focus-visible { outline-color: var(--accent-text); }
.theme-opt.is-active:focus-visible { outline-color: var(--accent-text); }
@media (max-width: 720px) { .gauge-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 460px) { .gauge-grid { grid-template-columns: minmax(0, 1fr); } }

/* ---- §7 Visual-Parity: Risiko-Dial mit Detailspalte, Wache-/Limit-Detailblöcke ---- */
.risk-score-wrap { display: grid; grid-template-columns: minmax(160px, 260px) 1fr; gap: var(--space-3); align-items: center; }
.risk-score-detail { min-width: 0; }
.guard-detail, .limit-box { margin-top: var(--space-3); }
.md-charts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); margin-top: var(--space-3); }
.md-cell { min-width: 0; }
.md-cell-label { font-size: 12px; color: var(--text-secondary); font-weight: 600; margin-bottom: 2px; }
@media (max-width: 720px) { .md-charts { grid-template-columns: minmax(0, 1fr); } }

/* ---- §7 Visual-Parity: Go-Live-Reifegrad als Karten mit Kriterienliste ---- */
.rd-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-3); }
.rd-card { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); background: var(--surface-1); }
.rd-card.is-ready { border-color: color-mix(in srgb, var(--positive) 45%, var(--border-subtle)); }
.rd-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); }
.rd-venue { font-weight: 700; letter-spacing: 0.02em; }
.rd-gross { margin: 0 0 var(--space-2); }
.rd-crit { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.rd-crit-item { display: flex; align-items: baseline; gap: var(--space-2); font-size: 12px; color: var(--text-secondary); }
.rd-crit-mark { font-weight: 700; width: 1em; }
.rd-crit-item.is-up .rd-crit-mark { color: var(--positive); }
.rd-crit-item.is-down .rd-crit-mark { color: var(--negative); }
.rd-foot { margin-top: var(--space-2); font-size: 11px; color: var(--text-muted); }

/* ---- §7 Visual-Parity: rekonstruierte LIVE-Statistik-Diagramme (Futures) ---- */
.lv-charts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); margin: var(--space-3) 0; }
.lv-cell { min-width: 0; }
.lv-cell-label { font-size: 12px; color: var(--text-secondary); font-weight: 600; margin-bottom: 2px; }
@media (max-width: 1100px) { .lv-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .lv-charts { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) { .risk-score-wrap { grid-template-columns: minmax(0, 1fr); } }

/* ---- Chip-Zeilen (§19 Phase 4): Klassen-/Fenster-/Indikator-Umschalter ---- */
.area-tools { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.chip-stack { display: flex; flex-direction: column; gap: var(--space-2); }
.chip-stack .seg { flex-wrap: wrap; align-self: flex-start; }

/* ---- Weltkarte (§17 Stufe 1): Blue-Marble-Basis + reale Ereignis-Regionen ---- */
.wmap-layout { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(220px, 1fr); gap: var(--space-3); align-items: start; }
@media (max-width: 900px) { .wmap-layout { grid-template-columns: minmax(0, 1fr); } }
.wmap { position: relative; border-radius: var(--radius-sm); overflow: hidden; background: var(--canvas-subtle); }
.wmap-img { display: block; width: 100%; height: auto; aspect-ratio: 2 / 1; filter: brightness(0.78) saturate(0.9); } /* Dark-Basis: Bild abdunkeln */
:root[data-theme="light"] .wmap-img { filter: none; }
@media (prefers-color-scheme: light) { :root:not([data-theme]) .wmap-img { filter: none; } }
.wmap-overlay { position: absolute; inset: 0; width: 100%; height: 100%; }
.wmap-controls { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.wmap-filter { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border-default); border-radius: var(--radius-sm); padding: 3px 8px; font: inherit; font-size: 12px; }
/* 0.5.36: Marker in konstanter Bildschirmgroesse. Radien liefert der Renderer
   (intelligence.ts rechnet Pixel in viewBox-Einheiten um), Strichstaerken haelt
   `vector-effect: non-scaling-stroke` unabhaengig von der Kartenskalierung fest.
   WICHTIG: hier KEIN `font-size` und KEINE `r`-Angabe — eine CSS-Deklaration
   schlaegt das vom Renderer gesetzte Praesentationsattribut. */
.wmap-dot { vector-effect: non-scaling-stroke; stroke: var(--canvas); stroke-width: 1.25; cursor: pointer; fill: var(--neutral); fill-opacity: 0.95; }
.wmap-dot.is-up { fill: var(--positive); }
.wmap-dot.is-down { fill: var(--negative); }
.wmap-dot.is-selected { stroke: var(--accent); stroke-width: 2.5; }
.wmap-dot:focus-visible { outline: none; stroke: var(--accent); stroke-width: 3; }
.wmap-ping { vector-effect: non-scaling-stroke; fill: none; stroke-width: 1.25; stroke: var(--neutral); pointer-events: none; transform-box: fill-box; transform-origin: center; animation: wmap-ping 3.2s ease-out infinite; }
.wmap-ping.is-up { stroke: var(--positive); }
.wmap-ping.is-down { stroke: var(--negative); }
@keyframes wmap-ping { 0% { transform: scale(1); opacity: 0.55; } 100% { transform: scale(3.2); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .wmap-ping { animation: none; opacity: 0; } }
.wmap-label { font-weight: 600; fill: var(--text-primary); text-anchor: middle; paint-order: stroke; stroke: var(--canvas); stroke-width: 3px; vector-effect: non-scaling-stroke; pointer-events: none; }
.wmap-side { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); min-height: 120px; }
.wmap-side-title { margin: 0 0 4px; font-size: 13px; color: var(--text-secondary); font-weight: 600; }

/* ---- Weltkarte V2 (§14): verortete Ereignisse, Marker-Ebenen strikt getrennt ----
   Kategorie = Form, Severity = eigener Ring (unbekannt gestrichelt, NIE „gering"),
   Aktualität = Puls (CSS, pausiert off-viewport/hidden), Marktimpact = eigene Ebene,
   Confidence = Deckkraft. Keine Glows, ausschließlich Design-Tokens. */
.wmap2-layer { grid-column: 1 / -1; }
.wmap2-layout { display: grid; grid-template-columns: minmax(0, 2.4fr) minmax(260px, 1fr); gap: var(--space-3); align-items: start; }
.wmap2 { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.wmap2-controls { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.wmap2-btn { padding: 2px 10px; font-size: 12px; }
/* Aktiver Zustand GEFUELLT (Zielbild) — die bisherige Variante faerbte nur Rand
   und Schrift und war neben dem inaktiven Knopf kaum zu unterscheiden. */
.wmap2-btn.is-on { background: var(--accent-solid); color: var(--accent-text); border-color: var(--accent-solid); font-weight: 600; }
.wmap2-zoom { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.wmap2-figure { position: relative; width: 100%; border-radius: var(--radius-sm); overflow: hidden; background: var(--canvas-subtle); border: 1px solid var(--border-subtle); }
.wmap2-svg { display: block; width: 100%; height: auto; touch-action: none; cursor: grab; }
.wmap2-svg:active { cursor: grabbing; }
.wmap2-svg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.wmap2-image { filter: brightness(0.82) saturate(0.92); }                      /* Dark: dezent abdunkeln */
:root[data-theme="light"] .wmap2-image { filter: none; }                        /* Light: keine Übersteuerung */
@media (prefers-color-scheme: light) { :root:not([data-theme]) .wmap2-image { filter: none; } }
.wmap2-hit { fill: transparent; cursor: pointer; }                              /* unsichtbare ≥40px-Trefferfläche */
.wmap2-hit:focus-visible { outline: none; stroke: var(--accent); stroke-width: 2; }
/* MARKERGROESSE — GEPRUEFTE INVARIANTE (0.5.36). Diese Karte zeichnet NICHT in
   2048×1024: `redraw()` setzt die viewBox auf die GEMESSENE Breite
   (`0 0 width height`), transformiert wird nur das Basisbild. Die Radien im
   Renderer (Puls 6, Severity-Ring 7,5, Kern 4,2) sind damit BEREITS
   Bildschirmpixel und duerfen NICHT wie bei den `.wmap-*`-Markern der
   Kalender-Ebene ueber `vbPerPx` umgerechnet werden — dort ist die viewBox fest
   2048 breit und wird gedehnt. Wer das hier „auch noch fixt", macht es kaputt. */
.wmap2-core { stroke: var(--canvas); stroke-width: 1; pointer-events: none; }
.wmap2-core.is-conf-unknown { stroke: var(--text-muted); stroke-dasharray: 1.5 1.5; }
.wmap2-core.is-selected { stroke: var(--accent); stroke-width: 2; }
.wmap2-sev { fill: none; pointer-events: none; }
.wmap2-sev.is-unknown { stroke: var(--neutral); stroke-width: 1.4; stroke-dasharray: 3 3; }
.wmap2-sev.is-gering { stroke: var(--info); stroke-width: 1.6; }
.wmap2-sev.is-mittel { stroke: var(--warning); stroke-width: 2.1; }
.wmap2-sev.is-hoch { stroke: var(--negative); stroke-width: 2.8; }
.wmap2-pulse { fill: none; stroke: var(--accent); stroke-width: 1.4; pointer-events: none; transform-box: fill-box; transform-origin: center; animation: wmap2-pulse 3.4s ease-out infinite; }
.wmap2-pulse.is-laufend { stroke: var(--neutral); animation-duration: 5.2s; }
/* Zweiter, um eine HALBE Periode versetzter Ring (wie in der Kalender-Ebene):
   der Puls laeuft durchgehend statt nach jedem Ring stehenzubleiben. NEGATIVER
   Versatz = der Echo-Ring startet bereits mitten im Lauf, kein Warten beim
   ersten Zeichnen. Je Zustand eigene Dauer ⇒ eigener Versatz. */
.wmap2-pulse.is-echo { animation-delay: -1.7s; }
.wmap2-pulse.is-laufend.is-echo { animation-delay: -2.6s; }
/* Ohne Bewegung darf der Echo-Ring NICHT als zweiter Strich stehenbleiben —
   zwei deckungsgleiche Ringe a 0.4 Deckkraft ergaeben einen fetten Ring. */
@media (prefers-reduced-motion: reduce) { .wmap2-pulse.is-echo { display: none; } }
/* Zweiter Ring auf halber Strecke: mit nur einem Ring stand der Puls nach jedem
   Durchlauf sichtbar still. Die Verzoegerung ist die HALBE Dauer der jeweiligen
   Stufe, damit der Abstand gleichmaessig bleibt. */
.wmap2-pulse.is-offset { animation-delay: 1.7s; }
.wmap2-pulse.is-offset.is-laufend { animation-delay: 2.6s; }
@keyframes wmap2-pulse { 0% { transform: scale(0.85); opacity: 0.55; } 100% { transform: scale(2); opacity: 0; } }
.wmap2.is-paused .wmap2-pulse { animation-play-state: paused; }                 /* off-viewport / Tab im Hintergrund */
/* Ohne Animation legt der zweite Ring sich deckungsgleich auf den ersten und
   verdoppelt nur dessen Deckkraft — dort bleibt es beim einen Ring. */
@media (prefers-reduced-motion: reduce) {
  .wmap2-pulse { animation: none; opacity: 0.4; }
  .wmap2-pulse.is-offset { display: none; }
}
.wmap2-impact { fill: var(--neutral); pointer-events: none; }
.wmap2-impact.is-up { fill: var(--positive); }
.wmap2-impact.is-down { fill: var(--negative); }
.wmap2-cluster { fill: var(--surface-1); fill-opacity: 0.92; stroke: var(--border-strong); stroke-width: 1.4; pointer-events: none; }
.wmap2-cluster.is-selected { stroke: var(--accent); stroke-width: 2.4; }
.wmap2-cluster-count { fill: var(--text-primary); font-size: 11px; font-weight: 700; text-anchor: middle; pointer-events: none; font-variant-numeric: tabular-nums; }
.wmap2-label { fill: var(--text-primary); font-size: 11px; font-weight: 600; text-anchor: middle; paint-order: stroke; stroke: var(--canvas); stroke-width: 3px; pointer-events: none; }
/* Legende als Pillen mit Farbpunkt (Zielbild) statt nackter Textreihe. Inhalt
   unveraendert. KEIN Kontrastrand an der Glyphe: der `--canvas`-Strich der
   Marker ist auf dem Kartenfoto ein Halo, auf `--surface-2` waere er hell
   unsichtbar und dunkel nur eine Verduennung. */
.wmap2-legend { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--text-secondary); }
.wmap2-legend-item {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--surface-2); border: 1px solid var(--border-subtle);
  border-radius: 999px; padding: 2px 9px 2px 6px; white-space: nowrap;
}
.wmap2-legend-icon { display: block; }
.wmap2-state:not([hidden]) { padding: var(--space-3) 0; }
.wmap2-side { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.wmap2-side-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.wmap2-side-title { margin: 0; font-size: 13px; color: var(--text-secondary); font-weight: 600; }
.wmap2-filter { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border-default); border-radius: var(--radius-sm); padding: 3px 8px; font: inherit; font-size: 12px; max-width: 100%; }
.wmap2-side-toggle { padding: 2px 10px; font-size: 12px; }
.wmap2-side:not(.is-open) .wmap2-filters,
.wmap2-side:not(.is-open) .wmap2-list,
.wmap2-side:not(.is-open) .wmap2-detail,
.wmap2-side:not(.is-open) .data-count { display: none; }
.wmap2-filters { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.wmap2-list { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow-y: auto; }
.wmap2-list-item { display: flex; flex-direction: column; gap: 1px; text-align: left; background: none; border: 0; border-left: 2px solid transparent; border-radius: var(--radius-sm); padding: 4px 6px; font: inherit; color: var(--text-primary); cursor: pointer; }
.wmap2-list-item:hover { background: var(--surface-interactive); }
.wmap2-list-item.is-selected { background: var(--accent-soft); border-left-color: var(--accent); }
.wmap2-list-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.wmap2-list-title { font-size: 12px; font-weight: 600; }
.wmap2-list-sub { font-size: 11px; color: var(--text-muted); }
.wmap2-detail-title { margin: 0 0 4px; font-size: 12px; color: var(--text-secondary); font-weight: 600; }
@media (max-width: 900px) {
  .wmap2-layout { grid-template-columns: minmax(0, 1fr); }
  /* Detailpanel wird zum Sheet: eingeklappt bleibt die Kopfzeile als Griff stehen. */
  .wmap2-side { position: fixed; left: 0; right: 0; bottom: 0; z-index: 40; max-height: 72vh; overflow-y: auto;
    background: var(--surface-1); border-radius: var(--radius) var(--radius) 0 0; border-color: var(--border-default);
    transform: translateY(calc(100% - 46px)); transition: transform 180ms ease; }
  .wmap2-side.is-open { transform: translateY(0); }
  .wmap2-list { max-height: 40vh; }
}
@media (prefers-reduced-motion: reduce) { .wmap2-side { transition: none; } }

/* ---- Timeline ---- */
/* Die Jetzt-Linie trug bisher NUR die Klasse chart-guide und war damit vom
   Hover-Fadenkreuz nicht zu unterscheiden. timeline-now hebt nur die Farbe,
   die Strichelung kommt weiterhin aus chart-guide. */
.timeline-now { stroke: var(--accent); opacity: .75; }
.timeline-now-label { fill: var(--accent); font-weight: 600; }
.timeline-stem { stroke: var(--border-default); stroke-width: 1; }
.timeline-dot { fill: var(--accent); stroke: var(--surface-1); stroke-width: 1.5; }
.timeline-dot.is-up { fill: var(--info); } .timeline-dot.is-down { fill: var(--negative); } .timeline-dot.is-flat { fill: var(--neutral); } .timeline-dot.is-warn { fill: var(--warning); }

/* ---- Slopegraph ----
   Der Renderer haengt die Serienklasse (is-up/is-down) an `chart-line` und
   `chart-dot` (slope.ts:52/53) — es gab dafuer KEINE Regel, nur `.series-N`.
   Alle Serien waren dadurch tuerkis, die Richtungsangabe des Aufrufers blieb
   wirkungslos. Bewusst NUR diese beiden Klassen: `.is-up`/`.is-down` allein ist
   die globale Textfarbregel und darf nicht auf SVG-Fuellungen greifen. */
.chart-line.is-up { stroke: var(--positive); }
.chart-line.is-down { stroke: var(--negative); }
.chart-dot.is-up { fill: var(--positive); }
.chart-dot.is-down { fill: var(--negative); }

/* ---- Heatmap ---- */
/* 0.5.37: Die Fuge lief in --canvas — das ist die SEITENflaeche, nicht die
   Panelflaeche, auf der die Heatmap liegt (.panel:755 background-color:
   --bg-elev); im Hellmodus zog sie graue Linien ueber Weiss. Jetzt eine
   Haarlinie in --border-subtle wie an jeder anderen Kante.
   KLARE NULLFARBE: heatmap.ts:43 klemmt die Intensitaet auf min. 0,08 — eine
   echte 0 war dadurch fast unsichtbar und von "keine Daten" kaum zu trennen.
   Die durchgezogene Haarlinie umrandet JEDE belegte Zelle, die fehlende bleibt
   rahmenlos gestrichelt und gedaempft: der Unterschied ist damit eine FORM,
   nicht nur eine Farbe (a11y-Regel 5). */
.heat-cell { stroke: var(--border-subtle); stroke-width: 1; fill: var(--neutral); }
.heat-cell.is-up { fill: var(--positive); } .heat-cell.is-down { fill: var(--negative); } .heat-cell.is-seq { fill: var(--accent); }
.heat-cell.is-missing { fill: none; stroke: var(--chart-missing); stroke-dasharray: 2 2; stroke-opacity: 0.55; }
/* 0.5.37: Die Zelle mit dem GROESSTEN Betrag hat fill-opacity 1 (heatmap.ts:43) —
   dort stand --text-primary (#eef5ff) auf --positive (#37c58b): Kontrast 1,8:1,
   also unlesbar, und zwar genau auf den Zellen, die man ansieht.
   Statt die Intensitaetsskala zu daempfen (das waere eine Datenluege) bekommt die
   Zahl einen Traeger aus der Panelflaeche: `paint-order: stroke` zeichnet den
   Umriss ZUERST, die Fuellung darueber. Der wirksame Kontrast ist damit in
   BEIDEN Themes der von Text zu Flaeche, unabhaengig von der Zellfarbe.
   heatmap.ts:45 setzt an diesem Text weder stroke noch fill — kein Konflikt. */
.heat-value { fill: var(--text-primary); font-size: 10px; pointer-events: none; font-variant-numeric: tabular-nums;
  paint-order: stroke; stroke: var(--surface-1); stroke-width: 2.4; stroke-linejoin: round; }

/* ---- Datentabelle ---- */
.data-table-wrap { display: flex; flex-direction: column; gap: var(--space-2); }
.data-table-scroll { overflow-x: auto; }
.data-table { font-size: 12px; }
.data-table th, .data-table td { padding: 6px 8px; border-bottom: 1px solid var(--border-soft); text-align: left; white-space: nowrap; }
/* Kopfzeile (Zielbild): 11px, gedaempft, Grossbuchstaben mit Sperrung — fuer
   sortierbare UND feste Spalten. Vorher formatierte EINE Regel `th` und `td`
   identisch, waehrend nur der Sortierknopf gedaempft war: in derselben Zeile
   standen zwei Kopf-Typografien nebeneinander.
   `--text-secondary` statt `--text-muted`: letzteres erreicht auf der
   Panelflaeche nur 4,1:1 und verfehlt AA fuer Kleintext.
   KEINE Polsterung anfassen — sonst wachsen auch die Chart-Datentabellen. */
.data-table thead th, .chart-datatable thead th {
  color: var(--text-secondary); font-size: 11px; font-weight: 650;
  letter-spacing: .06em; text-transform: uppercase;
  border-bottom: 1px solid var(--border-default);
}
.data-table td.ta-right, .data-table th.ta-right { text-align: right; font-variant-numeric: tabular-nums; }
/* Der Sortierknopf erbt die Kopf-Typografie und traegt nur noch den
   Aktivzustand — der Pfeil bleibt das zweite, nicht-farbliche Signal. */
.th-sort { background: none; border: 0; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; padding: 0; }
.th-sort:hover { color: var(--text-primary); }
.th-sort.is-active { color: var(--accent); }
.th-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.data-empty { color: var(--fg-muted); text-align: center; padding: var(--space-6); }
.data-table-footer { display: flex; align-items: center; gap: var(--space-3); justify-content: flex-end; font-size: 12px; color: var(--fg-muted); }
.data-table-tools { display: flex; justify-content: flex-end; }
.col-menu summary { cursor: pointer; font-size: 12px; color: var(--fg-muted); }
.col-menu-list { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-2) 0; }
.col-menu-item { display: flex; align-items: center; gap: 4px; font-size: 12px; }
/* EINE Pillenform fuer Seite/Status/Zustand (Zielbild). Vorher standen in
   derselben Tabellenzeile drei Bauformen nebeneinander: 4px-Ecke mit Grund ohne
   Rand, 999px-Vollkontur ohne Grund und 999px-Rand ohne Grund. Grund und Rand
   leiten sich jetzt aus der Textfarbe ab, die Varianten setzen nur `color` —
   dadurch bleiben die Semantik-Token die einzige Farbquelle. */
.side-badge, .status-badge {
  display: inline-flex; align-items: center; padding: 1px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1.5; white-space: nowrap;
  background: color-mix(in srgb, currentColor 12%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 38%, transparent);
}
.side-badge.is-up, .side-badge.is-down { background: color-mix(in srgb, currentColor 18%, transparent); }
.status-badge.is-up { color: var(--positive); } .status-badge.is-down { color: var(--negative); } .status-badge.is-flat { color: var(--warning); }
.ui-badge { background: color-mix(in srgb, currentColor 12%, transparent); }

/* ---- Responsive (§12: ≤ 768px = mobile Shell, 375px ohne Body-Overflow) ---- */
@media (max-width: 1200px) { .kpi-row, .kpi-row-secondary { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 900px) { .panel-grid { grid-template-columns: 1fr; } .panel-grid .span-2 { grid-column: span 1; } }
@media (max-width: 768px) {
  /* EINE Zeile statt zwei (vorher 92px = 44 + 40 + Abstand). 56px traegt die
     40px-Touchziele mit Luft. */
  :root { --header-h: 56px; }
  .app-root { grid-template-columns: minmax(0, 1fr); grid-template-areas: "authbar" "header" "main"; }
  .app-ticker-tape { left: 0; padding-inline: var(--space-3); }
  /* Off-Canvas-Navigation: Hamburger öffnet, Backdrop schließt (Touch, Safe-Area).
     Die zusätzliche Fußhöhe hält die LETZTEN Untermenüpunkte frei scrollbar. */
  .app-menu-btn { display: inline-flex; }
  .app-nav {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 40; width: min(84vw, 320px);
    max-height: 100vh; align-self: auto;
    padding: calc(var(--space-6) + env(safe-area-inset-top)) var(--space-3) calc(var(--space-2) + env(safe-area-inset-bottom));
    border-right: 1px solid var(--border-default); box-shadow: var(--shadow);
    transform: translateX(-100%); transition: transform 0.2s ease; overflow-y: auto;
  }
  .app-root.nav-open .app-nav { transform: translateX(0); }
  .app-backdrop { display: block; position: fixed; inset: 0; z-index: 30; background: var(--backdrop); }
  .app-backdrop[hidden] { display: none; }
  /* Touch-Ziele ≥ 40px (§12). */
  .app-navlink, .app-subnavlink, .nav-toggle, .tab, .app-iconbtn, .ui-btn, .seg-btn, .theme-opt, .app-select, .app-search-input, .app-search-hit, .app-filter-chip, .app-choice-trigger, .app-choice-option { min-height: 40px; }
  /* AUSNAHME von §12, bewusst und benannt (Auftrag 09.08.: „der Zeitumschalter
     sollte kleiner sein"). Sie gilt AUSSCHLIESSLICH für die Umschalter in
     Panel-Köpfen und im Performance-Chart — dort standen 40px hohe Segmente
     über der halben Diagrammbreite und dominierten die Ansicht.
     Warum das vertretbar ist: ein Segment-Umschalter ist EIN zusammenhängendes
     Ziel ohne Totzonen zwischen den Feldern; die Gruppe bleibt breit, nur die
     Höhe sinkt auf 34px. Freistehende Knöpfe, Navigation, Eingabefelder und
     Menüeinträge behalten die vollen 40px. */
  .panel-head-controls .seg-btn, .performance-mode-controls .seg-btn { min-height: 34px; }
  /* 09.08. (Befund am Gerät): Titel, Zeitraum-Umschalter und „Teildaten"-Abzeichen
     teilten sich EINE Zeile. Auf dem Handy blieb für den Umschalter so wenig übrig,
     dass er mitten im letzten Feld abgeschnitten wurde („3 Monate" → „3"). Der
     Umschalter bekommt deshalb mit dem Abzeichen zusammen eine eigene, volle Zeile
     unter dem Titel; das Abzeichen sitzt rechts außen, der Umschalter davor. */
  .panel-head { flex-wrap: wrap; }
  .panel-head-side { width: 100%; justify-content: space-between; }
  .nav-toggle { width: 40px; }
  .app-search-results { right: 0; min-width: 0; max-width: 100%; }
  /* Mobil ist die Suche kein Popover, sondern ein vollbreiter, DECKENDER
     Streifen direkt unter dem fixierten Kopf. Die top-Formel ist woertlich die
     Kopfhoehen-Formel weiter unten in diesem Block — der Streifen kann die
     iPhone-Kerbe damit nicht ueberdecken, sie steckt bereits im Kopf.
     `position: fixed` statt absolute, weil der mobile Kopf ohne backdrop-filter
     arbeitet; `width: 100%` statt 100vw (100vw misst hier 15 px zu breit). */
  .app-globals {
    position: fixed;
    top: calc(var(--header-h) + env(safe-area-inset-top, 0px));
    left: 0; right: 0;
    width: 100%; max-width: 100%;
    border-radius: 0; border-left: 0; border-right: 0;
    padding: var(--space-2) max(var(--space-3), env(safe-area-inset-right)) var(--space-2) max(var(--space-3), env(safe-area-inset-left));
    background: var(--surface-1);
  }
  .app-globals .app-search-results { position: static; max-height: 50vh; }
  /* Version/FX sind auf schmalen Geräten Kontext, kein Pflichtsignal. */
  .app-version-badge, .app-fx-badge { display: none; }
  .app-navlink { display: flex; align-items: center; }
  /* Risikoregler mobil einspaltig — MUSS in diesem Block bleiben: ein eigener
     zweiter @media-(max-width:768px)-Block wuerde als erster Treffer gefunden
     und verschoebe jede textuelle Auswertung des Mobil-Abschnitts. */
  .lr-field { flex: 1 1 100%; }
  .app-subnavlink { display: flex; align-items: center; }
  /* §5 mobil: EINE Zeile — wie im Alt-Dashboard. Hamburger · Titel · Suche ·
     Glocke · Börse · Modus · Steuerung, alles nebeneinander.
     Der Kopf ist FIXIERT und deckend: er trug die Kerbe (`env(safe-area-inset-
     top)`) vorher nicht selbst, sondern klebte per `top: var(--safe-top)`
     darunter. Dadurch blieb oberhalb ein Streifen, durch den der scrollende
     Inhalt sichtbar war — auf dem iPhone der auffällige „durchsichtige" Balken.
     Zusammen mit einem zu 6 % transparenten Hintergrund und `backdrop-filter`,
     der auf iOS nicht zuverlaessig greift, sah der ganze Kopf durchscheinend
     aus. Jetzt: Kerbe als eigenes `padding-top`, voll deckende Flaeche. */
  .app-header {
    position: fixed; top: 0; left: 0; right: 0; z-index: 26;
    display: flex; flex-wrap: nowrap; align-items: center;
    width: 100%; min-width: 0;
    height: calc(var(--header-h) + env(safe-area-inset-top, 0px));
    min-height: calc(var(--header-h) + env(safe-area-inset-top, 0px));
    gap: 6px;
    padding-top: env(safe-area-inset-top, 0px);
    padding-right: max(var(--space-3), env(safe-area-inset-right));
    padding-bottom: 0;
    padding-left: max(var(--space-3), env(safe-area-inset-left));
    background: var(--surface-1);
    backdrop-filter: none;
  }
  /* Der fixierte Kopf ist aus dem Fluss genommen: seine Rasterzeile faellt auf 0
     zusammen. Den Platz schafft die Wurzel — dort gilt er fuer JEDEN Inhalt
     (Warnleiste wie Hauptbereich), ohne Sonderfaelle je Kind. Die Kerbe steckt
     bereits in der Kopfhoehe, deshalb hier kein zweites safe-area-Padding. */
  .app-root {
    padding-top: calc(var(--header-h) + env(safe-area-inset-top, 0px));
  }
  .app-brand, .app-crumb { display: none; }
  .app-header-left { flex: 1 1 auto; min-width: 0; gap: var(--space-2); }
  .app-header-right { display: flex; flex: 0 0 auto; gap: 6px; margin-left: 0; }
  /* Mobil gibt es keine dauerhaft sichtbare Seitenleiste — hier IST der Titel
     die Ortsangabe und wird wieder eingeblendet. */
  .app-titlewrap { display: flex; flex: 1 1 auto; min-width: 0; }
  .app-title { font-size: 15px; }
  .app-fullscreen { display: none; }
  /* Auf einer Zeile zaehlt jeder Pixel: kompakte Ziele statt 40px-Kacheln.
     44px Hoehe bleibt als Touch-Ziel ueber die Kopfhoehe erhalten. */
  .app-iconbtn { width: 34px; min-width: 34px; padding: 0; }
  .app-venue-choice, .app-mode-choice { min-width: 0; flex: 0 0 auto; }
  .app-venue-choice .app-choice-trigger { max-width: 74px; padding-inline: 8px; }
  .app-mode-choice .app-choice-trigger { min-width: 34px; padding-inline: 8px; }
  .app-venue-choice .app-choice-trigger, .app-mode-choice .app-choice-trigger {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .app-choice-menu { width: min(190px, calc(100vw - 24px)); min-width: 0; max-width: calc(100vw - 24px); }
  /* Bereichsreiter bleiben im eigenen Scrollport; die sichtbare Laufleiste macht
     zusätzliche Unterpunkte auf Touch-Geräten erkennbar, ohne den Body zu verbreitern. */
  .tabbar {
    width: 100%; max-width: 100%; padding-bottom: 5px;
    overscroll-behavior-x: contain; scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent; scrollbar-gutter: stable;
  }
  .tabbar::-webkit-scrollbar { display: block; height: 5px; }
  .tabbar::-webkit-scrollbar-track { background: transparent; }
  .tabbar::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; }
  /* Die Kontext-Offcanvas wird mobil vollflächig.
     KEIN 100vw: `vw` zaehlt eine klassische Scrollleiste mit, die Layoutbreite
     nicht. Bei `right: 0` schob die Differenz das Panel um die Scrollleistenbreite
     nach links aus dem Bild (gemessen: left = -15 px bei 390 px Viewport).
     `width: 100%` folgt dem Enthaltendenblock und sitzt buendig. */
  .app-context {
    top: 0; right: 0; bottom: 0; left: 0; height: 100vh; height: 100dvh;
    width: 100%; max-width: 100%; border-radius: 0;
    padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
  }
  .live-balance-series-grid { grid-template-columns: minmax(0, 1fr); }
  .kpi-row, .kpi-row-secondary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app-main { padding: var(--space-4); padding-bottom: calc(var(--space-6) + 34px + env(safe-area-inset-bottom)); }
  /* Tabelle → mobile Kartenansicht */
  .data-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .data-table tr { display: block; border: 1px solid var(--border-soft); border-radius: var(--radius-sm); margin-bottom: var(--space-2); padding: 4px 8px; }
  .data-table td { display: flex; justify-content: space-between; border: 0; white-space: normal; padding: 3px 0; }
  .data-table td::before { content: attr(data-label); color: var(--fg-muted); font-size: 11px; margin-right: var(--space-3); }
  .data-table td.hide-mobile, .data-table th.hide-mobile { display: none; }
}
@media (max-width: 520px) {
  .app-title { font-size: 14px; }
}
@media (max-width: 460px) { .kpi-row, .kpi-row-secondary { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .app-nav { transition: none; } }

/* ===== GLOBALER TOAST-/NOTIFICATION-STACK =====
   Fixiert, bounded und pointer-transparent: Meldungen bleiben ueber allen
   Dashboard-Bereichen sichtbar, blockieren aber nicht die restliche Flaeche. */
.toast-stack {
  position: fixed;
  top: calc(var(--safe-top) + var(--header-h) + var(--space-3));
  right: calc(env(safe-area-inset-right, 0px) + var(--space-4));
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(420px, calc(100vw - 32px));
  max-height: calc(100vh - var(--header-h) - var(--safe-top) - var(--space-6));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 2px;
  pointer-events: none;
}
.toast {
  --toast-color: var(--info);
  --toast-soft: var(--info-soft);
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 32px;
  gap: var(--space-2);
  align-items: start;
  min-width: 0;
  padding: var(--space-3);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--surface-elevated) 96%, var(--toast-soft));
  border: 1px solid var(--border-default);
  border-left: 4px solid var(--toast-color);
  border-radius: var(--radius);
  box-shadow: 0 10px 32px color-mix(in srgb, var(--backdrop) 62%, transparent);
  pointer-events: auto;
  animation: toast-enter 160ms ease-out both;
}
.toast--success, .toast--completed { --toast-color: var(--positive); --toast-soft: var(--positive-soft); }
.toast--warning { --toast-color: var(--warning); --toast-soft: var(--warning-soft); }
.toast--error { --toast-color: var(--negative); --toast-soft: var(--negative-soft); }
.toast--cancelled { --toast-color: var(--neutral); --toast-soft: var(--neutral-soft); }
.toast--running { --toast-color: var(--info); --toast-soft: var(--info-soft); }
.toast-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  color: var(--toast-color);
  background: var(--toast-soft);
  font-size: 11px;
  font-weight: 800;
}
.toast--running .toast-icon { animation: toast-pulse 1.35s ease-in-out infinite; }
.toast-announcement { min-width: 0; }
.toast-title-row { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
.toast-title { overflow-wrap: anywhere; font-size: 13px; font-weight: 700; line-height: 1.35; }
.toast-count {
  flex: none;
  padding: 0 5px;
  color: var(--toast-color);
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
.toast-message, .toast-details { margin-top: 2px; overflow-wrap: anywhere; white-space: pre-wrap; }
.toast-message { color: var(--text-secondary); font-size: 12px; }
.toast-details { color: var(--text-muted); font-size: 11px; }
.toast-details[hidden], .toast-count[hidden] { display: none; }
.toast-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -5px -5px 0 0;
  padding: 0;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 20px;
  cursor: pointer;
}
.toast-close:hover { color: var(--text-primary); background: var(--surface-interactive); }
.toast-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@keyframes toast-enter { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes toast-pulse { 50% { opacity: 0.45; transform: scale(0.88); } }
@media (max-width: 600px) {
  .toast-stack {
    top: calc(var(--safe-top) + var(--header-h) + var(--space-2));
    left: calc(env(safe-area-inset-left, 0px) + var(--space-2));
    right: calc(env(safe-area-inset-right, 0px) + var(--space-2));
    width: auto;
    max-height: calc(100vh - var(--header-h) - var(--safe-top) - env(safe-area-inset-bottom, 0px) - var(--space-4));
  }
  .toast { grid-template-columns: 28px minmax(0, 1fr) 40px; padding: var(--space-3); }
  .toast-close { width: 40px; height: 40px; margin-top: -9px; }
}
@media (prefers-reduced-motion: reduce) {
  .toast, .toast--running .toast-icon { animation: none; }
}

/* §7 KI-Canvas (0.1.43): ruhige, theme-getreue Aktivitäts-Visualisierung. */
.ki-canvas { position: relative; min-height: 220px; }
.ki-canvas__surface { display: block; width: 100%; height: 220px; }
.ki-canvas__fallback { padding: var(--space-4, 16px); color: var(--fg-dim); font-size: 0.85rem; }

/* ===== 0.1.43 §5 — Elevation-/Glow-System (vier Stufen, verbindlich) =====
   Level 0 Standardkarte: NUR Border/Surface-Trennung (kein Außenschein) — Default .panel.
   Level 1 Hover/interaktiv: dezente Elevation.  Level 2 aktiv/fokussiert: präziser
   Türkis-Akzent (kein Neon).  Level 3 kritisch/live: äußerst sparsam (nur .is-critical).
   Statusfarben sind SEMANTIK (ok/warn/err), nie Dekoration. */
/* 0.5.36: Das Kantenlicht `--card-edge` gehoert zu Level 0 und muss in JEDER
   Stufe erhalten bleiben — es ist Oberflaechenbeschaffenheit, kein Aussenschein.
   Es HIER zu fuehren ist Pflicht: eine zweite `.panel { box-shadow: … }`-Regel
   weiter oben in der Datei wuerde von diesem Block ueberschrieben (gemessen:
   berechneter Wert war `none`, das Kantenlicht war unsichtbar). */
.panel { box-shadow: var(--card-edge); }                       /* Level 0: ruhig */
.panel:hover { box-shadow: var(--card-edge), var(--shadow); }  /* Level 1 */
.panel:focus-within, .panel.is-active { border-color: var(--accent); box-shadow: var(--card-edge), 0 0 0 1px var(--accent); } /* Level 2 */
.panel.is-critical { box-shadow: var(--card-edge), 0 0 0 1px var(--err), var(--shadow); } /* Level 3 — nur echte Kritikfälle */

/* §6: Chart-Atem — konsistenter Abstand zwischen Panel-Kopf, Telemetrie und Plot
   (behebt die Alt-System-Klasse „Telemetrieblock klebt an der Chart-Reihe"). */
.panel .chart, .panel svg.chart, .panel .ki-canvas { margin-top: var(--space-3); margin-bottom: var(--space-2); }
.kpi-row { gap: var(--space-3); margin-bottom: var(--space-4); }
.panel-grid { gap: var(--space-4); }

/* §5 Typografie: Primär-KPIs tragen tabellarische Ziffern + klare Hierarchie. */
.kpi-card .kpi-value { font-variant-numeric: tabular-nums; }
.kpi-card--secondary .kpi-value { font-size: 0.95em; color: var(--fg-dim); }

/* ===== 0.1.44 §19 Phase 2a — Übersicht: operative Lage (tokenbasiert, Level 0) ===== */
/* Kennzahlen-Strip unter dem Equity-Chart (Start/Hoch/Tief/Zeitraum-PnL/Winrate/Max DD). */
.equity-strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-2); }
/* §7 Visual-Parity: Summenzeile über der Exposure-Treemap (eigene Klasse, damit
   der Equity-Chart-Strip separat prüfbar bleibt). */
.expo-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-2); }
.strip-cell {
  min-width: 0; padding: 8px 10px;
  background-color: var(--surface-1); background-image: var(--card-sheen);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  box-shadow: var(--card-edge);
}
.strip-label { font-size: 11px; color: var(--fg-muted); }
.strip-value { font-weight: 600; font-size: 13px; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) { .equity-strip, .expo-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Konten-Matrix (Börse × Konto-Ebene): kompakte Tabelle + ehrliche Vertragsnotiz. */
.acct-matrix th[scope='row'] { text-align: left; color: var(--fg-muted); font-weight: 600; }
.acct-matrix td .stat-sub { text-align: right; }
/* Aktivitäts-Sub-Tabs (Positionen/Trades) spannen die volle Grid-Breite. */
.overview-activity { min-width: 0; }
/* Exposure-Treemap: Long/Short-Semantik (ok/err-Token, keine Dekor-Farben). */
/* Semantische Kacheln nutzen dieselbe --tree-color-Mechanik wie die Reihen —
   dadurch bekommen sie auch die Farbkante.  fehlte ganz. */
.tree-cell.is-up { --tree-color: var(--positive); }
.tree-cell.is-down { --tree-color: var(--negative); }
.tree-cell.is-flat { --tree-color: var(--warning); }

/* ===== 0.1.44 §19 Phase 6 — Polish (§13): tabellarische Ziffern auf ALLEN Zahlenwerten,
   Chart-Interaktion (Letztwert-Pille + Live-Puls), alles tokenbasiert. ===== */
.kpi-value, .kpi-change, .stat-value, .data-count, .strip-value, .panel-stand, .kpi-age { font-variant-numeric: tabular-nums; }
.chart-pill-bg { fill: var(--surface-elevated); stroke: var(--border-default); }
.chart-pill-text { fill: var(--text-primary); font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chart-pulse { fill: var(--accent); }
.chart-pulse-ring { fill: none; stroke: var(--accent); stroke-width: 2; transform-box: fill-box; transform-origin: center; animation: chart-pulse 2.4s ease-out infinite; }
@keyframes chart-pulse { 0% { transform: scale(1); opacity: 0.7; } 100% { transform: scale(2.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .chart-pulse-ring { animation: none; opacity: 0; } }
.chart-capture.is-panning { cursor: grabbing; }

/* ===== 0.1.46 §20 B3a — Globales Chrome + Übersicht-Pflichtelemente (tokenbasiert,
   ruhige Designsprache, KEINE Glows: nur Border/Surface/Semantik-Token). ===== */

/* Pflichtzone der Übersicht (Live-Steuerung, Pflicht-KPIs, Linsen-Kontostände). */
.overview-must { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-4); }
.overview-dashboard { display: grid; gap: var(--space-4); }
.overview-primary-row { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(280px, 1fr); gap: var(--space-4); align-items: stretch; }
.overview-primary-row > .overview-performance-card { grid-column: auto; min-width: 0; align-content: start; }
.overview-performance-card > .panel:last-child { flex: 1 1 auto; }
.overview-intelligence-card { height: 100%; min-height: 0; }
.overview-intelligence-card .panel-content { display: flex; flex-direction: column; gap: var(--space-3); }
.overview-intelligence-state { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.overview-intelligence-metrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.overview-intelligence-provenance { margin-top: auto; padding-top: var(--space-2); border-top: 1px solid var(--border-subtle); color: var(--text-muted); font-size: 11px; }
.overview-risk-row { min-width: 0; }
.overview-risk-row > .panel { width: 100%; }
.overview-risk-control .panel-content { display: grid; gap: var(--space-3); }
.overview-risk-kpis { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); }
.overview-risk-secondary { padding-top: var(--space-2); border-top: 1px solid var(--border-subtle); }
.overview-risk-secondary .stat-list { grid-template-columns: repeat(3, minmax(100px, auto) minmax(0, 1fr)); }
/* 0.5.37: gleiche Formsprache wie die KPI-Karten, nur ohne Icon-Kachel. Der feste
   2-px-Akzentstreifen links entfällt — die Karte trägt jetzt Verlaufs-Sheen und
   Kantenlicht wie .kpi-card/.panel.
   ZWEITER BEFUND, gleicher Ort: `overviewMetric()` reicht `trendClass(...)` als
   Klasse durch (areas/overview.ts:533/537/584/585), sichtbar war davon NICHTS —
   .is-up/.is-down setzen nur `color`, und Label/Wert/Sub überschreiben es alle
   drei. Jetzt trägt die Karte den Zustand als Rahmen + Tönung + Randschein und
   der Wert die Zustandsfarbe. Farbe ist nie das einzige Signal: der Wert selbst
   führt sein Vorzeichen, die Unterzeile die Erklärung. Der Randschein läuft über
   --glow-strength (Hell = 0). */
.overview-metric-card {
  min-width: 0; padding: 12px 13px;
  background-color: var(--surface-1); background-image: var(--card-sheen);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  box-shadow: var(--card-edge);
}
.overview-metric-card.is-up { --metric-tone: var(--positive); }
.overview-metric-card.is-down { --metric-tone: var(--negative); }
.overview-metric-card.is-up, .overview-metric-card.is-down {
  border-color: color-mix(in srgb, var(--metric-tone) 46%, var(--border-subtle));
  background-image: var(--card-sheen), linear-gradient(150deg, color-mix(in srgb, var(--metric-tone) 9%, transparent), transparent 58%);
  box-shadow: var(--card-edge), 0 6px 22px color-mix(in srgb, var(--metric-tone) calc(var(--glow-strength) * 34%), transparent);
}
.overview-metric-label { color: var(--text-muted); font-size: 10px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; }
.overview-metric-value { margin-top: 3px; color: var(--metric-tone, var(--text-primary)); font-size: 18px; font-weight: 730; line-height: 1.15; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.overview-metric-sub { margin-top: 4px; color: var(--text-muted); font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; }
.overview-support { display: grid; gap: var(--space-4); }
.overview-primary-kpis, .overview-secondary-kpis { margin-bottom: 0; }
@media (max-width: 1180px) {
  .overview-primary-row { grid-template-columns: minmax(0, 1.65fr) minmax(270px, 1fr); }
  .overview-risk-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .overview-risk-secondary .stat-list { grid-template-columns: repeat(2, minmax(100px, auto) minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .overview-primary-row { grid-template-columns: minmax(0, 1fr); }
  .overview-intelligence-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .overview-intelligence-metrics, .overview-risk-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .overview-risk-secondary .stat-list { grid-template-columns: minmax(100px, auto) minmax(0, 1fr); }
}

/* Live-Steuerung: zwei ruhige Blöcke (Live-Schalter · Kill-Switch) nebeneinander. */
.live-control-body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
.live-control-body .live-loading { grid-column: 1 / -1; }
.live-switch, .live-kill { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-3); min-width: 0; }
.live-block-label { font-size: 11px; color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: var(--space-2); }
.live-state-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.live-state-text { font-weight: 600; }
.live-state-reason { margin-top: var(--space-1); color: var(--fg-muted); font-size: 12px; overflow-wrap: anywhere; }
.live-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); flex-wrap: wrap; }
.ui-btn-danger { border-color: var(--negative); color: var(--negative); }
.ui-btn-danger:hover { background: var(--negative-soft); }
.ui-btn-danger:disabled { background: var(--bg-elev-2); }
/* Knopf-Hierarchie (Zielbild): primaer gefuellt · sekundaer Umriss (= .ui-btn,
   Bestand) · gefaehrlich Umriss in Rot (Bestand) · Geister-Knopf fuer Zeilen-
   und Werkzeugaktionen. Additiv — kein bestehender Knopf aendert sich, bis eine
   Ansicht die Klasse vergibt.
   Der Fokusring war BISHER NICHT VORHANDEN: es gab im ganzen Stylesheet keine
   `.ui-btn:focus-visible`-Regel, der Tastaturfokus haing am Browser-Standard. */
.ui-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ui-btn-primary { background: var(--accent-solid); color: var(--accent-text); border-color: var(--accent-solid); font-weight: 600; }
.ui-btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.ui-btn-primary:disabled { background: var(--surface-2); color: var(--text-disabled); border-color: var(--border-subtle); }
.ui-btn-ghost { background: transparent; border-color: transparent; color: var(--text-secondary); }
.ui-btn-ghost:hover { background: var(--surface-interactive); color: var(--text-primary); }
.ks-reason { color: var(--fg-muted); font-size: 12px; overflow-wrap: anywhere; }
.ui-badge.is-ok { color: var(--positive); border-color: var(--positive); }
.ui-badge.is-err { color: var(--negative); border-color: var(--negative); }
.ui-badge.is-warn { color: var(--warning); border-color: var(--warning); }
.ui-badge.is-neutral { color: var(--fg-muted); }
.live-paused-badge { color: var(--warning); border-color: var(--warning); }

.context-mode-runtime { margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--border-soft); min-width: 0; }
.context-mode-runtime > .panel-head { padding: 0; border: 0; min-height: 0; }
.context-mode-runtime > .panel-subtitle { margin-top: var(--space-2); overflow-wrap: anywhere; }
.context-mode-actions > .ui-btn { flex: 1 1 135px; min-width: 0; }

/* Bestätigungs-Dialog (Design-Tokens; wörtliche Tipp-Eingabe für LIVE STARTEN). */
.ui-dialog-backdrop { position: fixed; inset: 0; z-index: 40; background: var(--backdrop); display: flex; align-items: center; justify-content: center; padding: var(--space-4); }
.ui-dialog { background: var(--surface-elevated); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow); padding: var(--space-4); max-width: 420px; width: 100%; }
.ui-dialog-title { margin: 0 0 var(--space-2); font-size: 15px; }
.ui-dialog-note { margin: 0 0 var(--space-3); color: var(--fg-muted); font-size: 13px; }
.ui-dialog-check { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-2) 0; font-size: 13px; }
.ui-dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-3); }
.ui-input { width: 100%; background: var(--bg-elev-2); color: var(--fg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 10px; font: inherit; }
.ui-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Linsen-Kontostände (Hero-Zone): kompakter Strip (eigene Klasse — bewusst KEIN
   .equity-strip, damit der Equity-Chart-Strip separat prüfbar bleibt); aktive
   Linse markiert (Level 2). Zellen nutzen die globalen .strip-cell-Regeln. */
.lens-strip { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-2); }
.lens-strip .strip-cell.is-active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.strip-sub { font-size: 11px; color: var(--fg-dim); }
@media (max-width: 900px) { .lens-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Konten×Venues-Matrix: klickbare Zellen + Drilldown; unavailable = Zell-Zustand
   mit EXAKT dem gelieferten Vertragsgrund (kein Banner, keine stillen Nullen). */
.acct-full-wrap { overflow-x: auto; }
.acct-full td.acct-td { padding: 0; vertical-align: top; }
.acct-cell { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; width: 100%; background: transparent; border: 0; border-radius: var(--radius-sm); padding: 6px 8px; font: inherit; color: var(--fg); text-align: right; cursor: pointer; }
.acct-cell:hover { background: var(--surface-interactive); }
.acct-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.acct-cell-value { font-weight: 600; font-variant-numeric: tabular-nums; }
.acct-cell-value.is-unavailable { color: var(--fg-muted); font-weight: 500; }
.acct-cell-sub { font-size: 11px; color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.acct-cell-reason { font-size: 11px; color: var(--fg-muted); max-width: 260px; white-space: normal; overflow-wrap: anywhere; }
.acct-cell.is-unavailable { background: var(--neutral-soft); }
.acct-detail { margin-top: var(--space-3); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-3); }
.acct-detail-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.acct-detail-title { margin: 0; font-size: 13px; }
.acct-detail-sub { margin-top: var(--space-2); font-size: 12px; color: var(--fg-muted); }

/* ===== 0.1.46 §20 B3c — Settings-Editor, Command-Panels, Watchlist, Katalog.
   Ruhige Designsprache, ausschließlich Tokens, KEINE Glows. ===== */

/* Bestätigungs-Dialog: optionale Detailzeilen (Diff-Vorschau vor dem Ausführen). */
.ui-dialog-detail { margin: 0 0 var(--space-3); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-2) var(--space-3); }
.ui-dialog-detail-line { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; overflow-wrap: anywhere; }

/* Gemeinsame Rückmeldezeile der Command-Panels (Erfolg / Fehler / läuft). */
.cmd-feedback { margin-top: var(--space-2); font-size: 12px; overflow-wrap: anywhere; }
.cmd-feedback.is-ok { color: var(--positive); }
.cmd-feedback.is-err { color: var(--negative); }
.cmd-feedback.is-busy { color: var(--fg-muted); }
.cmd-actions-row { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.cmd-actions-row .ui-input { width: auto; min-width: 160px; }

/* Einstellungen: Werteliste mit Provenienz, Bereich, Auditstatus + Inline-Editor. */
.cfg-toolbar { display: flex; gap: var(--space-3); align-items: center; justify-content: space-between; margin-bottom: var(--space-3); flex-wrap: wrap; }
.cfg-search { max-width: 280px; }
.cfg-count { color: var(--fg-muted); font-size: 12px; white-space: nowrap; }
.cfg-rows { display: flex; flex-direction: column; gap: var(--space-2); }
.cfg-row { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-2) var(--space-3); }
.cfg-row.is-readonly { background: var(--bg-elev-2); }
.cfg-row-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.cfg-path { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; overflow-wrap: anywhere; }
.cfg-src.is-version { color: var(--accent); border-color: var(--accent); }
.cfg-src.is-env { color: var(--warning); border-color: var(--warning); }
.cfg-ro { color: var(--fg-muted); }
.cfg-row-main { display: flex; align-items: center; gap: var(--space-3); margin-top: 2px; flex-wrap: wrap; }
.cfg-value { font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.cfg-row-meta { margin-top: 2px; font-size: 11px; color: var(--fg-muted); overflow-wrap: anywhere; }
.cfg-edit { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; width: 100%; }
.cfg-edit .cfg-input { width: auto; min-width: 140px; }
.cfg-error { flex-basis: 100%; color: var(--negative); font-size: 12px; }

/* Bewährungs-Admin: aktive Sperren mit Freigeben-Aktion. */
.prob-locks { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
.prob-lock-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.prob-lock-key { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; }
.prob-lock-sub { color: var(--fg-muted); font-size: 11px; }

/* Watchlist-Pflege (Spot). */
.wl-list { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
.wl-row { display: grid; grid-template-columns: minmax(70px,.7fr) repeat(5,minmax(72px,1fr)) minmax(130px,1.4fr) auto repeat(4,auto); align-items: center; gap: var(--space-2); padding: var(--space-2); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.wl-symbol { font-family: var(--font-mono, ui-monospace, monospace); font-weight: 600; }
.wl-added { color: var(--fg-muted); font-size: 11px; flex: 1; }
.wl-metric, .wl-source, .wl-order { color: var(--fg-muted); font-size: 11px; overflow-wrap: anywhere; }
.wl-order { text-align: right; }

/* Asynchroner Research-/Systemexport. */
.research-export-form { display: grid; grid-template-columns: repeat(auto-fit,minmax(150px,1fr)); gap: var(--space-2); align-items: center; }
.research-export-form .ui-input { min-width: 0; width: 100%; }
.research-export-jobs { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-3); }
.research-export-job { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); padding: var(--space-3); display: grid; gap: var(--space-2); }
.research-export-job-head, .research-export-job-meta { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.research-export-job-head code { flex: 1; overflow-wrap: anywhere; }
.research-export-job-meta { color: var(--fg-muted); font-size: 11px; }
.research-export-job-meta span:not(:last-child)::after { content: ' ·'; }
.research-export-progress { width: 100%; accent-color: var(--accent); }

/* Command-Katalog (System/Audit): Envelope-Regeln über den Tabellen. */
.cmd-envelope { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--space-3); }
.cmd-envelope-line { font-size: 11px; color: var(--fg-muted); overflow-wrap: anywhere; }

@media (max-width: 700px) {
  .cfg-toolbar { flex-direction: column; align-items: stretch; }
  .cfg-search { max-width: none; }
  .cmd-actions-row .ui-input { min-width: 0; flex: 1; }
  .wl-row { grid-template-columns: 1fr 1fr; }
  .wl-symbol, .wl-source { grid-column: 1 / -1; }
  .wl-row .ui-btn { width: 100%; }
}

/* ---- §7 Visual-Parity: Radar (Spot-Risiko-Profil) ---- */
.radar-ring { stroke: var(--border-soft); stroke-width: 1; }
.radar-spoke { stroke: var(--border-soft); stroke-width: 1; }
.radar-spoke.is-missing { stroke: var(--border-subtle); stroke-dasharray: 3 3; }
.radar-label { fill: var(--fg-dim); font-size: 10px; }
.radar-label.is-missing { fill: var(--fg-muted); }
.radar-area { fill: color-mix(in srgb, var(--accent) 20%, transparent); stroke: var(--accent); stroke-width: 1.6; }
.radar-line { stroke: var(--accent); stroke-width: 1.6; }
.radar-dot { fill: var(--accent); stroke: var(--bg-elev); stroke-width: 1.2; }
.radar-dot.is-up { fill: var(--ok); } .radar-dot.is-flat { fill: var(--warn); } .radar-dot.is-down { fill: var(--err); }

/* ---- §7 Visual-Parity: Spot-Tachos/Chips, Monats-Heatmap, Risiko-Radar ---- */
.gauge-detail { margin-top: var(--space-3); }
.chip-row { align-items: center; }
.chip-note { font-size: 11px; color: var(--fg-muted); }
.month-heat { margin-bottom: var(--space-3); }
.month-heat-label, .radar-detail-label { font-size: 12px; color: var(--text-secondary); font-weight: 600; margin-bottom: 2px; }
.radar-wrap { display: grid; grid-template-columns: minmax(200px, 1fr) minmax(0, 1fr); gap: var(--space-3); align-items: center; }
@media (max-width: 720px) { .radar-wrap { grid-template-columns: minmax(0, 1fr); } }

/* ---- §7 Visual-Parity: Blasen-Landkarte + Strategie-/Registry-Karten ---- */
.chart-point-label { fill: var(--fg-dim); font-size: 10px; pointer-events: none; }
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-3); }
.mini-card { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); background: var(--surface-1); min-width: 0; }
.mini-card.is-locked { border-color: color-mix(in srgb, var(--negative) 45%, var(--border-subtle)); }
.mini-card.is-champion { border-color: color-mix(in srgb, var(--positive) 45%, var(--border-subtle)); }
.mini-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); flex-wrap: wrap; }
.mini-card-title { font-weight: 700; overflow-wrap: anywhere; }
.mini-card-sub { font-size: 11px; color: var(--fg-muted); overflow-wrap: anywhere; }
.mini-card-tags { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: var(--space-2); }
.mini-card-foot { margin-top: var(--space-2); font-size: 11px; color: var(--fg-muted); }

/* ---- §7 Visual-Parity: Kategoriefarben für Balken + Inline-Anteilsbalken in Zellen ---- */
.chart-bar.series-0 { fill: var(--chart-1); } .chart-bar.series-1 { fill: var(--chart-2); } .chart-bar.series-2 { fill: var(--chart-3); }
.chart-bar.series-3 { fill: var(--chart-4); } .chart-bar.series-4 { fill: var(--chart-6); } .chart-bar.series-5 { fill: var(--chart-7); }
.chart-bar.series-6 { fill: var(--chart-8); } .chart-bar.series-7 { fill: var(--neutral); }
.cell-share { display: inline-flex; align-items: center; gap: 6px; justify-content: flex-end; }
.cell-bar { display: inline-block; width: 48px; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.cell-bar > i { display: block; height: 100%; background: var(--accent); }
/* Vollbreite Auslastungsspur (Zielbild „Risikobudget"): gleiche Mechanik wie die
   Zellenspur, nur ueber die ganze Kartenbreite und mit Verlauf. */
.cell-bar.is-wide { display: block; width: 100%; height: 8px; border-radius: 999px; }
.cell-bar.is-wide > i { background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent)); border-radius: 999px; }
.cell-bar.is-wide.is-up > i { background: linear-gradient(90deg, color-mix(in srgb, var(--positive) 55%, transparent), var(--positive)); }
.cell-bar.is-wide.is-flat > i { background: linear-gradient(90deg, color-mix(in srgb, var(--warning) 55%, transparent), var(--warning)); }
.cell-bar.is-wide.is-down > i { background: linear-gradient(90deg, color-mix(in srgb, var(--negative) 55%, transparent), var(--negative)); }

/* ---- Grenzwert-Kacheln (0.5.36) ----
   Die Auslastung der neun Grenzwerte stand vorher nur als Fliesstext in einer
   Kennzahlen-Liste („… · 47 % ausgelastet"). Jetzt: grosser Ist-/Grenzwert,
   rechts der Prozentsatz, darunter die Spur — wie im Entwurf. Ohne Ist-Wert
   ODER ohne Grenze bleibt die Spur WEG; ein 0-%-Balken waere eine Aussage,
   die es nicht gibt. Die Zustandsfarbe steht immer zusaetzlich als Zahl. */
.limit-meter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-3); }
.limit-meter {
  min-width: 0; padding: 10px 12px; border-radius: var(--radius);
  background-color: var(--surface-1); background-image: var(--card-sheen);
  border: 1px solid var(--border-subtle); box-shadow: var(--card-edge);
}
.limit-meter-label { font-size: 12px; color: var(--text-secondary); }
.limit-meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); margin: 2px 0 6px; }
.limit-meter-value { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.limit-meter-pct { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.limit-meter.is-up .limit-meter-pct { color: var(--positive); }
.limit-meter.is-flat .limit-meter-pct { color: var(--warning); }
.limit-meter.is-down .limit-meter-pct { color: var(--negative); }
.limit-meter.is-down { border-color: color-mix(in srgb, var(--negative) 46%, var(--border-subtle)); }
.limit-meter-foot { display: flex; justify-content: space-between; gap: var(--space-2); margin-top: 6px; font-size: 11px; color: var(--text-muted); overflow-wrap: anywhere; }

/* ---- §7 Visual-Parity: Kriterien-Regler der Kanten-Analyse ---- */
.crit-tools { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-2); }
.crit-field { display: flex; flex-direction: column; gap: 2px; }
.crit-label { font-size: 11px; color: var(--text-secondary); font-weight: 600; }
.crit-input { width: 110px; }

/* ---- 0.1.46 §NAV-2: Wirkungs-Badge der Konto-Linse (Kopfzeile, kein Banner) ---- */
.app-lens-effect { flex: 0 0 auto; white-space: nowrap; align-self: center; }
.app-lens-effect.is-partial { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.app-lens-effect.is-off { color: var(--fg-muted); border-color: var(--border-subtle); }
.app-lens-effect[hidden] { display: none; }

/* ---- 0.1.46 §NAV-6/8: gruppierte zweite Navigationsebene ----------------------
   Die Untermenüs der Seitenleiste tragen Gruppenüberschriften mit Trenner; die
   Reiterleiste derselben Seite bekommt dieselben Gruppen als Inline-Trenner,
   damit lange Reiterleisten lesbar bleiben statt endlos zu scrollen. Mobil
   bleiben ALLE Untermenüpunkte über die linke Offcanvas erreichbar (Bestand). */
/* 27.07.: Deutlicher Luftraum ÜBER jeder Gruppenüberschrift — vorher klebte sie
   am letzten Punkt der vorigen Gruppe und der Trenner wirkte wie ein Unterstrich
   des darüberliegenden Menüpunkts. */
.nav-sub-group {
  /* --space-5 ist NIRGENDS definiert (die Skala kennt 1/2/3/4/6/8) — die Regel
     war ungueltig und die Gruppenueberschrift verlor ihren gesamten oberen
     Aussenabstand. */
  list-style: none; margin: var(--space-4) 0 2px; padding: 0 0 0 var(--space-2);
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg-muted); border-top: 1px solid var(--border-subtle); padding-top: var(--space-3);
}
.nav-sub-group:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.tabbar-group {
  flex: 0 0 auto; align-self: center; white-space: nowrap; padding: 0 var(--space-2) 0 var(--space-3);
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-muted);
  border-left: 1px solid var(--border-subtle);
}
.tabbar-group:first-child { border-left: 0; padding-left: 0; }
@media (max-width: 768px) { .tabbar-group { display: none; } }

/* ---- 0.1.46 §7 Visual-Parity: Client-Filterleiste über Tabellen (System-Audit) ----
   Rein darstellende Filter (Chips/Segment/Volltext) — sie lösen KEINEN Abruf aus. */
.log-toolbar {
  display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
.log-toolbar .chip-row { margin-bottom: 0; }
.log-search { width: auto; min-width: 180px; flex: 1 1 180px; }
@media (max-width: 640px) { .log-toolbar { align-items: stretch; } .log-search { flex-basis: 100%; } }

/* ---- 0.1.46 §7 Visual-Parity: Einstellungs-Formular (Klartext, Regler, Struktur) ----
   Klartext-Titel + Einheit über dem rohen Dot-Pfad, Zustands-Badge für Boolesche,
   Bereichsbalken/Prozent-Lesart für Zahlen mit Zod-Bereich, ausklappbarer Volltext
   für strukturierte Werte (R:R-Leiter). Rein additiv zur bestehenden Zeile. */
.cfg-label { font-weight: 600; }
.cfg-unit { font-size: 11px; color: var(--fg-muted); }
.cfg-row-head .cfg-path { color: var(--fg-muted); margin-left: auto; }
.cfg-live { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 45%, transparent); }
.cfg-bool.is-up { color: var(--positive); }
.cfg-bool.is-down { color: var(--fg-muted); }
.cfg-pct { font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.cfg-range {
  display: inline-block; position: relative; width: 120px; height: 6px;
  background: var(--bg-elev-2); border: 1px solid var(--border-subtle); border-radius: 3px; overflow: hidden;
}
.cfg-range-fill { position: absolute; inset: 0 auto 0 0; background: var(--accent); display: block; }
.cfg-struct { min-width: 0; }
.cfg-struct > summary { cursor: pointer; }
.cfg-json {
  margin: var(--space-2) 0 0; padding: var(--space-2); max-height: 260px; overflow: auto;
  background: var(--bg-elev-2); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; white-space: pre;
}
/* 0.5.35: Eingabefeld für strukturierte Werte (u. a. die R:R-Leiter
   exit.takeProfits). Volle Zeilenbreite, damit die Stufen lesbar untereinander
   stehen — in der schmalen Flex-Zeile wäre die Leiter unbrauchbar. */
.cfg-json-input {
  flex-basis: 100%; width: 100%; min-height: 140px; resize: vertical;
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px;
  line-height: 1.45; white-space: pre; overflow-wrap: normal; overflow-x: auto;
}
.cfg-slider { flex: 1 1 160px; min-width: 120px; accent-color: var(--accent); }
.cfg-live-hint { flex-basis: 100%; font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* Strategie-Karten der Einstellungen (Karten-Grid statt alphabetischer Pfadliste). */
.strat-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-3); }
.strat-card { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-2) var(--space-3); }
.strat-card-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.strat-card-name { font-weight: 600; overflow-wrap: anywhere; }
.strat-card-sub { font-size: 11px; color: var(--fg-muted); margin-top: 2px; }
.strat-card-params { margin-top: var(--space-2); }
.strat-card-params > summary { cursor: pointer; font-size: 12px; color: var(--fg-muted); }
@media (max-width: 700px) { .cfg-row-head .cfg-path { margin-left: 0; flex-basis: 100%; } }

/* ---- 0.1.46 §NAV-5: Slot-Raster der Experimente A–D ---------------------------
   Ein NICHT angelegter Slot ist bewusst sichtbar (gestrichelte, gedämpfte Karte)
   statt weggelassen — sonst sähe „drei Slots frei" wie „drei Slots fehlen" aus. */
.exp-slots .mini-card.is-empty { border-style: dashed; opacity: .7; }
.exp-slots .mini-card.is-empty .mini-card-title { color: var(--fg-muted); }

/* ---- 0.1.46 §7 Visual-Parity: Intelligence (Klassen-Tachos, Lagebericht-Karten,
   Aktions-Gruppen). Rein additiv — bestehende Panels bleiben unveraendert. ---- */
.gauge-cell-sub { font-size: 11px; color: var(--fg-muted); margin-top: 2px; text-align: center; }
.class-report-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-3); margin-top: var(--space-2); }
.class-report-card { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-2) var(--space-3); }
.class-report-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.class-report-name { font-weight: 600; }
.class-report-conf { font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.class-report-summary { margin: var(--space-2) 0 0; font-size: 13px; line-height: 1.45; }
.action-group { margin-top: var(--space-3); }
.action-group:first-child { margin-top: 0; }
.action-group-title { margin: 0 0 var(--space-2); font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-muted); }

/* ---- 0.1.46 §7 Visual-Parity: Stimmungs-Karten je Klasse (Bull/Bär/Neutral) ---- */
.tone-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-3); }
.tone-card { border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); padding: var(--space-2) var(--space-3); }
.tone-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.tone-card-name { font-weight: 600; }
.tone-card-net { font-size: 12px; font-variant-numeric: tabular-nums; }
.tone-ratio { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--bg-elev-2); margin: var(--space-2) 0; }
.tone-seg { display: block; height: 100%; }
.tone-seg.is-up { background: var(--positive); }
.tone-seg.is-down { background: var(--negative); }
.tone-seg.is-flat { background: var(--border); }
.tone-card-sub { font-size: 11px; color: var(--fg-muted); }

/* ---- 0.2.7: STRUKTURELL EIGENSTAENDIGE ANMELDEANSICHT -----------------------
   Ohne bestaetigte Sitzung enthaelt die Root ausschliesslich `.login-view`.
   Keine Shell wird per CSS ueberdeckt oder versteckt; `auth-only` definiert nur
   die Einflaechen-Geometrie des tatsaechlich gemounteten Auth-DOM. */
.app-root.auth-only { display: block; min-height: 100dvh; }
.login-view {
  display: grid; place-items: center; min-height: 100dvh;
  padding: max(var(--space-4), env(safe-area-inset-top)) max(var(--space-4), env(safe-area-inset-right))
    max(var(--space-4), env(safe-area-inset-bottom)) max(var(--space-4), env(safe-area-inset-left));
}
.login-card {
  width: min(380px, 100%); display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-8) var(--space-6);
  background: var(--surface-1); border: 1px solid var(--border-soft);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.login-brand { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
/* Original-Asset unveraendert (SHA-gesichert): keine Filter, kein Schatten, keine Invertierung. */
.login-logo { width: 112px; height: 112px; display: block; }
.login-word { font-weight: 700; font-size: 18px; letter-spacing: 0.02em; color: var(--text-primary); }
.login-title { margin: 0; text-align: center; font-size: 15px; font-weight: 600; color: var(--text-secondary); }
.login-form { display: flex; flex-direction: column; gap: var(--space-3); margin: 0; }
.login-field { display: flex; flex-direction: column; gap: var(--space-1); }
.login-label { font-size: 12px; color: var(--fg-muted); }
.login-input { font-size: 14px; }
.login-error {
  margin: 0; padding: var(--space-2) var(--space-3); font-size: 13px;
  color: var(--negative); background: var(--negative-soft);
  border: 1px solid var(--negative); border-radius: var(--radius-sm);
}
/* Sperr-/Drosselzustand des Servers (locked=true) ist kein Tippfehler-Fall — er
   wird als Warnung statt als Fehler gefaerbt, damit der Unterschied sichtbar ist. */
.login-error.is-locked { color: var(--warning); background: var(--warning-soft); border-color: var(--warning); }
.login-error[hidden] { display: none; }
.login-submit {
  padding: 8px 12px; font-size: 14px; font-weight: 600;
  background: var(--accent-solid); color: var(--accent-fg); border-color: var(--accent-solid);
}
.login-submit:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.login-submit:disabled { opacity: 0.6; cursor: progress; }
/* Sichtbarer Fokus auf ALLEN Bedienelementen der Anmeldung (Tastaturbedienung). */
.login-submit:focus-visible, .login-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Mobil ab 360px nutzbar: die Karte schrumpft mit (min(380px, 100%)), die Ansicht
   zentriert ohne feste Mindesthöhe, Touch-Ziele ≥ 40px erbt sie von .ui-btn/.ui-input. */
@media (max-width: 768px) { .login-view { min-height: 100dvh; } }
@media (max-width: 480px) {
  .login-card { padding: var(--space-6) var(--space-4); }
  .login-logo { width: 88px; height: 88px; }
  .login-input, .login-submit { min-height: 40px; }
}
.cmd-form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:12px}
.cmd-field{display:grid;gap:5px;color:var(--muted);font-size:12px;min-width:0}
.cmd-field>.ui-input{width:100%;min-width:0}
@media (max-width:768px){
  .cmd-form-grid{grid-template-columns:minmax(0,1fr)}
  .log-toolbar>.ui-input,.log-toolbar>.ui-btn{width:100%;min-width:0}
  .ui-dialog{max-height:calc(100dvh - 2 * var(--space-4));overflow:auto}
  .ui-dialog-actions{flex-wrap:wrap}
  .ui-dialog-actions>.ui-btn{flex:1 1 140px;min-height:40px}
}

/* ---- 0.3.1: Legacy Portfolio-Exposure als responsiver Donut -----------------
   Reine Darstellung des vorhandenen Positions-Payloads. Die sechs Farben sind
   die stabile Reihenfolge der Design-System-Palette; Long/Short bleiben zusätzlich textlich benannt. */
.portfolio-exposure-panel .panel-titlewrap {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; min-width: 0;
}
.exposure-anomaly-badge { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.expo-donut-layout {
  display: grid; grid-template-columns: minmax(190px, .8fr) minmax(260px, 1.2fr);
  align-items: center; gap: clamp(var(--space-4), 3vw, var(--space-8)); min-width: 0;
}
.expo-donut-figure { display: grid; place-items: center; min-width: 0; margin: 0; }
.expo-donut-svg { display: block; width: min(260px, 100%); height: auto; overflow: visible; }
/* Farbquelle je Reihe EINMAL definiert (0.5.36): Ring UND Legendenpunkt lesen
   dieselbe Variable und koennen nicht mehr auseinanderlaufen. Vorher standen
   dieselben sechs Hexwerte zweimal in der Datei — zwoelf hartcodierte Farben,
   die der Hellmodus unveraendert geerbt hat.
   Reihe 5 ist laut exposureDonutModel immer die Sammelgruppe "Weitere (n)" —
   deshalb --neutral statt einer Serienfarbe. --chart-5 bleibt bewusst aus: Rot
   ist hier die Verlustfarbe, kein Symbol. */
.expo-donut-series-0 { --expo-color: var(--chart-1); }
.expo-donut-series-1 { --expo-color: var(--chart-2); }
.expo-donut-series-2 { --expo-color: var(--chart-3); }
.expo-donut-series-3 { --expo-color: var(--chart-4); }
.expo-donut-series-4 { --expo-color: var(--chart-6); }
.expo-donut-series-5 { --expo-color: var(--neutral); }
/* Spur: --border-default, NICHT --surface-3 — letzteres ist in BEIDEN Themes
   schwaecher als die bisherige Spur und waere gegen --surface-1 kaum sichtbar. */
.expo-donut-track { fill: none; stroke: var(--border-default); stroke-width: 15; }
/* Schein nur im Dunkelmodus: Hell setzt --chart-line-glow auf 0px und
   --glow-strength auf 0, dieselbe Regel bleibt dort wirkungslos. */
.expo-donut-segment {
  fill: none; stroke: var(--expo-color); stroke-width: 15;
  filter: drop-shadow(0 0 var(--chart-line-glow) color-mix(in srgb, var(--expo-color) calc(var(--glow-strength) * 100%), transparent));
}
.expo-donut-total {
  fill: var(--fg); font-size: 12px; font-weight: 750; font-variant-numeric: tabular-nums;
}
.expo-donut-total.is-long { font-size: 8px; }
.expo-donut-center-label { fill: var(--fg-muted); font-size: 6px; }
.expo-donut-details { display: grid; gap: var(--space-4); min-width: 0; }
.expo-donut-legend { display: grid; gap: 4px; min-width: 0; }
.expo-donut-legend-row {
  display: grid; grid-template-columns: 10px minmax(0, 1fr) auto auto;
  align-items: center; gap: var(--space-2); min-width: 0; padding: 3px 0;
  font-size: 11px; border-bottom: 1px solid var(--border-soft);
}
.expo-donut-legend-row:last-child { border-bottom: 0; }
.expo-donut-swatch { width: 9px; height: 9px; border-radius: 3px; }
/* Legendenpunkt liest dieselbe --expo-color wie der Ring — eine Farbquelle. */
.expo-donut-swatch { background: var(--expo-color); }
.expo-donut-symbol { color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.expo-donut-value, .expo-donut-share { font-variant-numeric: tabular-nums; white-space: nowrap; }
.expo-donut-share { color: var(--fg); }
.expo-donut-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.expo-donut-summary-item {
  display: grid; gap: 2px; min-width: 0; padding: var(--space-2);
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1);
}
.expo-donut-summary-label, .expo-donut-summary-sub { color: var(--fg-muted); font-size: 10px; }
.expo-donut-summary-value { font-size: 13px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.expo-anomaly-note { margin-top: var(--space-3); }
@media (max-width: 700px) {
  .expo-donut-layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .expo-donut-svg { width: min(220px, 76vw); }
}
@media (max-width: 420px) {
  .expo-donut-legend-row { grid-template-columns: 10px minmax(0, 1fr) auto; }
  .expo-donut-value { display: none; }
  .expo-donut-summary { grid-template-columns: minmax(0, 1fr); }
}
