/* ==========================================================================
   BASE CSS — Fundament für alle Seiten
   ========================================================================== */

/* ── Status-Farben (Light) ───────────────────────────────── */
:root {
    --status-draft-bg:     #fef3c7; --status-draft-text:     #92400e;
    --status-preview-bg:   #dbeafe; --status-preview-text:   #1e40af;
    --status-hold-bg:      #fde8e8; --status-hold-text:      #991b1b;
    --status-published-bg: #d1fae5; --status-published-text: #065f46;
    --status-success-bg:   #d1fae5; --status-success-text:   #065f46;
    --status-error-bg:     #fef2f2; --status-error-text:     #dc2626;
    --status-warning-bg:   #fffbeb; --status-warning-text:   #b45309;
    --status-info-bg:      #dbeafe; --status-info-text:      #1d4ed8;
    /* Eigener Rahmen-Ton: die Textfarbe als Rahmen zu nehmen macht den Info-Kasten
       lauter als den Fehler-Kasten (dessen Rahmen ist ein -200er Pastellton). */
    --status-info-border:  #bfdbfe;
    /* Fünfter Schweregrad für Admonitions (.admonition--important) — derselbe
       lila-Akzent wie --text-link, als eigenes Paar benannt, damit die Zuordnung
       zum Schweregrad-System (Zeile oben) konsistent bleibt statt eine fremde
       Variable zweckzuentfremden. */
    --status-important-bg:   #f3e8ff; --status-important-text: #6d28d9;
    --text-link:           #6d28d9;   /* Premium/Sonderstatus, lila-Akzent */

    /* Signal-Semantik für Stock-Detail — verwendet von .sig-up/.sig-down
       (app.css:2439), .tech-score-banner__score--high/--low/--neutral,
       .variant-historical-hint, .coverage-warning und den Mail-Templates. */
    --signal-up:           #15803d;
    --signal-up-bg:        #f0fdf4;
    --signal-down:         #b91c1c;
    --signal-down-bg:      #fef2f2;
    --signal-neutral:      #71717a;
}
[data-theme="dark"] {
    --status-draft-bg:     #422006; --status-draft-text:     #fde68a;
    --status-preview-bg:   #1e3a5f; --status-preview-text:   #93c5fd;
    --status-hold-bg:      #7f1d1d; --status-hold-text:      #fca5a5;
    --status-published-bg: #14532d; --status-published-text: #86efac;
    --status-success-bg:   #14532d; --status-success-text:   #86efac;
    --status-error-bg:     #7f1d1d; --status-error-text:     #fca5a5;
    --status-warning-bg:   #422006; --status-warning-text:   #fde68a;
    --status-info-bg:      #1e3a5f; --status-info-text:      #93c5fd;
    --status-info-border:  #1e3a8a;
    --status-important-bg:   #3b0764; --status-important-text: #c4b5fd;
    --text-link:           #c4b5fd;

    --signal-up:           #4ade80;
    --signal-up-bg:        #052e16;
    --signal-down:         #f87171;
    --signal-down-bg:      #5a1a1a; /* aufgehellt von #450a0a — Kontrast gegen text-main */
    --signal-neutral:      #a1a1aa;
}

/* ==========================================================================
   SELF-HOSTED INTER FONT (Variable Font, latin + latin-ext)
   ========================================================================== */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('/fonts/inter-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('/fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   MARKET INSIDER - MODERN DATA GRID (OPTIMIZED & FIXED)
   ========================================================================== */

/* 1. VARIABLEN & THEMES */
:root {
    /* --- UI BASIS (MD3) --- */
    --bg-app:       #f9f9ff;
    --bg-panel:     #ffffff; /* from surface-container-lowest */
    --text-main:    #111c2d;
    --text-muted:   #424754;
    --border-color: #c2c6d6;
    --border-strong:#727785;

    /* --- MD3 Surfaces --- */
    --surface-container:     #e7eeff;
    --surface-container-low: #f0f3ff;
    --surface-container-high:#dee8ff;
    --surface-dim:           #cfdaf2;
    --primary-container:     #2170e4;
    --on-primary-container:  #fefcff;
    --accent:                #3b82f6;   /* Generischer Akzent (Tabs, Fokus-Outline, Akzent-Text) — schaltet jetzt mit dem Theme */
    --primary:               #3b82f6;   /* Fokus-/Primary-Akzent (gleicher Wert wie --accent) */

    /* Snap-Tone-Tokens (Blau/Orange, NICHT Gruen/Rot — Projekt-Konvention wegen
       Farbsehschwaeche). Duplikat der Werte aus app.css: dort fuer den Stock-
       Detail-Header, hier fuer die \layout\spark\SparkChart-Familie, die in der
       Editorial-Artikel-Zone (WebsiteLayout laedt app.css nicht) genutzt wird. */
    --snap-up-text:   #1d4ed8;
    --snap-down-text: #c2410c;
    --secondary:             #545f73;
    --secondary-container:   #d5e0f8;
    --tertiary:              #825100;
    --tertiary-container:    #a36700;
    --on-tertiary-container: #fffbff;

    /* Hover-/Selektions-Overlay (Listen, nav-drawer, Quick-Search) */
    --hover-bg: rgba(0,0,0,0.05);

    /* RGB-Triplet des Primärtons für Alpha-Tints (Sidebar-Active, Primary-
       Schatten) — Site-CSS-Dateien überschreiben es zusammen mit --btn-primary-* */
    --brand-tint: 0, 88, 190;

    /* --- RADIEN --- */
    --radius-xs:  0.125rem;
    --radius-sm:  0.25rem;
    --radius-md:  0.5rem;
    --radius-lg:  0.75rem;
    --radius-full: 9999px;

    /* --- SCHATTEN --- */
    --shadow-xs:  0 1px 2px rgba(0,0,0,0.05);
    --shadow-sm:  0 2px 6px rgba(0,0,0,0.08);
    --shadow-md:  0 4px 12px rgba(0,0,0,0.12);
    --shadow-lg:  0 8px 24px rgba(0,0,0,0.15);
    --shadow-xl:  0 12px 32px rgba(0,0,0,0.18);
    --shadow-focus: 0 0 0 3px rgba(var(--brand-tint), 0.15);
    --shadow-primary-sm: 0 1px 3px rgba(var(--brand-tint), 0.3);
    --shadow-primary-md: 0 2px 8px rgba(var(--brand-tint), 0.15);
    --shadow-primary-lg: 0 4px 16px rgba(var(--brand-tint), 0.3);

    /* --- ABSTÄNDE --- */
    --space-xs:  0.25rem;
    --space-sm:  0.5rem;
    --space-md:  1rem;
    --space-lg:  1.5rem;
    --space-xl:  2rem;
    --space-2xl: 3rem;

    /* --- LAYOUT --- */
    /* 38px = 26px Kompakt-Controls (.btn--sm-Maß, siehe .app-toolbar .btn/.toolbar-input
       weiter unten) + 6px Luft je Seite, gleiches Verhältnis wie vorher (42px/30px). */
    --toolbar-height: 38px;

    /* --- TYPOGRAFIE --- */
    --font-mono: ui-monospace, 'Cascadia Code', Menlo, Consolas, 'Liberation Mono', monospace;

    /* --- BUTTONS (Light) --- */
    --btn-bg:       #ffffff;
    --btn-text:     #111c2d;
    --btn-border:   #c2c6d6;
    --btn-shadow:   0 1px 2px rgba(0,0,0,0.05);

    /* Primary Action (Blau MD3) */
    --btn-primary-bg:    #0058be;
    --btn-primary-hover: #004a9e; /* Unchanged, kept from original */
    --btn-primary-text:  #ffffff;

    /* Fokusring auf bewusst hell gehaltenen Trägerflächen (z. B. .lexikon-svg,
       das seinen weißen Hintergrund in BEIDEN Themes literal setzt — siehe
       Begründung dort). Absichtlich NICHT im Dark-Block gespiegelt: die Fläche
       darunter wechselt nicht mit, und jeder helle Dark-Ton läge dort bei
       unter 2:1 statt der geforderten 3:1 (WCAG 1.4.11). */
    --focus-ring-on-light: #0058be;

    /* Success Action (Gruen) — quiz.css .quiz-step--answered / .quiz-nav__next--submit;
       paart mit --btn-primary-text, daher Light/Dark-Inversion analog --btn-primary-bg */
    --btn-success-bg:    #15803d;

    /* Upload-Progress-Stripe-Overlay (Light: heller Bar → weiße Streifen mit etwas Alpha) */
    --upload-stripe-overlay: rgba(255, 255, 255, 0.25);

    /* --- PIVOT FARBEN --- */
    /* Header & Level 0 */
    --pvt-header-bg:  #1e293b;
    --pvt-header-txt: #f1f5f9;

    /* Level 1: deutlich erkennbar als Gruppe */
    --pvt-lvl1-bg:    #e2e8f0;
    --pvt-lvl1-txt:   #1a1a2e;

    /* Level 2 & Daten */
    --pvt-lvl2-bg:    #f1f5f9;
    --pvt-lvl2-txt:   #1a1a2e;
    --pvt-bg-even:    #ffffff;
    --pvt-bg-odd:     #f8fafc;

    /* Spalten Summen — ttl_line/ttl_share dunkelst → clevel0 → clevel1 → clevel2 hellst */
    --pvt-col-total: #c2c8d2; /* Gesamt (ttl_line/ttl_share): dunkelster Ton */
    --pvt-col-0-bg: #d0d5dd; --pvt-col-0-txt: #1a1a2e; /* clevel0: kräftig */
    --pvt-col-1-bg: #dfe3ea; --pvt-col-1-txt: #1a1a2e; /* clevel1: mittel */
    --pvt-col-2-bg: #ebeef3; --pvt-col-2-txt: #1a1a2e; /* clevel2: dezent */

    /* Header-Overlay: Spaltenfarben halbtransparent über Header-Hintergrund */
    --pvt-col-total-overlay: rgba(194, 200, 210, 0.45);
    --pvt-col-0-overlay: rgba(208, 213, 221, 0.38);
    --pvt-col-1-overlay: rgba(223, 227, 234, 0.30);
    --pvt-col-2-overlay: rgba(235, 238, 243, 0.22);

    /* Interaktion */
    --pvt-hover:      rgba(59, 130, 246, 0.08);
    --pvt-marked:     #fef3c7;
    --pvt-marked-txt: #000000;

    /* Sekundäre Flächen (z.B. KPI-Kacheln) */
    --bg-secondary:    #f0f3ff;
    --text-secondary:  #545f73;

    /* Card-Hintergrund (Light) */
    --bg-card: #ffffff;

    /* Links */
    --link-color:       #0058be;
    --link-hover:       #004a9e;
    --link-visited:     #4a2d8a;

    /* Icons (Light Mode: Orange) */
    --theme-icon-color: #825100;
}

[data-theme="dark"] {
    /* --- UI DARK (MD3 Dark) --- */
    --bg-app:       #121318;
    --bg-panel:     #1d1e25;
    --text-main:    #e2e2e9;
    --text-muted:   #c4c6d0;
    --border-color: #2e3038;
    --border-strong:#44474f;

    /* --- MD3 Dark Surfaces --- */
    --surface-container:     #1d1e25;
    --surface-container-low: #191a20;
    --surface-container-high:#272830;
    --surface-dim:           #121318;
    --primary-container:     #004a9e;
    --on-primary-container:  #d8e2ff;
    --accent:                #60a5fa;   /* Hellerer Akzent für Dark (Kontrast auf dunklem Grund) */
    --primary:               #60a5fa;
    --snap-up-text:   #60a5fa;
    --snap-down-text: #fb923c;
    --secondary:             #bcc7de;
    --secondary-container:   #3c475a;
    --tertiary:              #ffb95f;
    --tertiary-container:    #653e00;
    --on-tertiary-container: #ffddb8;

    /* Hover-/Selektions-Overlay (Listen, nav-drawer, Quick-Search) */
    --hover-bg: rgba(255,255,255,0.08);

    /* Alpha-Tint-Triplet Dark (heller Primärton) — s. :root */
    --brand-tint: 173, 198, 255;

    /* --- BUTTONS (Dark) --- */
    --btn-bg:       #272830;
    --btn-text:     #e2e2e9;
    --btn-border:   #44474f;
    --btn-shadow:   0 1px 3px rgba(0,0,0,0.5);

    --btn-primary-bg:    #adc6ff;
    --btn-primary-hover: #d8e2ff;
    --btn-primary-text:  #001a3d;

    /* Dark: heller Success-Bg → dunkler --btn-primary-text bleibt lesbar */
    --btn-success-bg:    #86efac;

    /* Dark: heller Primary-Bar → dunkle Streifen für Sichtbarkeit */
    --upload-stripe-overlay: rgba(0, 0, 0, 0.25);

    /* --- PIVOT DARK --- */
    /* Header (thead): dunkelstes Schwarz */
    --pvt-header-bg: #0a0a0a; --pvt-header-txt:#e0e0e0;

    /* Zeilen-Gruppen: Level 0 = dunkelst, höhere Levels heller */
    --pvt-lvl1-bg:   #282828; --pvt-lvl1-txt:  #e0e0e0;
    --pvt-lvl2-bg:   #1e1e1e; --pvt-lvl2-txt:  #e0e0e0;

    /* Datenzeilen: neutrales Schwarz */
    --pvt-bg-even:   #111111;
    --pvt-bg-odd:    #141414;

    /* Spalten-Summen: ttl_line/ttl_share dunkelst → clevel0 → clevel1 → clevel2 hellst */
    --pvt-col-total: #050505; /* Gesamt (ttl_line/ttl_share): fast schwarz = dunkelst */
    --pvt-col-0-bg: #181818; --pvt-col-0-txt: #e0e0e0; /* clevel0: dunkel */
    --pvt-col-1-bg: #1e1e1e; --pvt-col-1-txt: #e0e0e0; /* clevel1: mittel */
    --pvt-col-2-bg: #252525; --pvt-col-2-txt: #e0e0e0; /* clevel2: hellst */

    /* Header-Overlay: Spaltenfarben halbtransparent über Header-Hintergrund */
    --pvt-col-total-overlay: rgba(255, 255, 255, 0.18);
    --pvt-col-0-overlay: rgba(255, 255, 255, 0.14);
    --pvt-col-1-overlay: rgba(255, 255, 255, 0.10);
    --pvt-col-2-overlay: rgba(255, 255, 255, 0.06);

    /* Akzentfarbe Blau nur für Interaktion */
    --pvt-hover:     rgba(59, 130, 246, 0.12);
    --pvt-marked:    #854d0e;
    --pvt-marked-txt:#ffffff;

    /* Sekundäre Flächen (z.B. KPI-Kacheln) */
    --bg-secondary:    #1d1e25;
    --text-secondary:  #bcc7de;

    /* Card-Hintergrund (Dark) */
    --bg-card: #1d1e25;

    /* Links (Dark: helles Blau, gut lesbar auf dunklem Hintergrund) */
    --link-color:       #8ab4f8;
    --link-hover:       #adc6ff;
    --link-visited:     #c58af9;

    /* Icons (Dark Mode: Blau-Akzent) */
    /* Folgt dem Primärton — Site-CSS-Overrides färben das Toggle-Icon mit */
    --theme-icon-color: var(--btn-primary-bg);
}

/* 2. APP LAYOUT (Full Screen) */
html, body {
    height: 100vh;
    margin: 0; padding: 0;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 15px;
    background-color: var(--bg-app);
    color: var(--text-main);
    overflow: hidden;
}

body {
    display: flex;
    flex-direction: column;
}
/* Scroll-Lock während ein Modal (z. B. DNS-Detail) offen ist — Klasse wird
   vom JS auf <body> getoggelt (code.js). */
body.app-modal-open {
    overflow: hidden;
}

a { color: var(--link-color); }
a:hover { color: var(--link-hover); }
a:visited { color: var(--link-visited); }

.app-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100vw;
    background-color: var(--bg-app);
}

/* Header */
.app-header {
    flex: 0 0 auto;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-color);
    overflow: hidden;
}
.header-branding {
    padding: 0.25rem 16px 0;
}

/* Per-Element Collapse beim Scrollen */
.scroll-collapse {
    max-height: 600px;
    opacity: 1;
    overflow: hidden;
    transition: max-height 0.3s cubic-bezier(0.4, 0.0, 0.2, 1)
      , opacity 0.3s ease
      , padding 0.3s ease
      , margin 0.3s ease;
}
body.compact-mode .scroll-collapse {
    max-height: 0; opacity: 0;
    padding-top: 0; padding-bottom: 0;
    margin-top: 0; margin-bottom: 0;
}

/* Border ausblenden wenn ALLE direkten Kinder collapsible sind */
body.compact-mode .app-header:not(:has(> :not(.scroll-collapse))) {
    border-bottom-color: transparent;
}
/* Seitentitel: ohne Basis-Regel zog der Browser-Default (2em/32px) — für eine App-Kopfzeile
   deutlich zu groß. Moderate Größe, klar über Nav/Body, aber nicht dominant. Der
   compact-mode (Scroll/Mobile) schrumpft weiter auf 1rem. */
.header-branding h1 {
    font-size: 1.375rem;
    line-height: 1.25;
    margin: 0;
    padding: 4px 0;
}
.header-branding-row { display: flex; align-items: center; gap: 8px; }
.header-branding-row h1 { flex: 1 1 auto; min-width: 0; }
/* Manueller Header-Collapse-Toggle: auf allen Viewports sichtbar, oben rechts
   in der header-branding-row (h1 hat flex:1 1 auto, der Button folgt am Zeilenende).
   Ergänzt den scroll-basierten Auto-Collapse (initCompactScroll) um ein sofortiges
   Einklappen ohne erst scrollen zu müssen — auch auf Desktop/Tablet gewünscht.
   MIT .btn QUALIFIZIEREN (Spezifität 0,2,0): `.btn { display: inline-flex }` steht
   ~180 Zeilen weiter unten bei sonst gleicher Spezifität (0,1,0) — unqualifiziert
   würde eine spätere .btn-Änderung dieses display() wieder überschreiben. */
.btn.header-collapse-toggle { display: inline-flex; flex: none; }
/* Drei Icon-Spans (Auto/Auf/Zu) — welcher sichtbar ist, entscheidet
   `data-header-mode` auf <body> (von app.toggleHeaderCompact gepflegt),
   NICHT `body.compact-mode`: der Modus (was der Nutzer eingestellt hat) und
   der aktuelle visuelle Collapse-Zustand (was die Scroll-Logik daraus macht)
   sind zwei verschiedene Dinge. `:not([data-header-mode])` deckt den Moment
   vor dem ersten JS-Tick ab (Default-Zustand ist "automatisch"). Einheitlich
   inline-flex (nicht auf den Browser-Default verlassen) — sonst springt
   .icon-svg beim Umschalten vertikal, weil vertical-align (Inline-Fluss) und
   Flex-Alignment unterschiedlich zentrieren. */
.header-collapse-toggle .hct-icon-auto,
.header-collapse-toggle .hct-icon-open,
.header-collapse-toggle .hct-icon-closed { display: none; align-items: center; }
body:not([data-header-mode]) .header-collapse-toggle .hct-icon-auto,
body[data-header-mode="auto"] .header-collapse-toggle .hct-icon-auto { display: inline-flex; }
body[data-header-mode="open"] .header-collapse-toggle .hct-icon-open { display: inline-flex; }
body[data-header-mode="closed"] .header-collapse-toggle .hct-icon-closed { display: inline-flex; }
@media (max-width: 768px) {
    /* 32px statt der 30px-Basishöhe: haelt das Touch-Target sicher über dem
       Mindestmaß (WCAG 2.2 SC 2.5.8: 24px). */
    .btn.header-collapse-toggle { height: 32px; }
}
/* H1 verkleinern im compact-mode auf Mobile */
body.compact-mode .header-branding h1 {
    font-size: 1rem;
    line-height: 1.2;
    margin: 0;
    padding: 6px 0;
    transition: font-size 0.3s ease, margin 0.3s ease, padding 0.3s ease;
}
p, li { margin: 0; padding: 6px 16px; font-size: 0.9375rem; line-height: 1.5; color: var(--text-muted); }
ul { list-style: none; padding-left: 1.2em; }
ul > li { position: relative; }
ul > li::before {
  content: '';
  position: absolute;
  left: -0.6em;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 10px;
  background: var(--border-strong);
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z'/%3E%3C/svg%3E");
  mask-size: contain;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
}

/* 3. TOOLBAR (Start + Center linksbuendig, End rechts via margin-left:auto) */
.app-toolbar {
    flex: 0 0 auto;
    height: var(--toolbar-height);
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    padding: 0 12px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-strong);
    position: relative;
}
/* Toolbar-Controls kompakter als der App-Default (.btn ist 30px/0.90rem — das ist
   die Größe für Modals/Formulare/Cards außerhalb von Toolbars und bleibt dort
   unveraendert). Toolbar-gescoped statt an der .btn-Basisklasse gedreht, sonst
   wären Buttons in der ganzen App betroffen. Werte = .btn--sm 1:1 (keine dritte
   Größen-Stufe erfinden). .toolbar-input ist bereits toolbar-exklusiv benannt,
   daher direkt an der Basisklasse (siehe unten). */
/* ACHTUNG Spezifität: .app-toolbar .btn (0,2,0) sticht ALLE .btn--*-Modifier (0,1,0).
   Ein künftiger .btn--lg IN der Toolbar würde hier still plattgedrückt — dann diese
   Regel ausnehmen statt am Modifier zu drehen. Für .btn--icon ist das bereits erledigt:
   die Höhe von 26px ist dort gewollt (quadratisch), nur das Horizontal-Padding muss
   weg — siehe die toolbar-gescopte Ausnahme beim .btn--icon-Block weiter unten. */
/* Gilt auch für ins Erweitert-Menü ausgelagerte Buttons: .toolbar-overflow-items liegt im
   .app-popover, NICHT in .app-toolbar — ohne die zweite Selektor-Hälfte fielen sie dort auf
   30px zurück und spränge derselbe Button beim Resize in der Größe. */
.app-toolbar .btn,
.toolbar-overflow-items .btn { height: 26px; padding: 0 8px; font-size: 0.78rem; }
/* Mobil zurück auf 32px: 26px unterschreitet das Touch-Target-Minimum, und die
   .filter-pill/.toggle-filter__btn in derselben Leiste wachsen hier ebenfalls auf 32px
   (sonst stünden 26px- neben 32px-Controls). Die 38px-Toolbar trägt 32px noch. Gerade mobil
   lagert das Overflow-JS die meisten Buttons ins Menü aus — die müssen zwingend mitwachsen. */
@media (max-width: 768px) {
  .app-toolbar .btn,
  .toolbar-overflow-items .btn,
  .toolbar-input { height: 32px; }
}
/* End-Gruppe (Startpage + UserMenu) rechts ankern */
.toolbar-group.end { margin-left: auto; }
/* Leere Gruppen erzeugen sonst sichtbaren gap-Versatz */
.toolbar-group:empty { display: none; }
/* Hamburger-Button (Mobile/Tablet) */
button.nav-hamburger { display: none; }
@media (max-width: 1024px) {
    .app-toolbar {
        overflow-x: auto;
        scrollbar-width: none;
    }
    .app-toolbar::-webkit-scrollbar { display: none; }
    .toolbar-group { flex-shrink: 0; }
    /* In der Scroll-Toolbar würde margin-left:auto die End-Gruppe an Center
       kleben (min-content shrink-wrap), nicht an den Viewport-Rand — Reset. */
    .toolbar-group.end { margin-left: 0; }
    /* Center nicht strecken in der H-Scroll-Toolbar (min-content), sonst bricht der Scroll. */
    .toolbar-group.center:has(.pivot-toolbar) { flex: 0 0 auto; }
    button.nav-hamburger { display: inline-flex; }
}

/* Gruppen-Reset: Keine automatischen Margins mehr */
.toolbar-group { display: flex; align-items: center; gap: 8px; margin: 0; }
/* Spezifische Klassen aus deinem HTML */
.pivot-toolbar { display: flex; align-items: center; flex: 1 1 auto; }
.pivot-toolbar-group { display: flex; gap: 8px; }
/* Emittenten-Suche: ein <form>-Block in der Center-Gruppe, Controls als Zeile.
   .form-control ist 100% breit (app.css) — hier scoped auf kompakte Toolbar-Breiten. */
.issuer-search { display: flex; align-items: center; gap: 8px; margin: 0; }
.issuer-search input.form-control  { width: 200px; }
.issuer-search select.form-control { width: auto; }
/* Eigenes GET-Form mit eigenem Submit (kein Filter-Panel mit "Anwenden"-Footer) —
   der "Suchen"-Button muss auch im ausgelagerten Erweitert-Menü sichtbar bleiben. */
.toolbar-overflow-items .issuer-search [type="submit"] { display: inline-flex; }
/* LogViewer-Filter (admin\LogViewer::renderFilterForm): gleicher Fall wie .issuer-search
   oben — eigenes GET-Form, eigener "Filtern"-Submit statt geteiltem Panel-Footer. */
.toolbar-overflow-items .log-filter-group [type="submit"] { display: inline-flex; }
/* Kalender-Reports (Dividenden-, Quartalszahlen-Kalender): Verlaufs-Sparkline füllt die
   (feste) Verlauf-Spalte exakt aus (preserveAspectRatio="none" → das SVG streckt sich auf
   100% Spaltenbreite). */
.cal-spark { display: block; line-height: 0; }
.cal-spark svg { width: 100%; height: 26px; display: block; }
/* Zweizeilige Datums-/Zeit-Zelle (Quartalszahlen-Kalender: „Nächster Bericht"/„Letzte VÖ"):
   Datum oben, typische Veröffentlichungs-Uhrzeit klein/gedämpft darunter — hält die Spalte
   schmal, statt die lange ET/DE-Angabe einzeilig abzuschneiden. */
.cal-next { display: inline-flex; flex-direction: column; line-height: 1.25; }
.cal-next__date { white-space: nowrap; }
.cal-next__time { font-size: .8em; color: var(--text-muted); }
/* Upsell-Teaser unter der gegateten Kalender-Tabelle (verborgene Termine / Private Markets). */
.cal-teaser { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; margin-top: 1.5rem; }
.cal-teaser .teaser-card { border: 1px solid var(--border-color); border-radius: 8px; padding: 1.25rem; background: var(--surface-container-low); }
.cal-teaser .teaser-card strong { display: block; margin-bottom: .4rem; }
.cal-teaser .teaser-card p { margin: 0 0 1rem; color: var(--text-muted); font-size: .9em; }
/* Center-Slot muss wachsen, damit die Heatmap-Gruppe real nach rechts rückt — sonst ist
   .toolbar-group.center inhaltsbreit und margin-left:auto wirkungslos. Nur wenn der Slot die
   Pivot-Toolbar trägt; andere Center-Inhalte bleiben kompakt. (:has()-loser Fallback: Heatmap
   steht dann hinter den Filtern statt flush rechts — kein Bruch.) */
.toolbar-group.center:has(.pivot-toolbar) { flex: 1 1 auto; }
/* Heatmap-Steuerung (🔥 + CB) ans rechte Toolbar-Ende, weg von den Filtern. */
.pivot-toolbar-right { margin-left: auto; }

/* Erweitert-Button: .toolbar-overflow-only = nur für Overflow (kein eigener Filter).
   Wird per JS eingeblendet wenn Overflow-Items vorhanden. */
.toolbar-overflow-only { display: none; }
/* Der Button trägt zusätzlich .btn (display:inline-flex, gleiche Spezifität, weiter
   unten deklariert) — ohne .btn-Qualifizierung gewinnt die Basis-Regel den Tie-Break und
   der Button erscheint trotz fehlendem Filter. Daher die Hide-Regel hier nachziehen. */
.btn.toolbar-overflow-only { display: none; }
/* Per JS (app.initToolbarOverflow) eingeblendet, sobald Overflow-Items vorhanden sind —
   deterministisch via Klasse statt Inline-Style (sonst Race mit obigem display:none). */
.btn.toolbar-overflow-only.is-overflow-active { display: inline-flex; }
.toolbar-sep.toolbar-overflow-only.is-overflow-active { display: block; }
/* Overflow-Container: Toolbar-Items behalten ihr kompaktes Inline-Layout */
.toolbar-overflow-items {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    padding: 4px 0;
}
.toolbar-overflow-items:empty { display: none; }
/* Individuelle Submit-Buttons im Overflow verstecken — Footer "Anwenden" übernimmt */
.toolbar-overflow-items [type="submit"] { display: none; }

.pivot-toolbar-sep, .toolbar-sep {
    width: 1px; height: 24px; background: var(--border-color); margin: 0 5px;
}

/* Pivot-Toolbar durchgehend icon-only: die gepinnten Steuerungen (Details / Alle
   öffnen / Alle schließen) zeigen nur ihr Symbol (+/−/Checkbox) + Tooltip; der Text
   (.pv-btn-label) ist ausgeblendet — Standard für alle Pivot-Reports, nicht nur mobil. */
.pivot-toolbar .pv-btn-label { display: none; }
/* Nur die icon-only gewordenen Buttons kompakter — Export u.a. (ohne
   .pv-btn-label) behalten ihr normales Padding samt Text. */
.pivot-toolbar .btn:has(.pv-btn-label) { padding-left: 8px; padding-right: 8px; }
/* Heatmap-Button „an": Standard- und alternativer (farbenblind) Modus durch
   UNTERSCHIEDLICHE Farben getrennt — Standard = Marker-Gelb, alternativ = Primär-Blau
   (passt zum farbenblind-Schema blau/orange). Beide Variablen sind dark-mode-aware. */
.pivot-heat-btn.active { background-color: var(--pvt-marked); }
.pivot-heat-btn.active.heat-alt { background-color: var(--btn-primary-bg); color: var(--btn-primary-text); }

/* 4. UNIFIED BUTTON SYSTEM */
.btn {
    background-color: var(--btn-bg);
    color: var(--btn-text);
    border: 1px solid var(--btn-border);
    box-shadow: var(--btn-shadow);

    /* border-box: height ist die *Gesamthoehe* — Rahmen + Padding-Overrides
       (.day-nav, .stat-filter-select) wachsen sonst über die 30px hinaus
       und die Toolbar-Felder werden unterschiedlich hoch. */
    box-sizing: border-box;
    border-radius: var(--radius-md);
    padding: 0 12px;
    height: 30px;
    font-size: 0.90rem;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    white-space: nowrap;
    transition: all 0.15s ease-in-out;
    text-decoration: none;
    font-family: inherit;
    line-height: 1.4;
}
/* Links als Buttons: nie Link-Farbe erben */
a.btn, a.btn:visited, a.btn:hover { color: inherit; text-decoration: none; }

.btn:hover {
    border-color: var(--border-strong);
    background-color: var(--bg-panel);
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(var(--brand-tint), 0.1);
}

.btn:active,
.btn.active {
    transform: translateY(0);
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
    background-color: var(--border-color);
}

/* Deaktivierter Button (nativ via [disabled] oder .is-disabled für Label-Wrapper):
   ausgegraut + not-allowed. Bewusst KEIN pointer-events:none (das würde Tooltip-
   Hover auf disabled Buttons töten — siehe admin-schedule.css); natives [disabled]
   blockt Klicks ohnehin, die enthaltene Checkbox trägt zusätzlich disabled. */
.btn:disabled,
.btn.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
/* Kein Hover-Lift auf deaktivierten Buttons (der Engine-Hover würde sonst greifen). */
.btn:disabled:hover,
.btn.is-disabled:hover {
    transform: none;
    box-shadow: var(--btn-shadow);
    border-color: var(--btn-border);
    background-color: var(--btn-bg);
}

/* Primary */
.btn--primary,
a.btn--primary, a.btn--primary:visited {
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    border-color: transparent;
    box-shadow: var(--shadow-primary-sm);
}
.btn--primary:hover,
a.btn--primary:hover {
    background-color: var(--btn-primary-hover);
    color: var(--btn-primary-text);
    box-shadow: 0 2px 6px rgba(var(--brand-tint), 0.35);
}

/* Secondary */
.btn--secondary, a.btn--secondary, a.btn--secondary:visited {
    background: var(--border-color, #e2e8f0);
    color: var(--text-main, #1a1a2e);
    border-color: transparent;
}
.btn--secondary:hover, a.btn--secondary:hover {
    background: var(--bg-panel, #d1d5db);
    color: var(--text-main);
}

/* Danger — #dc2626 mit weißer Schrift 4,8:1 (WCAG 2.1 AA, 1.4.3); das frühere #ef4444 lag bei 3,8:1 */
.btn--danger, a.btn--danger, a.btn--danger:visited {
    background: #dc2626;
    color: #fff;
    border-color: transparent;
}
.btn--danger:hover, a.btn--danger:hover { background: #b91c1c; color: #fff; }

/* Success / Warning — wurden benutzt (QuizDashboard „Zertifikat senden", billing
   „Sofort zurückstufen"), waren aber nie definiert: die Buttons rendern seither neutral.
   Farben = die dunklere Stufe der Signal-Tokens: mit weißer Schrift je 5,0:1 (WCAG 2.1 AA, 1.4.3) — die
   Signal-Töne #16a34a/#d97706 selbst lagen bei 3,3:1 bzw. 3,2:1. */
.btn--success, a.btn--success, a.btn--success:visited {
    background: #15803d;
    color: #fff;
    border-color: transparent;
}
.btn--success:hover, a.btn--success:hover { background: #166534; color: #fff; }

.btn--warning, a.btn--warning, a.btn--warning:visited {
    background: #b45309;
    color: #fff;
    border-color: transparent;
}
.btn--warning:hover, a.btn--warning:hover { background: #92400e; color: #fff; }

/* Outline */
.btn--outline {
    background: transparent;
    color: var(--btn-primary-bg);
    border-color: var(--btn-primary-bg);
}
.btn--outline:hover {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
}

/* Ghost (kein Border, kein Background) */
.btn--ghost {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--text-muted);
}
.btn--ghost:hover {
    background: var(--surface-container-low, #f0f3ff);
    color: var(--text-main);
}

/* Size: Small */
.btn--sm { padding: 0 8px; height: 26px; font-size: 0.78rem; }

/* Icon-only: quadratischer Button, dessen Bedeutung allein am Symbol + Tooltip
   hängt (Aktions-Spalten in Tabellen, wo beschriftete Buttons die Zeile sprengen).
   Bewusst KEINE eigene Breite: aspect-ratio greift nur, wenn eine Achse auto ist
   — mit fester width wäre die Deklaration tot und der Button müsste für jede
   Höhe (30px Standard, 26px --sm, 32px mobil) einzeln nachgepflegt werden.
   flex: none, weil die Gruppe ein Flex-Container ist und Pivot-Spalten vom
   Nutzer schmalgezogen werden können — sonst quetscht der Button, während das
   Icon (flex-shrink: 0) stehen bleibt und überläuft. */
.btn--icon { padding: 0; width: auto; aspect-ratio: 1; flex: none; }
/* Der Größen-Modifier .btn--lg steht weiter unten und würde sein Padding sonst
   per Quellreihenfolge zurückbringen — Content-Box auf 0, Icon läuft über.
   Die Toolbar-Variante (0,2,0) sticht die Modifier ohnehin und braucht dieselbe
   Neutralisierung; ihre 26px-Höhe bleibt richtig und wird nicht angefasst. */
.btn--lg.btn--icon, .btn--sm.btn--icon { padding: 0; }
.app-toolbar .btn--icon,
.toolbar-overflow-items .btn--icon,
.admin-search .btn--icon { padding: 0; }

/* Aktions-Gruppe einer Tabellenzeile (ein Formular, ein Submit-Button je Aktion).
   vertical-align, weil sich ein inline-flex sonst an der Baseline ausrichtet und
   die Tabellenzeile um die Unterlängen höher würde als ihre Nachbarn. */
.user-row-actions { display: inline-flex; gap: 4px; align-items: center; vertical-align: middle; }
/* Touch: 26px unterschreitet das Touch-Target-Minimum — dieselbe Anhebung wie
   bei den Toolbar-Controls oben, hier zusätzlich mit mehr Abstand, weil direkt
   nebeneinander destruktive Aktionen (Sperren, Deaktivieren) liegen. */
@media (max-width: 768px) {
  .user-row-actions { gap: 8px; }
  .user-row-actions .btn--icon { height: 32px; }
}

/* Size: Large (CTA Buttons) */
.btn--lg {
    padding: 12px 28px;
    height: auto;
    font-size: 0.95rem;
    font-weight: 600;
    border-radius: 6px;
}

/* Größen-Default für JEDES layout\SvgIcon-Icon. Die SVGs tragen nur ein viewBox,
   keine width/height — ohne Regel rendert der Browser sie in Ersatz-Elementgroesse
   (300x150px, faktisch bildschirmfuellend). Bisher musste JEDER Konsument die Größe
   über einen Eltern-Selektor setzen (.btn .icon-svg, .info-icon .icon-svg, …); wurde
   das vergessen, explodierte das Icon. Dieser Default macht SvgIcon eigenstaendig
   benutzbar; alle Eltern-Regeln (0,2,0) stechen ihn per Spezifität weiterhin aus. */
.icon-svg { width: 16px; height: 16px; vertical-align: middle; fill: currentColor; flex-shrink: 0; }

/* SVG Icons in Buttons */
.btn svg { width: 16px; height: 16px; stroke-width: 2.5; }
/* Nur die Abweichung vom globalen .icon-svg-Default (16px) — vertical-align/fill/
   flex-shrink kommen von dort. */
.btn .icon-svg { width: 18px; height: 18px; }

/* Kompakte Multi-Select-Toolbar-Filter (report\FilterDropdownRenderer, genutzt von
   SegmentFilterTrait + MarketCapFilterTrait + SectorFilterTrait): je ein Trigger-
   Button mit Count-Badge, der ein .app-popover mit Checkbox-Pillen oeffnet. Die
   Popover-Mechanik (Positionierung + Outside-Click) kommt aus code.js. */
.filter-dd { display: inline-flex; margin-left: 6px; }
.filter-dd__toggle { display: inline-flex; align-items: center; gap: 6px; }
.filter-dd__toggle--active { border-color: var(--btn-primary-bg); color: var(--btn-primary-bg); }
.filter-dd__caret { font-size: 0.7em; opacity: 0.7; }
.filter-dd__count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px;
    font-size: 0.7rem; font-weight: 700; line-height: 1;
    border-radius: 999px; background: var(--btn-primary-bg); color: var(--btn-primary-text);
}
/* Panel erbt .app-popover (position:fixed, z-index, Animation) aus app.css — hier
   nur das Innenleben. */
.filter-dd__panel { min-width: 240px; }
.filter-dd__close { cursor: pointer; }
/* Panel-scoped: gewinnt über .popover-body (gleicher Knoten trägt beide Klassen)
   bei max-height/overflow/padding — unabhängig von der CSS-Ladereihenfolge. */
.filter-dd__panel .filter-dd__opts { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 15px; max-height: 320px; overflow-y: auto; }
.filter-dd__form .popover-footer { display: flex; gap: 8px; align-items: center; }
.filter-dd__form .filter-dd__all { margin-right: auto; }

/* Multi-Select-Pille im Popover: die native Checkbox bleibt für JS (.fdd-cb-*) und
   Tastaturbedienung erhalten, liegt aber transparent über der Pille. */
.filter-pill {
    position: relative;
    display: inline-flex; align-items: center;
    padding: 0 12px; height: 26px;
    font-size: 0.78rem; font-weight: 500;
    border: 1px solid var(--btn-border); border-radius: 999px;
    background: var(--btn-bg); color: var(--btn-text);
    cursor: pointer; user-select: none;
    /* Nur die tatsächlich animierten Properties — sonst liefe der :focus-visible-outline
       durch die Transition (Fokus muss für Tastaturbedienung sofort sichtbar sein). */
    transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out,
                border-color 0.15s ease-in-out, transform 0.15s ease-in-out;
}
.filter-pill:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.filter-pill input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.filter-pill:has(input:checked) { background: var(--btn-primary-bg); color: var(--btn-primary-text); border-color: transparent; }
.filter-pill:has(input:focus-visible) { outline: 2px solid var(--link-color); outline-offset: 2px; }
/* Mobile: größeres Touch-Target (bestehender 768px-Breakpoint). */
@media (max-width: 768px) { .filter-pill { height: 32px; padding: 0 14px; } }

/* Segmented-Control / „Pill"-Umschalter für eine Einzelauswahl in Report-Toolbars (report\ToggleFilterTrait):
   Reihe von <a>-Optionen als ein gerundetes Segment, die aktive trägt .is-active. Anchor-basiert (navigiert),
   im Gegensatz zur input-basierten .filter-pill im Multi-Select-Popover. Nutzt dieselben Button-Tokens.
   flex-wrap:nowrap ist Absicht: app.initToolbarOverflow() (code.js) misst per scrollWidth, ob der Toolbar-
   Host überläuft, und lagert dann den HINTERSTEN Block als Ganzes ins Filter-Panel aus. Bräche die Gruppe
   VORHER intern selbst um (flex-wrap:wrap), würde sie ihre eigene Breite durch das Umbrechen "verstecken" —
   der Host misst dann keinen Überlauf mehr, die Gruppe bleibt in der Toolbar hängen und bricht dort sichtbar
   um (zwei Zeilen in einer Pille mit border-radius:999px + overflow:hidden — die zweite Zeile wird abgeschnitten). */
.toggle-filter {
    display: inline-flex; flex-wrap: nowrap; margin-left: 6px;
    border: 1px solid var(--btn-border); border-radius: 999px; overflow: hidden;
}
.toggle-filter__btn {
    display: inline-flex; align-items: center;
    height: 26px; padding: 0 14px;
    font-size: 0.78rem; font-weight: 500; text-decoration: none;
    color: var(--btn-text); background: var(--btn-bg);
    border-right: 1px solid var(--btn-border);
    transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
    white-space: nowrap;
}
.toggle-filter__btn:last-child { border-right: 0; }
.toggle-filter__btn:hover { color: var(--btn-primary-bg); }
.toggle-filter__btn.is-active { background: var(--btn-primary-bg); color: var(--btn-primary-text); }
@media (max-width: 768px) { .toggle-filter__btn { height: 32px; } }

/* Einmal im Filter-Panel (per Toolbar-Overflow ausgelagert oder von vornherein dort gerendert), darf die
   Gruppe wieder umbrechen — auf schmalen Phones passen "Marktkapitalisierung"/"Sektor"/"Handelsvolumen"
   selbst als eigene Panel-Zeile oft nicht nebeneinander. Die einzelne-Pillen-Optik (statt einer gemeinsam
   gerundeten Kapsel mit inneren Trennstrichen) matcht dabei bewusst .filter-pill aus demselben Panel — sonst
   hinge bei zwei Zeilen ein border-right auf dem Button, der jetzt am Zeilenende steht, aber nicht der
   tatsächliche DOM-.last-child ist. */
.toolbar-overflow-items .toggle-filter {
    flex-wrap: wrap; gap: 6px;
    border: 0; border-radius: 0; overflow: visible;
}
.toolbar-overflow-items .toggle-filter__btn {
    border: 1px solid var(--btn-border); border-radius: 999px;
}
.toolbar-overflow-items .toggle-filter__btn:last-child { border-right: 1px solid var(--btn-border); }

/* Report-Filter (report\FilterRenderer): ein Filter = <label class="report-filter"> mit Beschriftung
   und Steuerelement — in der Toolbar inline nebeneinander, im Erweitert-Formular je eine Zeile.
   Pill-Gruppen (.report-filter__pills) tragen .filter-pill-Häkchen/Radios aus demselben Panel. */
.report-filter { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.report-filter__label { font-size: 0.82rem; color: var(--text-muted); }
.report-filter__pills { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.report-filter-form { display: flex; flex-direction: column; gap: 10px; max-width: 64rem; }
/* Im Panel (Erweitert-Formular und per Overflow-JS verschobene Toolbar-Filter) je eine Zeile:
   Beschriftung in fester Spalte, Steuerelement direkt daneben. Früher space-between — auf breiten
   Bildschirmen (Panel über die volle Fensterbreite) lagen Beschriftung und Feld Tausende Pixel
   auseinander. max-width am Formular deckelt die Zeilenlänge zusätzlich. */
.report-filter-form .report-filter,
.toolbar-overflow-items .report-filter { display: flex; justify-content: flex-start; align-items: flex-start; gap: 12px; white-space: normal; }
.report-filter-form .report-filter > .report-filter__label,
.toolbar-overflow-items .report-filter > .report-filter__label { flex: 0 0 9rem; padding-top: 5px; /* auf Höhe der Pille/des Feldes (26–30px) ausrichten */ }
.report-filter-form .report-filter__pills { justify-content: flex-start; }
/* Schmale Phones: Beschriftung über dem Steuerelement statt in fester Spalte daneben */
@media (max-width: 480px) {
  .report-filter-form .report-filter,
  .toolbar-overflow-items .report-filter { flex-direction: column; gap: 4px; }
  .report-filter-form .report-filter > .report-filter__label,
  .toolbar-overflow-items .report-filter > .report-filter__label { flex: 0 0 auto; padding-top: 0; }
}
.report-filter__heading { margin: 6px 0 0; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.report-filter__sep { border: 0; border-top: 1px solid var(--border-color); margin: 4px 0; }

/* Datums-Perioden-Picker (report\PeriodNavTrait): ‹ Datumsfeld Mode-Dropdown › als ein Segment.
   Navigation via public/js/period-nav.js (data-url-template). */
.day-nav { display: inline-flex; align-items: center; margin-left: 6px; }
.day-nav .btn { padding: 4px 8px; margin: 0; line-height: 1; box-sizing: border-box; flex-shrink: 0; }
.day-nav__prev { border-radius: var(--radius-sm, 4px) 0 0 var(--radius-sm, 4px); border-right: 0; }
.day-nav__date { border-radius: 0; cursor: pointer; }
/* Tag/Monat sind native date/month-Inputs: Datum linksbündig, nativer Kalender-Button bleibt rechts sichtbar.
   Breite grosszügig, damit Datum + Button nicht abgeschnitten/gequetscht werden (Fix: 7.5rem war zu eng). */
.day-nav__date[type="date"]   { width: 9.5rem; min-width: 9.5rem; text-align: left; }
.day-nav__date[type="month"]  { width: 9.1rem; text-align: left; }
.day-nav__date[type="number"] { width: 4.5rem; text-align: center; }
.day-nav__mode { border-radius: 0; border-left: 0; cursor: pointer; }
.day-nav__next { border-radius: 0 var(--radius-sm, 4px) var(--radius-sm, 4px) 0; border-left: 0; }

/* 5. UNIFIED TABLE SYSTEM */
.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    text-align: left;
}
.data-table th,
.data-table td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-main);
}
.data-table th {
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-panel);
}
/* Compact (Help-Tabellen, Revision) */
.data-table--compact th,
.data-table--compact td { padding: 4px 8px; font-size: 0.8rem; }
/* Small (CMS-Listen) */
.data-table--sm th,
.data-table--sm td { padding: 6px 10px; font-size: 0.85rem; }
/* Striped rows */
.data-table--striped tbody tr:nth-child(even) td { background-color: var(--pvt-bg-even); }
.data-table--striped tbody tr:nth-child(odd) td  { background-color: var(--pvt-bg-odd); }
/* Row hover */
.data-table--hover tbody tr:hover td { background-color: var(--pvt-hover); }
/* Sticky header */
.data-table--sticky thead th { position: sticky; top: 0; z-index: 1; background: var(--pvt-lvl1-bg); color: var(--pvt-lvl1-txt); border-bottom: 1px solid var(--border-strong); }
/* Key-Value Layout (Label | Wert) */
.data-table--kv th { width: 180px; white-space: nowrap; background: var(--bg-panel); }
/* Header uppercase (CMS-Style) */
.data-table--caps th { text-transform: uppercase; letter-spacing: 0.03em; font-size: 0.8rem; }
/* No-wrap (Daten-Tabellen) */
.data-table--nowrap { white-space: nowrap; }
/* Code in Tabellen */
.data-table code { background: var(--bg-panel); padding: 1px 5px; border-radius: var(--radius-xs); font-size: 0.8rem; }
.text-right { text-align: right; }

/* SparkChart-Familie (\layout\spark\SparkChart) — Duplikat der Regeln aus
   app.css: dort für Report-/Dashboard-Widgets, hier für dieselbe Komponente
   in der Editorial-Artikel-Zone (WebsiteLayout lädt app.css nicht). Diverging-
   Balken (SparkBars/SparkWinLoss) tragen ihre Füllung selbst über .bar-*. */
.spark { display: inline-block; vertical-align: middle; }
.spark.is-positive { color: var(--snap-up-text); }
.spark.is-negative { color: var(--snap-down-text); }
.spark.is-neutral  { color: var(--text-muted); }
.spark.is-accent   { color: var(--accent); }
.spark.is-muted    { color: var(--text-muted); }
.spark .bar-pos     { fill: var(--snap-up-text); }
.spark .bar-neg     { fill: var(--snap-down-text); }
.spark .bar-neutral { fill: var(--text-muted); }
.spark .spark-base    { stroke: var(--text-muted); stroke-width: 0.5; stroke-opacity: 0.5; }
.spark .spark-mark    { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 1.5 1.5; }
.spark .bullet-target { stroke: var(--text-main); stroke-width: 1.5; }
.spark .spark-hit     { fill: transparent; }
.spark-empty { color: var(--text-muted); }

/* News-Duell-Profiteur-Snapshot (\marketdata\editorial\ArticleRenderer::financialsCharts())
   — zwei Mikro-Balkencharts (Umsatz/Jahresüberschuss) neben der Kennzahlen-
   tabelle, nicht statt ihr (Spec §6: Zahlen bleiben ECHTE HTML-Tabelle). */
.snapshot-charts {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: 8px 16px 16px;
}
.snapshot-chart {
  flex: 1 1 240px;
  min-width: 200px;
}
.snapshot-chart-label {
  margin: 0 0 4px;
  padding: 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}
/* BFSG/WCAG: Verweis auf die (barrierefreie) Tabelle darunter — die Werte je
   Balken stecken sonst nur im Hover-Tooltip, ohne Tastatur-/Screenreader-Weg. */
.snapshot-chart-hint {
  margin: 4px 0 0;
  padding: 0;
  font-size: 0.75rem;
}
.snapshot-chart .spark {
  width: 100%;
  height: auto;
}
/* X-Achse unter dem Balken-Chart: gleich breite Zellen wie die Balken-Slots.
   Seitenabstand = padX des SVG (1,5 von 320 Einheiten ≈ 0,47 %). */
.snapshot-chart-axis {
  display: flex;
  padding: 0 0.47%;
  font-size: 0.7rem;
  line-height: 1.3;
  color: var(--text-muted);
}
.snapshot-chart-axis span {
  flex: 1 1 0;
  min-width: 0;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Toolbar Input (z.B. Date-Picker, Filter-Selects). Größe = .btn--sm/.app-toolbar .btn
   (26px/0.78rem), Klasse ist bereits toolbar-exklusiv benannt/genutzt — direkt an der
   Basisklasse angepasst statt über einen zusätzlichen Scoping-Selektor. */
.toolbar-input {
  height: 26px;
  padding: 0 8px;
  font-size: 0.78rem;
  border: 1px solid var(--btn-border);
  border-radius: 6px;
  background: var(--btn-bg);
  color: var(--btn-text);
  box-shadow: var(--btn-shadow);
  box-sizing: border-box;
  transition: all 0.15s ease-in-out;
}
/* appearance:none nimmt dem Select den nativen Dropdown-Pfeil — ohne Ersatz war
   es optisch von einem Textfeld nicht zu unterscheiden. Chevron als Data-URI
   (gleiches Muster wie .pivot-collapse-* in app.css), Dark-Mode über eine
   zweite URI statt filter:invert — invert würde auch den Select-Grund kippen.
   ⚠ FALLE: jede Regel mit HÖHERER Spezifität als (0,1,1) — also alles ab zwei
   Klassen, z. B. `.x .field-input { padding: … }` — löscht das padding-right
   hier lautlos mit, und der Chevron läuft über den Options-Text. Wer Kompakt-
   Felder braucht, nimmt den Modifier `.field-input--inline` unten (eine Klasse,
   damit gewinnt diese Regel) statt einen Kontext-Selektor. */
select.toolbar-input,
select.field-input {
  appearance: none;
  padding-right: 26px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 7px center;
  background-size: 13px;
}
[data-theme="dark"] select.toolbar-input,
[data-theme="dark"] select.field-input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23cbd5e1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}
/* Beide Klassen setzen color + background hart und schlagen damit das
   UA-Ausgrauen gesperrter Controls — ohne Ersatz sah ein disabled-Feld aus wie
   ein bedienbares. Bewusst nicht auf select verengt: bei Text-Inputs (z. B.
   drei in admin\RoleAdmin) gilt derselbe Grund. */
.toolbar-input:disabled,
.field-input:disabled {
  opacity: 0.55;
  cursor: default;
}
.toolbar-input:focus,
.field-input:focus {
  outline: none;
  border-color: var(--btn-primary-bg);
  box-shadow: var(--shadow-focus);
}

/* Datums-Navigation (filter\date): Pfeile + Date-Input + Heute in einer Reihe.
   Auf Mobile blenden sich die Datums-Labels der Pfeile aus — nur ←/→ bleiben. */
.toolbar-date-nav,
.toolbar-date-nav__form {
  display: flex;
  align-items: center;
  gap: 6px;
}
.toolbar-date-nav__btn--disabled {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}
@media (max-width: 768px) {
  .toolbar-date-nav__label { display: none; }
}

/* Theme Toggle Special */
#btn-theme-toggle .theme-icon {
    color: var(--theme-icon-color); display: inline-flex; align-items: center;
    transition: transform 0.3s, filter 0.3s;
}
#btn-theme-toggle:hover .theme-icon { transform: rotate(20deg); }

/* Light Mode zeigt Mond → dunkler Schatten bei Hover */
[data-theme="light"] #btn-theme-toggle:hover .theme-icon {
    filter: drop-shadow(0 0 6px rgba(80, 50, 180, 0.8)) drop-shadow(0 0 14px rgba(80, 50, 180, 0.6)) drop-shadow(0 0 28px rgba(40, 20, 100, 0.5));
}
/* Dark Mode zeigt Sonne → warmer Glow bei Hover */
[data-theme="dark"] #btn-theme-toggle:hover .theme-icon {
    filter: drop-shadow(0 0 6px rgba(255, 180, 0, 0.9)) drop-shadow(0 0 14px rgba(255, 160, 0, 0.7)) drop-shadow(0 0 28px rgba(255, 120, 0, 0.5));
}

/* 5. WORKSPACE & TABLE CONTAINER */
.app-workspace {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    position: relative;
    contain: layout style;
    min-height: 0;
    padding: 0px 0px;
}
@media (max-width: 768px) {
    .app-workspace {
        overflow-x: auto;
    }
}
.app-workspace.loading {
    pointer-events: none;
    position: relative;
    min-height: 200px;
}
.app-workspace.loading > *:not(.page-loading-overlay) {
    opacity: 0.4;
    transition: opacity 0.15s;
}
.app-workspace.loading > .page-loading-overlay {
    opacity: 1;
}

/* Klasse statt ID: die ID trägt seit der Mehr-Instanzen-Umstellung eine Instanz-Kennung
   (\Pivot\Pivot::containerId) — das Aussehen gehört aber allen Pivot-Containern. */
.pivot-table-container {
    flex: 1;
    overflow: auto;
    width: 100%;
    position: relative;
    background-color: var(--bg-app);
    padding-top: 0; margin-top: 0;
}

/* ==========================================================================
   AUTH / USERMANAGEMENT STYLES
   ========================================================================== */

/* ── Guest Layout ────────────────────────────────────────────────────────── */
.app-shell--guest {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--bg-panel);
}
.app-shell--guest .app-header {
  position: static;
  text-align: center;
  border: none;
  background: transparent;
  padding: 24px 0 0;
}
.app-workspace--guest {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  width: 100%;
  padding: 24px;
}

/* ── Auth Card ───────────────────────────────────────────────────────────── */
.auth-card {
  background: var(--bg-app);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  padding: 32px;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--shadow-md);
}
.auth-card-title {
  margin: 0 0 8px;
  font-size: 1.4rem;
  color: var(--text-main);
}
.auth-subtitle {
  margin: 0 0 16px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* ── Auth Form ───────────────────────────────────────────────────────────── */
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 16px;
}
.auth-field label {
  display: block;
  margin-bottom: 4px;
  font-size: 0.90rem;
  font-weight: 600;
  color: var(--text-main);
}
.auth-field--row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.auth-field-row {
  display: flex;
  gap: 12px;
}
.auth-field-row .auth-field {
  flex: 1;
}
.field-input {
  width: 100%;
  padding: 10px 12px;
  font-size: 0.9rem;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--bg-app);
  color: var(--text-main);
  transition: border-color 0.15s;
  box-sizing: border-box;
}
/* Kompakte Variante für Felder IN einer Tabellenzelle (Inline-Edit). Bewusst
   ein Modifier mit EINER Klasse: ein Kontext-Selektor (`.x .field-input`)
   hätte (0,2,0) und würde das padding-right der Chevron-Regel oben mit-
   überschreiben — genau die Falle, die dort beschrieben ist. Die Mindestbreite
   kommt aus dem Kontext (`--field-input-inline-min` an der Tabelle), nicht aus
   einem eigenen Selektor. */
.field-input--inline {
  width: auto;
  min-width: var(--field-input-inline-min, 90px);
  padding: 4px 8px;
  font-size: 0.85rem;
}

/* ── Standard-Formular (.app-form) ────────────────────────────────────────── */
/* Neutrale, wiederverwendbare Form-Klasse (nicht auth-spezifisch). Trägt zwei
   Feld-Strukturen mit identischem Look (Block-Label oben, Feld darunter):
   - Builder (\html\input->label()): <label><span>Text</span><control class="field-input"></label>
   - Handgeschrieben: <div class="app-field"><label>Text</label><control class="field-input"></div> */
.app-form { display: flex; flex-direction: column; gap: 14px; }
.app-form > label { display: block; margin: 0; }
.app-form label > span,
.app-field > label {
  display: block;
  margin-bottom: 4px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-main);
}
.app-field-row { display: flex; flex-wrap: wrap; gap: 12px; }
.app-field-row .app-field { flex: 1; min-width: 0; }
/* Breiten-Modifier für gemischte Feldgrößen in einer Row (Layout in der Klasse,
   nicht inline). Gleiche Spezifität wie die .app-field-Basisregel, stehen danach
   → gewinnen. --2x = doppelt gewichtetes Hauptfeld, --md/sm/xs = feste Kurzfelder. */
.app-field-row .app-field--2x { flex: 2; }
.app-field-row .app-field--md { flex: 0 0 180px; }
.app-field-row .app-field--sm { flex: 0 0 120px; }
.app-field-row .app-field--xs { flex: 0 0 90px; }
/* Opt-in Stack-Utility: gleichmäßiger vertikaler Rhythmus zwischen direkten Kindern
   (z.B. Fieldset mit gestapelten Row/Checkbox/Notiz, wo .app-form-Gap nicht greift).
   Bewusst opt-in statt global auf fieldset, um fremde .app-form-Formulare nicht zu treffen. */
.app-stack > * + * { margin-top: 14px; }
/* Mobil: Felder deterministisch untereinander statt unkontrolliertem Flex-Schrumpf.
   flex-basis auf auto zurück, damit die festen --md/sm/xs-Breiten nicht zu Höhen werden. */
@media (max-width: 640px) {
  .app-field-row { flex-direction: column; }
  .app-field-row .app-field { flex: 1 1 auto; }
}
.auth-checkbox {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 0.90rem;
  color: var(--text-main);
}

/* ── Status-Banner (SSoT) ─────────────────────────────────────────────
   Eine Hinweisbox mit Schweregrad. Vorher stand dasselbe Rezept sechsmal
   parallel im Projekt (Login-CTAs, Broker-Notices, Depot-Fehlerbanner,
   CMS-Feedback, Scheduler-Banner) — mit auseinanderlaufendem Padding, teils
   hartkodierten Rahmenfarben ohne Dark-Mode und teils Textfarben, die den
   Kontrast verfehlten.

   Textfarbe ist bewusst --text-main und NICHT das Status-Token: bei der
   Error-Variante liegt Token-Text auf Token-Hintergrund im Light-Mode nur bei
   4,4:1 und verfehlt WCAG AA; die übrigen Varianten liegen knapp darüber.
   Einheitliche Textfarbe statt Grenzwerte pro Variante.

   Der Schweregrad muss dann über die FLÄCHE erkennbar sein: die Status-
   Hintergründe sind im Light-Mode nahezu weiss, ein 1px-Rahmen allein trägt das
   Signal nicht. Deshalb gehört der 4px-Balken zur Basis — `--flat` ist das
   bewusste Opt-out, nicht umgekehrt.

   Modifier: --info/--success/--warning/--error (Schweregrad; Default ist info,
   damit ein vergessener Modifier sichtbar wird statt unsichtbar), dazu
   optional --flat, --compact und --tight. */
.status-banner {
  margin-bottom: 16px;
  padding: 10px 16px;
  border: 1px solid var(--status-info-text);
  border-left-width: 4px;
  border-radius: 6px;
  background: var(--status-info-bg);
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text-main);
}
.status-banner--info    { background: var(--status-info-bg);    border-color: var(--status-info-text); }
.status-banner--success { background: var(--status-success-bg); border-color: var(--status-success-text); }
.status-banner--warning { background: var(--status-warning-bg); border-color: var(--status-warning-text); }
.status-banner--error   { background: var(--status-error-bg);   border-color: var(--status-error-text); }
/* Modifier stehen NACH der Basis und setzen border-color neu — border-left-width
   bleibt dabei erhalten, weil sie nur die Farbe anfassen. */
.status-banner--flat    { border-left-width: 1px; }
.status-banner--compact { padding: 8px 10px; font-size: 0.85rem; }
.status-banner--tight   { margin-bottom: 8px; }
/* Fließtext in der Box: neutralisiert die globale p-Regel (16px seitlich),
   sonst steht Text gegenüber Headline und Button eingerückt. */
.status-banner p {
  margin: 6px 0 0;
  padding: 0;
  font-size: inherit;
  color: inherit;
}

/* ── Reset-/Resend-CTA (Login) ────────────────────────────────────────
   Skelett kommt aus .status-banner; hier nur der abweichende obere Abstand.
   Padding und font-size bewusst NICHT überschrieben: die alten Werte wichen um
   4px bzw. 0,02rem ab (unsichtbar) und hätten .status-banner--compact auf
   diesen Boxen dauerhaft ausgehebelt. */
.auth-reset-cta,
.auth-resend-cta {
  margin: 12px 0 16px;
}
.auth-reset-cta .auth-reset-cta__btn {
  /* Vollbreiten-CTA: nach 3+ Fehlversuchen visuell prominent.
     Höhere Spezifität als .auth-btn { display: inline-flex } nötig,
     da .auth-btn später im File steht. */
  display: block;
  margin-top: 10px;
  width: 100%;
  text-align: center;
}

/* ── Resend-CTA bei unbestätigter E-Mail (Login) ───────────────────────
   Box-Regeln oben zusammen mit .auth-reset-cta; die p-Regel steht jetzt in
   .status-banner p. */
.auth-resend-cta__form {
  margin: 10px 0 0;
}
.auth-resend-cta .auth-resend-cta__btn {
  /* Vollbreiten-CTA analog Reset-CTA; höhere Spezifität schlägt
     .auth-btn { display: inline-flex } weiter unten im File. */
  display: block;
  width: 100%;
  text-align: center;
}

/* ── Passwort-Show/Hide-Toggle (auto-injected via code.js) ───────────── */
.auth-pw-wrapper {
  position: relative;
}
.auth-pw-wrapper .field-input {
  padding-right: 44px;
}
.auth-pw-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.auth-pw-toggle:hover {
  color: var(--text-main);
  background: var(--surface-container);
}
.auth-pw-toggle.is-shown {
  color: var(--btn-primary-bg);
}
.auth-pw-toggle:focus-visible {
  outline: 2px solid var(--btn-primary-bg);
  outline-offset: 1px;
}

/* ── Auth Buttons ──────────────────────────────────────────────────────────
   NUR für die Auth-Flows (Login/Register/Passwort/Magic-Link): der grosse
   Formular-Button (10/16px, weight 600) plus die OAuth-Varianten. Außerhalb dieser
   Masken gehört das reguläre .btn-System — .auth-btn war dort lange als generischer
   Admin-/Pagination-Button zweckentfremdet (fachfremd und optisch zu wuchtig).
   Bewusst KEINE Größen-/Farb-Modifier mehr (--sm/--small/--danger sind entfallen): die
   gab es nur, weil die Klasse als generischer Button zweckentfremdet war. Was hier bleibt,
   ist der Formular-Button selbst plus die OAuth-Varianten. */
.auth-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 16px;
  font-size: 0.9rem;
  font-weight: 600;
  border: 1px solid var(--btn-border);
  border-radius: 6px;
  background: var(--btn-bg);
  color: var(--btn-text);
  cursor: pointer;
  transition: all 0.15s;
  text-decoration: none;
}
.auth-btn:hover {
  border-color: var(--border-strong);
}
.auth-btn--primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-text);
  border-color: var(--btn-primary-bg);
}
.auth-btn--primary:hover {
  background: var(--btn-primary-hover);
}

/* ── OAuth Buttons ───────────────────────────────────────────────────────── */
.auth-btn--oauth {
  width: 100%;
  padding: 10px 16px;
  margin-top: 8px;
  background: #fff;
  color: #374151;
  border: 1px solid var(--border-color, #d1d5db);
  text-decoration: none;
  font-weight: 500;
}
.auth-btn--oauth:hover {
  background: #f9fafb;
  border-color: #9ca3af;
}
.auth-btn--google {
  border-left: 3px solid #4285f4;
}
.auth-btn--microsoft {
  border-left: 3px solid #00a4ef;
}
.auth-divider {
  display: flex;
  align-items: center;
  margin: 16px 0 8px;
  color: #9ca3af;
  font-size: 0.85rem;
}
.auth-divider::before, .auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-color, #e5e7eb);
}
.auth-divider span {
  padding: 0 12px;
}

/* ── OAuth Provider Profil ───────────────────────────────────────────────── */
.oauth-provider-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.oauth-provider-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border-color, #e5e7eb);
}
.oauth-provider-row:last-child {
  border-bottom: none;
}
.oauth-provider-label {
  font-weight: 600;
  min-width: 80px;
}
/* Provider-Farbbalken. Hing früher an .auth-btn--google/--microsoft — also an einer
   BUTTON-Klasse, obwohl das Ziel ein <span>-Label ist (Gruppierung nach Effekt statt nach
   Bedeutung). Eigene Marker-Klassen: der Balken gehört zum Label, nicht zum Button. */
.oauth-provider-label--google    { border-left: 3px solid #4285f4; padding-left: 6px; }
.oauth-provider-label--microsoft { border-left: 3px solid #00a4ef; padding-left: 6px; }

/* ── Auth Alerts ─────────────────────────────────────────────────────────── */
.auth-alert {
  padding: 12px 16px;
  border-radius: 6px;
  font-size: 0.9rem;
  margin-bottom: 12px;
}
.auth-alert ul {
  margin: 0;
  padding-left: 18px;
}
.auth-alert--error {
  background: #fef2f2;
  color: #991b1b;
  border: 1px solid #fecaca;
}
.auth-alert--success {
  background: #f0fdf4;
  color: #166534;
  border: 1px solid #bbf7d0;
}
.auth-alert--warning {
  background: #fffbeb;
  color: #92400e;
  border: 1px solid #fde68a;
}
/* Neutraler Hinweis (kein Fehler, keine Warnung) — zieht die Status-Tokens, damit
   der Dark-Mode ohne eigene [data-theme]-Regel mitkommt. Der Rahmen nimmt bewusst
   --status-info-border und NICHT die Textfarbe: sonst hätte die niedrigste
   Dringlichkeitsstufe den kräftigsten Rahmen der ganzen Gruppe. */
.auth-alert--info {
  background: var(--status-info-bg);
  color: var(--status-info-text);
  border: 1px solid var(--status-info-border);
}
[data-theme="dark"] .auth-alert--error {
  background: #2a1215;
  color: #fca5a5;
  border-color: #7f1d1d;
}
[data-theme="dark"] .auth-alert--success {
  background: #0f2417;
  color: #86efac;
  border-color: #14532d;
}
[data-theme="dark"] .auth-alert--warning {
  background: #2a210f;
  color: #fcd34d;
  border-color: #78350f;
}
/* --info braucht hier nichts: zieht die Status-Tokens (Zeile 14/34). */

/* ── Auth Badges ─────────────────────────────────────────────────────────── */
.auth-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: 10px;
  vertical-align: middle;
}
.auth-badge svg { width: 14px; height: 14px; }
.auth-badge--success {
  background: #dcfce7;
  color: #166534;
}
.auth-badge--warning {
  background: #fef9c3;
  color: #854d0e;
}
.auth-badge--danger {
  background: #fee2e2;
  color: #991b1b;
}
.auth-badge--info {
  background: #dbeafe;
  color: #1e40af;
}
/* Neutraler Zustand (inaktiv, widerrufen, unbekannter Slug). Fehlte bis
   27.07.2026, weshalb solche Faelle auf .badge--muted auswichen — eine Klasse,
   die es in keinem Stylesheet gibt und die nackten Text rendert. */
.auth-badge--neutral {
  background: #e5e7eb;
  color: #374151;
}
[data-theme="dark"] .auth-badge--success { background: #14532d; color: #86efac; }
[data-theme="dark"] .auth-badge--warning { background: #422006; color: #fde047; }
[data-theme="dark"] .auth-badge--danger  { background: #7f1d1d; color: #fca5a5; }
[data-theme="dark"] .auth-badge--info    { background: #1e3a5f; color: #93c5fd; }
[data-theme="dark"] .auth-badge--neutral { background: #374151; color: #d1d5db; }

/* ── Auth Footer / Links ─────────────────────────────────────────────────── */
.auth-footer {
  margin-top: 16px;
  text-align: center;
  font-size: 0.90rem;
  color: var(--text-muted);
}
.auth-link {
  color: var(--btn-primary-bg);
  text-decoration: none;
  font-weight: 500;
}
.auth-link:hover {
  text-decoration: underline;
}
.auth-privacy-notice {
  margin: 16px 0 0;
  padding: 8px 12px;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-muted);
  text-align: center;
  border-top: 1px solid var(--border-color);
}

/* Der Legacy-Alias .auth-table ist entfallen: er war laut eigenem Kommentar nur
   „data-table --sticky --hover" unter fachfremdem Namen (mit Auth hatte er nie etwas zu
   tun) und lieferte als vierte konkurrierende Zell-Padding-Regel uneinheitliche
   Zeilenhöhen. Alle ~45 Verwendungen tragen jetzt direkt das generische Tabellen-System
   (siehe „UNIFIED TABLE SYSTEM" weiter oben). */
.user-alert-detail td {
  padding: 4px 12px 12px;
  background: var(--bg-panel);
}
/* Eingebettete Detail-Tabelle: kompakter, und ihr Kopf darf NICHT sticky sein (er säße
   sonst in der aufgeklappten Zeile fest, statt mit ihr zu scrollen). */
.user-alert-detail .data-table {
  font-size: 0.8rem;
}
.user-alert-detail .data-table--sticky thead th {
  position: static;
}
.admin-filter-advanced {
  margin: 8px 0 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.admin-filter-advanced.hidden {
  display: none;
}

/* ── Profile Grid ────────────────────────────────────────────────────────── */
.profile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 24px;
  padding: 24px;
}
.profile-card {
  background: var(--bg-app);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 24px;
  display: flex;
  flex-direction: column;
}
.profile-card > form
, .profile-card .auth-form {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.profile-card > form > button:last-child
, .profile-card .auth-form > button:last-child {
  margin-top: auto;
}
.profile-card h3 {
  margin: 0 0 16px;
  color: var(--text-main);
}
.profile-card--wide {
  grid-column: 1 / -1;
}
/* Karte als Ganzes klickbar (Hub-/Einstiegs-Grids, z.B. marketdata\admin\MarketDataHub).
   Ersetzt die früheren Inline-Styles am <a>; der Hover hebt nur den Rahmen an, damit
   die Karte nicht wie ein Button wirkt.
   :hover/:visited MÜSSEN mitgenannt werden — a:hover/a:visited weiter oben sind
   (0,1,1) und schlagen ein einzelnes .profile-card--link (0,1,0); ohne sie faerbt
   nackter Text in der Karte nach dem ersten Klick violett. Gleiches Muster wie
   a.btn/a.btn:visited/a.btn:hover. */
.profile-card--link
, .profile-card--link:hover
, .profile-card--link:visited {
  text-decoration: none;
  color: inherit;
}
.profile-card--link {
  transition: border-color .15s ease;
}
/* Der Rahmenwechsel ist Zugabe, NICHT der Fokusring: den liefert die globale
   :focus-visible-Regel weiter unten. Hier niemals outline: none ergänzen. */
.profile-card--link:hover
, .profile-card--link:focus-visible {
  border-color: var(--link-color);
}
/* padding: 0 neutralisiert das globale p{padding:6px 16px} — sonst sitzt der Hinweis
   16px weiter rechts als das h3 der Karte. Gilt als letztes Kind der Karte. */
.profile-card__hint {
  margin: 0;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* ── Admin Container ─────────────────────────────────────────────────────── */
.admin-container {
  padding: 24px;
}
/* Padding-freie Variante für voll-tabellarische Berichte (Protokoll-Viewer u. a.) —
   das 24px-Innenpolster laesst breite Tabellen unschoen eingerueckt wirken. */
.admin-container--flush {
  padding: 0;
}
/* Standard-Klasse für Zeitpunkt-Spalten (Ziel-Breite 72px, Datum/Zeit stapeln am
   Leerzeichen). Projekt-Konvention: jede DateTime-Spalte bekommt sie, damit die
   Spalte überall schmal + konsistent bleibt. Hinweise zum Rollout:
     - Auf table-layout:auto ist width ein Hinweis; das nicht umbrechbare Datum
       ("2026-07-10") setzt die reale min-content-Breite (~85-96px inkl. Zell-Padding).
     - Gehoert DIREKT auf die Zelle; report-eigene, spezifischere Breiten-Overrides
       auf derselben Spalte gewinnen (bewusst niedrig-spezifisch gehalten).
     - In frozen Pivots (overflow:hidden + feste Zeilenhöhe) würde die 2. Zeile
       (Uhrzeit) abgeschnitten — dort NICHT verwenden. */
.col-dt {
  width: 72px;
  white-space: normal;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}
.admin-toolbar {
  margin-bottom: 16px;
}
.admin-search {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
/* Filterleisten laufen im Body, nicht in der .app-toolbar — die 26px-Kopplung
   aus `.app-toolbar .btn` greift hier also nicht, und ein 30px-Button neben
   einem 26px-Feld sitzt sichtbar schief. Spezifität (0,2,0) sticht auch
   .btn--sm/.btn--lg ab: eine Control-Höhe pro Leiste ist hier gewollt. */
.admin-search .btn {
  height: 26px;
  padding: 0 8px;
  font-size: 0.78rem;
}
@media (max-width: 768px) {
  /* Mit .toolbar-input (Mobile-Block oben) auf 32px mitwachsen — sonst steht ein
     26px-Button neben einem 32px-Feld und unterschreitet das Touch-Minimum. */
  .admin-search .btn {
    height: 32px;
  }
}
.admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 24px;
}
.admin-pagination {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  /* Ohne align-items streckt der Default `stretch` einen reinen Text-Span
     ("Seite 3 / 12") auf Button-Hoehe und klebt die Schrift oben an. */
  align-items: center;
  /* Am Boden des scrollenden .app-workspace andocken (nicht position:fixed — .app-workspace
     trägt contain:layout und wäre dafür der falsche Containing-Block, siehe app.confirm-
     Modal-Portal-Pattern in code.js. sticky bezieht sich stattdessen auf den nächsten
     scrollenden Ancestor, und das ist hier zufällig .app-workspace selbst — funktioniert
     ohne Portal-Trick). Erspart bei langen Tabellen (z.B. 50 Zeilen/Seite) das Scrollen bis
     ganz nach unten, nur um die Seiten-Buttons zu erreichen. */
  position: sticky;
  bottom: 0;
  background: var(--bg-panel);
  padding: 8px 0;
  border-top: 1px solid var(--border-color);
  z-index: 10;
}

/* ── Page-Loading Overlay & Spinner (layout-übergreifend) ──────── */
.page-loading-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  z-index: 10000;
}
.page-loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid var(--border-color);
  border-top-color: var(--btn-primary-bg);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
.btn-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid transparent;
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin .6s linear infinite;
  vertical-align: middle;
  margin-right: 6px;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Gast-Banner ────────────────────────────────────────────────────────── */
.guest-banner-container {
  position: relative;
}
.guest-banner-tab {
  display: flex;
  align-items: center;
  gap: 6px;
  position: relative;
  cursor: pointer;
  padding: 4px 14px;
  border-radius: 6px;
  border: none;
  background: var(--btn-primary-bg, #2563eb);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  overflow: hidden;
  transition: box-shadow 0.2s;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
@media (max-width: 768px) {
  .guest-banner-tab {
    height: 32px;
    padding: 0 12px;
  }
}
.guest-banner-tab:hover {
  box-shadow: 0 2px 8px rgba(37, 99, 235, 0.35);
}
.guest-banner-tab::after {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 60%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.35) 50%,
    transparent 100%
  );
  animation: shiny-sweep 3s ease-in-out infinite;
  pointer-events: none;
}
@keyframes shiny-sweep {
  0%   { left: -100%; }
  50%  { left: 150%; }
  100% { left: 150%; }
}
.guest-banner-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 240px;
  max-width: calc(100vw - 20px);
  background: var(--bg-panel, var(--bg-app));
  border: 1px solid var(--border-color);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
  z-index: 10000;
  padding: 12px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  box-sizing: border-box;
}
.guest-banner-dropdown.visible {
  display: block !important;
  opacity: 1;
  transform: translateY(0);
}
.guest-banner-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 10px;
  line-height: 1.4;
}
.guest-banner-actions {
  display: flex;
  gap: 8px;
}
.guest-banner-actions .btn {
  flex: 1;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-decoration: none;
  font-size: 13px;
  touch-action: manipulation;
}

/* ── Site-Toggle (Einstellungsseite) ────────────────────────────────────── */
.site-toggle {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  cursor: pointer;
}
.site-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
}
.site-toggle__slider {
  position: absolute;
  inset: 0;
  background: var(--border-color, #cbd5e1);
  border-radius: 22px;
  transition: background 0.2s;
}
.site-toggle__slider::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  left: 3px;
  bottom: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s;
}
.site-toggle input:checked + .site-toggle__slider {
  background: var(--btn-primary-bg, #2563eb);
}
.site-toggle input:checked + .site-toggle__slider::before {
  transform: translateX(18px);
}

/* ── Audit Details ───────────────────────────────────────────────────────── */
.audit-details {
  font-size: 0.75rem;
  max-width: 300px;
  max-height: 80px;
  overflow: auto;
  margin: 0;
  background: var(--bg-panel);
  padding: 4px 8px;
  border-radius: 4px;
  white-space: pre-wrap;
  word-break: break-all;
}

/* ── Landing Page Komponenten ──────────────────────────────────────────── */
.landing-hero {
  text-align: center;
  padding: 80px 24px 64px;
  max-width: 720px;
  margin: 0 auto;
}
.landing-hero__title {
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1.15;
  color: var(--text-main);
  margin: 0 0 20px;
  letter-spacing: -0.02em;
}
.landing-hero__subtitle {
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 0 0 32px;
}

.landing-features {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 24px 64px;
}
.landing-features__heading {
  text-align: center;
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 40px;
}
/* Steht zwischen Blocküberschrift und Kachelraster. Kein max-width: schmale
   Textspalten auf breitem Monitor sind hier unerwünscht. */
.landing-features__heading:has(+ .landing-features__intro) {
  margin-bottom: 16px;
}
.landing-features__intro {
  text-align: center;
  margin: 0 0 32px;
  padding: 0;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text-muted);
}
.landing-features__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}
/* Themenblöcke der Startseite: viele kurze Kacheln. auto-fill statt fester
   Spaltenzahl, weil das Raster hinter der 260px-Sidebar steht — eine
   Media-Query misst den Viewport und läge damit systematisch daneben.
   minmax mit fester Untergrenze verhindert zugleich den Überlauf: Grid-Items
   haben min-width:auto und können sonst nicht unter die Breite des längsten
   Wortes schrumpfen ("Marktmissbrauchsverordnung"), was .app-workspace mit
   overflow-x:hidden stumm abschneiden würde. */
.landing-features__grid--dense {
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}
.landing-features__grid--dense .landing-card {
  padding: 18px;
  /* Nicht --bg-app: das ist der Seitenhintergrund, im Dark-Theme stünden 49
     Karten sonst als flaue Wand ohne Trennung da. */
  background: var(--bg-panel);
}
/* Globales p{padding:6px 16px} neutralisieren — sonst sitzt der Text 34px vom
   Rand, der Titel aber bei 18px, und die nutzbare Textbreite schrumpft. */
.landing-card__desc {
  padding: 0;
}

.landing-card {
  border: 1px solid var(--border-color);
  border-radius: 10px;
  padding: 24px;
  background: var(--bg-app);
  transition: box-shadow 0.2s, transform 0.2s;
}
.landing-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.landing-card__icon {
  width: 48px;
  height: 48px;
  color: var(--btn-primary-bg);
  margin-bottom: 16px;
}
.landing-card__icon svg {
  width: 100%;
  height: 100%;
}
.landing-card__title {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-main);
  margin: 0 0 8px;
}
.landing-card__desc {
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0;
}

a.landing-card {
  text-decoration: none;
  color: inherit;
  display: block;
}
a.landing-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  cursor: pointer;
}

.landing-card__img-wrap {
  aspect-ratio: 16/9;
  overflow: hidden;
  border-radius: 6px;
  margin-bottom: 16px;
}
.landing-card__img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.landing-card__tagline {
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--text-main);
  margin: 0 0 8px;
  font-style: italic;
}

.landing-card__benefits {
  font-size: 0.88rem;
  color: var(--text-muted);
  padding-left: 1.2em;
  margin: 12px 0 0;
  line-height: 1.6;
}

.landing-cta {
  text-align: center;
  padding: 64px 24px;
  background: var(--bg-panel);
  border-top: 1px solid var(--border-color);
}
.landing-cta__title {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 12px;
}
.landing-cta__text {
  font-size: 1.05rem;
  color: var(--text-muted);
  margin: 0 0 28px;
}
.landing-cta__actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}
.landing-hero__actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

/* Conversion-Nutzenblock ("Mit kostenlosem Konto") — als abgesetztes Panel,
   nutzt sonst die landing-features-Basis (Grid/Heading/Cards). */
.landing-benefits {
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  padding: 40px 24px;
  margin: 8px auto 24px;
}

@media (max-width: 768px) {
  .landing-features__grid { grid-template-columns: 1fr; }
  .landing-hero__title { font-size: 1.8rem; }
  .landing-hero { padding: 48px 16px 40px; }
}

/* Belegleiste (Startseiten-Auftrag Aufgabe 8, marketdata\app\HomeStatsBar) — vier
   gecachte Kennzahlen + Frische-Hinweis, direkt unter dem Hero. */
.landing-stats {
  max-width: 900px;
  margin: 0 auto 32px;
  text-align: center;
}

.landing-stats__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.landing-stats__item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: 12px;
}

.landing-stats__value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-main);
}

.landing-stats__label {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.landing-stats__updated {
  margin-top: 12px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

@media (max-width: 768px) {
  .landing-stats__grid { grid-template-columns: repeat(2, 1fr); }
}

/* AGB-Seite: Guest-Layout Override – kein Zentrieren, normaler Scroll */
.app-shell--guest:has(.agb-wrapper) {
  justify-content: flex-start;
}
.app-workspace--guest:has(.agb-wrapper) {
  align-items: flex-start;
  justify-content: flex-start;
  overflow-y: auto;
}
.agb-wrapper {
  max-width: 900px;
  margin: 0 auto;
  padding: 24px;
  background: var(--bg-app);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}
.agb-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border-color);
}
.agb-logo-icon {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
}
.agb-logo-text {
  display: flex;
  flex-direction: column;
}
.agb-logo-name {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-main);
  letter-spacing: -0.02em;
}
.agb-logo-company {
  font-size: 0.8rem;
  color: var(--text-muted);
}
.agb-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
  border-bottom: 2px solid var(--border-color);
  padding-bottom: 0;
}
.agb-btn {
  padding: 8px 16px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--text-muted);
  transition: color 0.2s;
}
.agb-btn:hover {
  color: var(--text-main);
}
.agb-tabs {
  display: flex;
  gap: 4px;
}
.agb-tab {
  padding: 8px 20px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.95rem;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color 0.2s, border-color 0.2s;
}
.agb-tab:hover {
  color: var(--text-main);
}
.agb-tab--active {
  color: var(--text-main);
  border-bottom-color: var(--accent, #3b82f6);
  font-weight: 600;
}
.agb-content {
  font-size: 15px;
  line-height: 1.7;
  color: var(--text-main);
}
.agb-content h3 {
  font-size: 1.4em;
  margin: 0 0 16px;
}
.agb-content p {
  margin: 0 0 12px;
  font-size: 15px;
  padding: 0;
  color: var(--text-main);
}
.agb-content hr {
  border: none;
  border-top: 1px solid var(--border-color);
  margin: 24px 0;
}
.agb-content strong {
  color: var(--text-main);
}
.agb-content a {
  color: var(--accent, #3b82f6);
  text-decoration: underline;
}

/* AGB Druckansicht */
@media print {
  html, body {
    height: auto !important;
    width: auto !important;
    overflow: visible !important;
    font-size: 9pt !important;
    background: white !important;
    color: black !important;
  }
  body {
    display: block !important;
  }
  .app-shell,
  .app-shell--guest {
    display: block !important;
    height: auto !important;
    width: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
    background: white !important;
  }
  .app-workspace,
  .app-workspace--guest {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
    padding: 0 !important;
  }
  .app-header,
  .agb-toolbar,
  .kb-dialog-overlay,
  .cms-edit-bar-dock {
    display: none !important;
  }
  .agb-logo {
    border-bottom: 1px solid #ccc !important;
  }
  .agb-logo-name {
    color: black !important;
  }
  .agb-logo-company {
    color: #555 !important;
  }
  .agb-wrapper {
    max-width: none !important;
    width: auto !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    background: white !important;
  }
  .agb-content {
    font-size: 9pt !important;
    line-height: 1.5 !important;
    color: black !important;
  }
  .agb-content p {
    font-size: 9pt !important;
    padding: 0 !important;
    color: black !important;
  }
  .agb-content h3 {
    font-size: 11pt !important;
    color: black !important;
  }
  .agb-content strong {
    color: black !important;
  }
  .agb-content hr {
    border-top: 1px solid #ccc !important;
  }
  .agb-content a {
    color: black !important;
    text-decoration: none !important;
  }
  .agb-content a::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    color: #555;
  }
  .agb-content[style*="display:none"] {
    display: block !important;
    page-break-before: always;
  }
}

/* WATCHLIST COMPONENTS (.wl-* + .app-select): siehe app.css — dort konsolidiert,
   inkl. .wl-btn-active und .stock-search-*. Nur von Market-Reports genutzt (app.css-Kontext). */

/* ── Toast-Benachrichtigungen ─────────────────────────────────────── */
.app-toast {
  position: fixed;
  top: 24px;
  right: 24px;
  z-index: 10600; /* über DNS-Modalen (10001) + Command-Palette (10500), unter Confirm-Overlay (11000) */
  min-width: 320px;
  max-width: 440px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 20px;
  border-radius: 10px;
  font-size: 14px;
  line-height: 1.5;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.1);
  opacity: 0;
  transform: translateY(-12px) scale(0.96);
  transition: opacity .3s ease, transform .3s ease;
  pointer-events: auto;
  overflow: hidden;
}
.app-toast-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.app-toast-icon {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  margin-top: 1px;
}
.app-toast-icon svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
}
.app-toast-body {
  flex: 1;
  min-width: 0;
}
.app-toast-title {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 2px;
}
.app-toast-message {
  font-size: 13px;
  opacity: 0.9;
}
.app-toast-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 3px;
  background: rgba(255, 255, 255, 0.4);
  border-radius: 0 0 10px 10px;
  animation: toast-progress 4s linear forwards;
}
@keyframes toast-progress {
  from { width: 100%; }
  to   { width: 0%; }
}
.app-toast-error {
  background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
  color: #fff;
}
.app-toast-success {
  background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
  color: #fff;
}
.app-toast-info {
  background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
  color: #fff;
}
.app-toast-warning {
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
  color: #fff;
}

/* ── Confirm-Dialog (Ersatz für native confirm()) ──────────────── */
.app-confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 11000;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: app-confirm-fadein .15s ease;
}
.app-confirm-overlay.app-confirm--closing {
  opacity: 0;
  transition: opacity .15s ease;
}
.app-confirm-dialog {
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  padding: 20px 24px;
  min-width: 320px;
  max-width: 440px;
  animation: app-confirm-scalein .15s ease;
}
.app-confirm-body { margin-bottom: 20px; color: var(--text-main); line-height: 1.5; }
.app-confirm-body p { margin: 0 0 4px; }
.app-confirm-body p:last-child { margin-bottom: 0; }
.app-confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
.app-confirm-btn {
  padding: 7px 18px;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid var(--border-color);
  transition: background .12s, box-shadow .12s;
}
.app-confirm-cancel {
  background: var(--btn-bg);
  color: var(--btn-text);
}
.app-confirm-cancel:hover { background: var(--surface-container-low); }
.app-confirm-ok {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-text);
  border-color: var(--btn-primary-bg);
}
.app-confirm-ok:hover { background: var(--btn-primary-hover); }
.app-confirm-ok--danger {
  background: #dc2626;
  color: #fff;
  border-color: #dc2626;
}
.app-confirm-ok--danger:hover { background: #b91c1c; }
.app-confirm-input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  margin-bottom: 16px;
  border: 1px solid var(--border-color, #ccc);
  border-radius: 6px;
  font-size: .95rem;
  background: var(--surface-container, #fff);
  color: var(--text-main, #222);
}
.app-confirm-input:focus { outline: 2px solid var(--primary, #3b82f6); border-color: transparent; }
@keyframes app-confirm-fadein { from { opacity: 0 } to { opacity: 1 } }
@keyframes app-confirm-scalein { from { transform: scale(0.95); opacity: 0 } to { transform: scale(1); opacity: 1 } }

/* ── Schedule-Admin Edit-Form (im Standard-Modal .app-modal) ───────────────── */
.schedule-edit-form__row { margin-bottom: 12px; }
.schedule-edit-form__row--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.schedule-edit-field {
  display: block;
  margin-bottom: 12px;
}
.schedule-edit-form__row--split > .schedule-edit-field { margin-bottom: 0; }
.schedule-edit-field__label {
  display: block;
  font-weight: 500;
  margin-bottom: 4px;
  color: var(--text-main);
}
.schedule-edit-field__input {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  color: var(--text-main);
  font: inherit;
  transition: border-color .12s, box-shadow .12s;
}
[data-theme="dark"] .schedule-edit-field__input { background: var(--surface-container-high); }
.schedule-edit-field__input:hover { border-color: var(--border-strong, var(--border-color)); }
.schedule-edit-field__input:focus {
  outline: none;
  border-color: var(--btn-primary-bg);
  box-shadow: 0 0 0 3px rgba(var(--brand-tint), 0.15);
}
.schedule-edit-field__input--mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.schedule-edit-field__input--textarea { resize: vertical; font-size: 13px; }
.schedule-edit-field__hint {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-muted, #6b7280);
}
/* Bool-Param im Schedule-Edit: Checkbox VOR dem Label, Hint in eigener Zeile */
.schedule-edit-field--bool {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.schedule-edit-field--bool .schedule-edit-field__label { margin-bottom: 0; }
.schedule-edit-field--bool input[type="checkbox"] { cursor: pointer; }
.schedule-edit-field--bool .schedule-edit-field__hint {
  flex-basis: 100%;
  margin-top: 0;
}
.schedule-edit-form__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

[data-theme="dark"] .signal-preview {
  background: var(--bg-secondary, #1e293b);
}


/* ==========================================================================
   SITE HEADER (Top-Level Navigation)
   ========================================================================== */

.site-header {
    position: sticky; /* Stays sticky, more robust than fixed for this layout */
    top: 0;
    width: 100%;
    z-index: 1000;
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: var(--shadow-xs);
    border-bottom: 1px solid var(--border-color);
}

[data-theme="dark"] .site-header {
    background: rgba(18, 19, 24, 0.85); /* Matches old zone-nav dark */
    box-shadow: none;
}

.site-header-inner {
    max-width: 1280px; /* Corresponds to max-w-7xl */
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1.5rem; /* Mindestabstand Brand↔Nav↔CTA bei kurzem Label + space-between */
    padding: 0 1.5rem;
    height: 5rem; /* 80px */
}

.site-header-brand {
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--text-main);
    text-decoration: none;
    white-space: nowrap;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Inline-SVG-Wortmarke (cms.site.brand_html) statt Text-Brand; erbt currentColor → Light/Dark-adaptiv */
.brand-logo {
    height: 32px;
    width: auto;
    max-width: 100%; /* knapper Header: proportional skalieren statt clippen (Container hat overflow:hidden) */
    display: block;
}
@media (max-width: 768px) {
    .brand-logo { height: 26px; }
}

.site-header-nav {
    display: flex;
    align-items: center;
    gap: 2rem; /* space-x-8 */
}

.site-header-nav-item {
    display: inline-flex;
    align-items: center;
    padding-bottom: 0.25rem;
    font-size: 1rem;
    font-weight: 500;
    color: var(--text-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    transition: color 0.2s, border-color 0.2s;
}

.site-header-nav-item:hover {
    color: var(--text-main);
}

.site-header-nav-item.active {
    color: var(--btn-primary-bg);
    font-weight: 600;
    border-bottom-color: var(--btn-primary-bg);
}

.site-header-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

/* Ticker-/Firmen-Suche im Kopfbereich (Startseiten-Auftrag Aufgabe 8, siehe
   StandardLayout::renderHeaderStockSearch()). Die Trefferliste (.stock-search-
   results) wird per JS (market.js) befuellt und per display:block sichtbar
   gemacht/versteckt. position:relative traegt hier (statt als Inline-Style im
   PHP-Markup) den positionierten Vorfahren fuer das absolute Dropdown. */
.site-header-search {
    position: relative;
    min-width: 140px;
}

.stock-search-input {
    padding: 0.4rem 0.65rem;
    width: clamp(140px, 18vw, 220px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 0.25rem);
    background: var(--bg-app);
    color: var(--text-main);
    font-size: 0.9rem;
}

.stock-search-input:focus {
    outline: none;
    border-color: var(--btn-primary-bg, var(--primary));
}

.stock-search-results {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1000;
    min-width: 320px;
    max-height: 340px;
    overflow-y: auto;
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md, 0.5rem);
    box-shadow: var(--shadow-md, 0 4px 12px rgba(0, 0, 0, 0.15));
    padding: 0.25rem 0;
    margin-top: 0.25rem;
}

.stock-search-item {
    padding: 0.4rem 0.75rem;
    cursor: pointer;
}

.stock-search-item:hover,
.stock-search-item.is-selected {
    background: var(--surface-container-low, var(--bg-app));
}

.stock-search-name {
    font-weight: 600;
    font-size: 0.9rem;
}

.stock-search-meta-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.stock-search-meta {
    font-size: 0.78rem;
    color: var(--text-muted);
}

.stock-search-empty {
    padding: 0.5rem 0.75rem;
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* Kein display:none-Breakpoint mehr (Review-Fund): die Suche war die einzige
   Stelle mit Zugriff auf Ticker-/ISIN-/WKN-Suche, seit StockDetail::getToolbar()
   die alte Instanz verlor — ein harter Cutoff unter 1024px liesse die Funktion
   auf jedem Smartphone/Tablet ersatzlos verschwinden (BFSG/WCAG 2.1 AA
   4.1.2-relevant). clamp(140px, 18vw, 220px) auf .stock-search-input schrumpft
   stattdessen stetig; unter 768px verschwindet ohnehin .site-header-nav
   (Hamburger-Sidebar uebernimmt, siehe Media-Query weiter unten) und gibt den
   Platz wieder frei. Eigenes Icon-Trigger+Overlay-Pattern fuer sehr schmale
   Phones (<360px) ist ein offener Folge-Punkt, kein Ersatz fuer diesen Fix. */

/* Icon-Buttons der Zonenleiste (Theme, Anzeige-Modus) + Info-/Sprach-Menü-Summary
   teilen denselben dezenten Icon-Button-Look. Kein margin-left:auto — die
   Action-Gruppe ist via .site-header-inner (space-between) ohnehin rechts
   verankert; ein auto-Margin riss die Buttons sonst auseinander, sobald mehrere
   nebeneinander stehen. */
.site-header-actions #btn-theme-toggle,
.site-header-actions #btn-display-mode,
.site-header-actions .lang-menu-toggle,
.site-header-actions .info-menu-toggle {
    background: none;
    border: none;
    color: var(--text-main);
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    border-radius: var(--radius-sm, 4px);
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.875rem;
}

/* transform/box-shadow zurücknehmen: .btn:hover hebt den Button um 1px und legt
   einen Schatten darunter — sinnvoll für einen Button mit Rahmen und Fläche, hier
   aber wandert ein randloses Icon beim Hovern nach oben und bekommt den Schatten
   eines Körpers, den es nicht hat. Die Basisregel darüber nimmt beides weg
   (background: none, border: none), der Hover-Zustand hatte es zurückgeholt. */
.site-header-actions #btn-theme-toggle:hover,
.site-header-actions #btn-display-mode:hover,
.site-header-actions .lang-menu-toggle:hover,
.site-header-actions .info-menu-toggle:hover {
    background: var(--hover-bg, rgba(0,0,0,0.05));
    transform: none;
    box-shadow: none;
}

/* Touch-Target: .btn ist 30px, mobil unterschreitet das die 32px-Mindesthöhe, die
   base.css an den anderen Stellen selbst durchsetzt (.app-toolbar .btn und
   .toolbar-input weiter oben, .footer-links a weiter unten). Die Zonenleiste war
   die letzte Gruppe ohne — gilt für Theme-, Anzeige-, Info-, Sprach- und
   Share-Button gleichermaßen, deshalb an .btn im Container statt je Selektor.
   Spezifität (0,2,0) sticht die .btn-Basisklasse sauber aus. */
@media (max-width: 768px) {
  .site-header-actions .btn { height: 32px; }
}

/* Modus-Umschalter (Website / Cockpit) in der Top-Bar — Phase 3 Nav-Redesign */
.mode-switch {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    background: var(--surface-container-low);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    flex-shrink: 0;
}
.mode-switch-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.85rem;
    text-decoration: none;
    color: var(--text-muted);
    border-radius: calc(var(--radius-md) - 2px);
    transition: background 0.15s, color 0.15s;
}
.mode-switch-btn:hover {
    color: var(--text-main);
    background: var(--surface-container);
}
.mode-switch-btn--active,
.mode-switch-btn--active:hover {
    background: var(--bg-panel);
    color: var(--text-main);
    box-shadow: var(--shadow-xs);
}
.mode-switch-icon {
    font-size: 0.95rem;
    line-height: 1;
}
@media (max-width: 1024px) {
    .mode-switch-btn {
        padding: 0.375rem 0.5rem;
        font-size: 0.8rem;
    }
    .mode-switch-btn > span:not(.mode-switch-icon) {
        display: none;
    }
}

/* Adjust app-shell padding to account for fixed header height */
body:has(.site-header) .app-shell {
    height: calc(100vh - 5rem);
}

@media (max-width: 1024px) {
    .site-header-inner {
        height: 3.5rem;
        padding: 0 0.75rem;
        gap: 0.5rem;
    }

    /* Zone-Nav kompakt: kleinere Schrift, engerer Abstand */
    .site-header-nav {
        gap: 0.75rem;
    }
    .site-header-nav-item {
        font-size: 0.8rem;
        padding-bottom: 0;
        border-bottom: none;
    }

    .site-header-actions .btn--primary {
        display: none;
    }

    .site-header-brand {
        font-size: 0.95rem;
    }

    /* Header-Höhe anpassen */
    body:has(.site-header) .app-shell {
        height: calc(100vh - 3.5rem);
    }
}

/* Mobile: Horizontal-Nav durch Sidebar (Hamburger) ersetzen */
@media (max-width: 768px) {
    .site-header-nav {
        display: none;
    }

    /* Wortmarke lebt mobil in der Slide-in-Nav (.sidebar-logo), nicht doppelt im
       Header — Desktop ist umgekehrt (sidebar-logo aus, Header-Brand an, s.
       website.css). Nur scopen, wenn eine Sidebar existiert: Landing-Layout
       (ohne Sidebar) behält die Header-Wortmarke als einziges Logo. */
    body:has(.app-sidebar) .site-header-brand {
        display: none;
    }
}

/* Zwischenbereich 769-1024px: FAB-Hamburger ausblenden (Horizontal-Nav reicht) */
@media (min-width: 769px) and (max-width: 1024px) {
    body:has(.site-header) .sidebar-hamburger {
        display: none;
    }
}

/* ==========================================================================
   TEILEN-BUTTON (Social Sharing) — Launcher in site-header-actions + Modal.
   DSGVO/TTDSG-konform: reine Share-Links, kein Drittanbieter-Script.
   ========================================================================== */
/* Launcher: CI-getönter Icon-Button (Soft-Tint aus dem Primary-Token), damit er zum
   Corporate-Blau passt und nicht als dunkles, mageres Icon untergeht. Tint via color-mix
   gegen das Primary-Token → adaptiert automatisch an Dark-Mode (dort ist --btn-primary-bg hell). */
.site-header-actions .share-launch {
    background: color-mix(in srgb, var(--btn-primary-bg) 12%, transparent);
    border: none;
    color: var(--btn-primary-bg);
    cursor: pointer;
    padding: 7px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    transition: background 0.15s, color 0.15s;
}
.site-header-actions .share-launch:hover {
    background: color-mix(in srgb, var(--btn-primary-bg) 20%, transparent);
}
.site-header-actions .share-launch .icon-svg {
    width: 20px;
    height: 20px;
}

/* Modal: Ziele als 3-Spalten-Kachelraster (2 Spalten auf sehr schmal). */
.share-targets {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}
@media (max-width: 480px) {
    .share-targets {
        grid-template-columns: repeat(2, 1fr);
    }
}
.share-target {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-panel);
    color: var(--text-main);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.share-target:hover {
    border-color: var(--share-color, var(--btn-primary-bg));
    background: var(--bg-app);
}
.share-target:active {
    transform: translateY(1px);
}
.share-target svg {
    width: 28px;
    height: 28px;
    color: var(--share-color, var(--text-main));
}
/* Markenfarben (X nutzt --text-main → adaptiert an Dark-Mode). */
.share-target--whatsapp { --share-color: #25d366; }
.share-target--x        { --share-color: var(--text-main); }
.share-target--facebook { --share-color: #1877f2; }
.share-target--linkedin { --share-color: #0a66c2; }
.share-target--telegram { --share-color: #229ed9; }
.share-target--reddit   { --share-color: #ff4500; }
.share-target--email    { --share-color: var(--text-muted); }

/* Copy-Zeile: read-only URL + Kopieren-Button. */
.share-copy-row {
    display: flex;
    gap: 8px;
    margin-top: 16px;
}
.share-copy-url {
    flex: 1 1 auto;
    min-width: 0;
    height: 36px;
    padding: 0 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-app);
    color: var(--text-muted);
    font-size: 0.85rem;
}
.share-copy-btn {
    flex: 0 0 auto;
}
.share-copy-btn svg {
    width: 16px;
    height: 16px;
}
/* Fixes Dunkelgrün + weißer Text — theme-invariant lesbar (kein helles Dark-Mode-Grün). */
.share-copy-btn.is-copied {
    background: #15803d;
    border-color: transparent;
    color: #fff;
}
.share-modal-close svg {
    width: 18px;
    height: 18px;
}


/* ==========================================================================
   GLOBALE FEINSCHLIFFE (MD3 Redesign)
   ========================================================================== */

:focus-visible {
    outline: 2px solid var(--btn-primary-bg);
    outline-offset: 2px;
}

/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: var(--radius-full);
}
::-webkit-scrollbar-thumb:hover {
    background: var(--border-strong);
}

/* ==========================================================================
   NAV-DRAWER (Mobile Hamburger-Menü)
   ========================================================================== */
.nav-drawer {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 280px; max-width: 80vw;
    background: var(--bg-panel);
    border-right: 1px solid var(--border-strong);
    box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,0.15));
    transform: translateX(-100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 10000;
    display: flex; flex-direction: column;
    overflow-y: auto;
}
.nav-drawer.open { transform: translateX(0); }
.nav-drawer-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600; font-size: 0.95rem;
}
.nav-drawer-body { flex: 1; overflow-y: auto; padding: 8px 0; }
.nav-drawer-body a {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 16px;
    color: var(--text-main); text-decoration: none;
    font-size: 0.9rem;
    transition: background 0.15s;
}
.nav-drawer-body a:hover { background: var(--hover-bg, rgba(0,0,0,0.05)); }
.nav-drawer-body a:visited { color: var(--text-main); }
.nav-drawer-body a.active {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-color, #fff);
    font-weight: 600;
    border-radius: 4px;
    margin: 0 8px;
    padding: 10px 8px;
}
.nav-drawer-backdrop {
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 9999;
    opacity: 0; pointer-events: none;
    transition: opacity 0.25s ease;
}
.nav-drawer-backdrop.active { opacity: 1; pointer-events: auto; }

/* ── Global-Nav-Dropdown (Toolbar-Layout) + geteilte Nav-Icons ───────────────
   AppContext::getGlobalMenuHtml() rendert ein Dropdown in der Toolbar; die
   gleichen .app-nav-dropdown-item/.app-nav-icon-Elemente speist auch der mobile
   nav-drawer. Die Klassen waren nie gestylt (Pfad selten getriggert, da echte
   Seiten Sidebar/Website-Nav nutzen) — die rohen SvgIcon::resolve-SVGs liefen
   dadurch ohne Größenbegrenzung (riesige Symbole). Sichtbarkeit des Dropdowns
   steuert JS (toggleReportMenu → inline display), daher hier kein display. */
.app-nav-icon { display: inline-flex; align-items: center; flex-shrink: 0; }
.app-nav-icon svg { width: 18px; height: 18px; fill: currentColor; }
.app-nav-dropdown-container { position: relative; display: inline-flex; }
.app-nav-dropdown-trigger { display: inline-flex; align-items: center; gap: 6px; }
.app-nav-title { display: inline-flex; align-items: center; gap: 6px; }
.app-nav-dropdown-arrow { font-size: 0.6rem; opacity: 0.7; }
.app-nav-dropdown-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 220px;
    max-height: 70vh;
    overflow-y: auto;
    padding: 4px;
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md, 8px);
    box-shadow: var(--shadow-md, 0 6px 20px rgba(0, 0, 0, 0.15));
    z-index: 1000;
}
.app-nav-dropdown-menu .app-nav-dropdown-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: var(--radius-sm, 4px);
    color: var(--text-main);
    text-decoration: none;
    font-size: 0.9rem;
    white-space: nowrap;
}
.app-nav-dropdown-menu .app-nav-dropdown-item:hover { background: var(--hover-bg, rgba(0, 0, 0, 0.05)); }
.app-nav-dropdown-menu .app-nav-dropdown-item.active { background: var(--hover-bg, rgba(0, 0, 0, 0.05)); font-weight: 600; }

/* ── CMS Card Grid ──────────────────────────────────────── */
.cms-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }

/* Seitliche Kante der Kategorie-Auflistung als EINE Quelle.
   Kachel- und Listenansicht rücken unterschiedlich weit ein, und die Ansicht ist
   umschaltbar (app.toggleCategoryView, gemerkt in localStorage) — ein zweiter Ort
   mit denselben Zahlen liefe beim ersten Umschalten auseinander. Voreinstellung
   ist die LISTE (\cms\CategoryPage::defaultViewMode), also der schmalere Wert. */
.app-workspace { --cms-listing-gutter: 1.5rem; }
.app-workspace:has(> .cms-card-grid[data-view="list"]) { --cms-listing-gutter: 1rem; }

/* Liegt das Grid direkt im Workspace (z. B. Kategorie-Startseite ohne Artikel-Wrapper),
   fehlt das .cms-article-Padding — Karten kleben sonst am Viewport-Rand */
.app-workspace > .cms-card-grid { padding: 1.25rem var(--cms-listing-gutter); }

/* Sprach-Hinweis über einer Kategorie, hinter deren Kacheln noch nichts übersetzt
   ist (\cms\CategoryPage::translationNotice). Bewusst zurückhaltend: eine
   Auskunft, keine Warnung — die Seite funktioniert, sie ist nur noch nicht
   fertig. Nur `padding` und `font-size` sind nötig; margin, line-height und
   color trägt die `p`-Grundregel bereits. */
.app-workspace > .cms-lang-note {
  padding: 1.25rem var(--cms-listing-gutter) 0.5rem;
  font-size: 0.875rem;
}
.cms-card {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 14px; border: 1px solid var(--border-color); border-radius: 6px;
    text-decoration: none; color: var(--text-main); transition: all 0.15s ease-in-out;
}
.cms-card:hover {
    border-color: var(--border-strong); background: var(--bg-panel);
    transform: translateY(-2px); box-shadow: 0 2px 8px rgba(59,130,246,0.12);
}
.cms-card-icon { flex-shrink: 0; width: 36px; height: 36px; color: var(--text-muted); }
.cms-card-icon svg { width: 100%; height: 100%; }
.cms-card:hover .cms-card-icon { color: var(--text-main); }
.cms-card-text h3 { font-size: 1.05rem; margin: 0 0 4px 0; }
.cms-card-text p { font-size: 0.9rem; margin: 0; color: var(--text-muted); padding: 0; }
.cms-card--hidden { opacity: 0.5; }
.cms-card--hidden:hover { opacity: 0.75; }
.cms-card-meta { font-size: 0.825rem; color: var(--text-muted); margin: 0 0 4px 0; }
.cms-card-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.cms-card-badge {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 0.75rem; font-weight: 500; padding: 2px 7px;
    border-radius: 4px; background: var(--surface-container-high, #e2e8f0);
    color: var(--text-main, #334155); line-height: 1.3;
}
.cms-card-badge svg { width: 12px; height: 12px; }
.cms-card-badge--license {
    background: color-mix(in srgb, var(--accent, #3b82f6) 12%, transparent);
    color: var(--accent, #3b82f6); font-weight: 600;
}
.cms-card-badge--github {
    background: var(--surface-container-highest, #cbd5e1);
    color: var(--text-main, #0f172a);
}
[data-theme="dark"] .cms-card-badge {
    background: #1e293b; color: #cbd5e1;
}
[data-theme="dark"] .cms-card-badge--license {
    background: #1e3a5f; color: #93c5fd;
}
[data-theme="dark"] .cms-card-badge--github {
    background: #334155; color: #f1f5f9;
}

/* Card-Grid: Listenansicht */
.cms-card-grid[data-view="list"] {
    display: flex; flex-direction: column; gap: 0; padding: 0.5rem 1rem;
}
.cms-card-grid[data-view="list"] .cms-card {
    border: none; border-bottom: 1px solid var(--border-color);
    border-radius: 0; padding: 0.75rem 1rem;
}
.cms-card-grid[data-view="list"] .cms-card:last-child { border-bottom: none; }
.cms-card-grid[data-view="list"] .cms-card-icon { width: 24px; height: 24px; }
.cms-card-grid[data-view="list"] .cms-card-icon svg { width: 24px; height: 24px; }
.cms-card-grid[data-view="list"] .cms-card:hover {
    transform: none; box-shadow: none;
    background: var(--surface-container, #f0f4f8);
}

/* ── In-Article Grid & Callout-Boxen ────────────────────────── */
.cms-grid-2 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
    margin: 2rem 0;
}
.cms-grid-2 > .cms-card,
.cms-callout-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    padding: 1.5rem;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-panel);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
    transition: transform 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.cms-grid-2 > .cms-card:hover,
.cms-callout-card:hover {
    border-color: var(--border-strong);
    transform: translateY(-2px);
    box-shadow: 0 4px 14px rgba(59, 130, 246, 0.1);
}
.cms-grid-2 > .cms-card h3,
.cms-callout-card h3 {
    margin: 0 0 0.75rem 0;
    font-size: 1.2rem;
    font-weight: 700;
}
.cms-grid-2 > .cms-card p,
.cms-callout-card p {
    margin: 0 0 1rem 0;
    line-height: 1.6;
    color: var(--text-muted);
}
.cms-grid-2 > .cms-card p:last-child,
.cms-callout-card p:last-child {
    margin-bottom: 0;
    margin-top: auto;
    padding-top: 0.5rem;
}

/* ── Admonitions (> [!NOTE]/[!TIP]/[!IMPORTANT]/[!WARNING]/[!CAUTION]) ──────
   Erzeugt von \Markdown::toHtml() aus der GitHub-Stil-Blockquote-Syntax.
   Gleiche Architektur wie .status-banner (admin, base.css oben): der 4px-
   Rahmen trägt den Schweregrad über die FLÄCHE, nicht über Icon oder Text —
   ein 1px-Rahmen allein ist im Light-Mode auf nahezu weißem Grund kaum
   sichtbar. Textfarbe bewusst --text-main statt des Status-Tokens: bei der
   Error/Caution-Variante liegt Token-Text auf Token-Hintergrund im Light-Mode
   nur bei 4,4:1 und verfehlt WCAG AA knapp (identische Begründung wie bei
   .status-banner) — eine einheitliche Textfarbe umgeht jede Grenzwert-Prüfung
   pro Variante. */
.admonition {
    margin: 1.5rem 0;
    padding: 0.9rem 1.1rem;
    border: 1px solid var(--status-info-text);
    border-left-width: 4px;
    border-radius: 6px;
    background: var(--status-info-bg);
    color: var(--text-main);
}
.admonition--note      { background: var(--status-info-bg);      border-color: var(--status-info-text); }
.admonition--tip       { background: var(--status-success-bg);   border-color: var(--status-success-text); }
.admonition--important { background: var(--status-important-bg); border-color: var(--status-important-text); }
.admonition--warning   { background: var(--status-warning-bg);   border-color: var(--status-warning-text); }
.admonition--caution   { background: var(--status-error-bg);     border-color: var(--status-error-text); }
.admonition-title {
    margin: 0 0 0.35rem 0;
    padding: 0;
    font-weight: 700;
    color: var(--text-main);
}
.admonition p {
    margin: 0.4rem 0 0;
    padding: 0;
    color: inherit;
    line-height: 1.6;
}
.admonition > :first-child { margin-top: 0; }
.admonition > :last-child  { margin-bottom: 0; }

/* ── Blockquote-Default für Artikel-Content ─────────────────────────────
   Bis 22.09.2026 ungestylt (Browser-Default) — Artikel-Zitate/Tipps wie
   "> **Hinweis:** ..." liefen ohne jede Auszeichnung aus. Bewusst schlicht
   und deutlich von .admonition abgesetzt (kein Rahmen-Balken), damit ein
   Redakteur die beiden Bausteine visuell auseinanderhält: Zitat = neutral
   eingerückt, Admonition = farbig mit Schweregrad. */
.cms-content-block blockquote {
    margin: 1.5rem 0;
    padding: 0.6rem 1.1rem;
    border-left: 3px solid var(--border-color);
    color: var(--text-muted);
}
.cms-content-block blockquote p {
    margin: 0.3rem 0;
}
.cms-content-block blockquote > :first-child { margin-top: 0; }
.cms-content-block blockquote > :last-child  { margin-bottom: 0; }

/* ── PostgreSQL Configurator ───────────────────────────────── */
.pg-calc-wrapper {
    max-width: 1240px;
    margin: 0 auto;
    padding: 1.5rem 1rem;
}
.pg-calc-hero {
    text-align: center;
    margin-bottom: 2.5rem;
}
.pg-calc-hero-badge {
    display: inline-block;
    padding: 0.3rem 0.8rem;
    font-size: 0.85rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-radius: 999px;
    background: rgba(59, 130, 246, 0.12);
    color: var(--btn-primary-bg, #2563eb);
    margin-bottom: 0.75rem;
}
.pg-calc-hero-title {
    font-size: clamp(1.6rem, 3vw, 2.3rem);
    font-weight: 800;
    margin: 0 0 1rem 0;
    line-height: 1.25;
}
.pg-calc-hero-sub {
    max-width: 820px;
    margin: 0 auto;
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--text-muted);
}
.pg-calc-layout {
    display: grid;
    grid-template-columns: 460px 1fr;
    gap: 2rem;
    align-items: start;
}
@media (max-width: 1024px) {
    .pg-calc-layout {
        grid-template-columns: 1fr;
    }
}
.pg-calc-panel {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}
.pg-calc-panel-title {
    font-size: 1.15rem;
    font-weight: 700;
    margin: 0 0 1.25rem 0;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border-color);
}
.pg-calc-field {
    margin-bottom: 1.25rem;
}
.pg-calc-field:last-child {
    margin-bottom: 0;
}
.pg-calc-label {
    font-size: 0.9rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
    display: block;
}
.pg-calc-label-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}
.pg-calc-val-badge {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--btn-primary-bg, #2563eb);
    background: var(--surface-container, #f1f5f9);
    padding: 0.2rem 0.6rem;
    border-radius: 6px;
    border: 1px solid var(--border-color);
}
.pg-calc-select {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background: var(--surface-container);
    color: var(--text-main);
    font-size: 0.95rem;
    font-weight: 500;
}
.pg-calc-btn-group {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
}
.pg-calc-choice {
    display: flex;
    flex-direction: column;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background: var(--surface-container);
    color: var(--text-main);
    cursor: pointer;
    text-align: left;
    transition: all 0.15s ease-in-out;
}
.pg-calc-choice:hover {
    border-color: var(--border-strong);
    background: var(--surface-container-high);
}
.pg-calc-choice.is-active {
    border-color: var(--btn-primary-bg, #2563eb);
    background: var(--surface-container-high);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
}
.pg-calc-choice-icon {
    font-size: 1.25rem;
    margin-bottom: 0.25rem;
}
.pg-calc-choice-title {
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 0.2rem;
}
.pg-calc-choice-desc {
    font-size: 0.78rem;
    color: var(--text-muted);
    line-height: 1.35;
}
.pg-calc-grid-choices {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
}
@media (max-width: 480px) {
    .pg-calc-grid-choices,
    .pg-calc-btn-group {
        grid-template-columns: 1fr;
    }
}
.pg-calc-slider {
    width: 100%;
    accent-color: var(--btn-primary-bg, #2563eb);
    cursor: pointer;
    margin: 0.5rem 0;
}
.pg-calc-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.pg-calc-chip {
    font-size: 0.8rem;
    font-weight: 500;
    padding: 0.25rem 0.55rem;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--surface-container);
    color: var(--text-main);
    cursor: pointer;
    transition: all 0.15s ease-in-out;
}
.pg-calc-chip:hover {
    background: var(--surface-container-high);
}
.pg-calc-chip.is-active {
    background: var(--btn-primary-bg, #2563eb);
    color: var(--btn-primary-text, #fff);
    border-color: var(--btn-primary-bg, #2563eb);
}
.pg-calc-checkbox-label {
    display: flex;
    gap: 0.6rem;
    align-items: flex-start;
    cursor: pointer;
    font-size: 0.88rem;
    line-height: 1.45;
}
.pg-calc-checkbox {
    margin-top: 0.2rem;
    accent-color: var(--btn-primary-bg, #2563eb);
}
.pg-calc-alert {
    background: #fef3c7;
    border: 1px solid #f59e0b;
    color: #92400e;
    padding: 1rem 1.25rem;
    border-radius: 10px;
    margin-bottom: 1.5rem;
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    font-size: 0.92rem;
    line-height: 1.5;
}
.pg-calc-alert-icon {
    font-size: 1.3rem;
    line-height: 1;
}
.pg-calc-tabs-bar {
    display: flex;
    gap: 0.5rem;
    border-bottom: 2px solid var(--border-color);
    margin-bottom: 1.25rem;
}
.pg-calc-tab {
    padding: 0.75rem 1.25rem;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.95rem;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: all 0.15s ease-in-out;
}
.pg-calc-tab:hover {
    color: var(--text-main);
}
.pg-calc-tab.is-active {
    border-bottom-color: var(--btn-primary-bg, #2563eb);
    color: var(--btn-primary-bg, #2563eb);
}
.pg-calc-tab-content {
    display: none;
}
.pg-calc-tab-content.is-active {
    display: block;
}
.pg-calc-code-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.6rem;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.pg-calc-code-meta {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-muted);
}
.pg-calc-code {
    background: #0b1329;
    color: #e2e8f0;
    padding: 1.25rem;
    border-radius: 10px;
    overflow-x: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    font-size: 0.85rem;
    line-height: 1.55;
    border: 1px solid var(--border-color);
    max-height: 600px;
}
.pg-calc-expl-cards {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}
.pg-calc-expl-card {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 1.5rem;
}
.pg-calc-expl-card h3 {
    margin: 0 0 0.75rem 0;
    font-size: 1.1rem;
    font-weight: 700;
}
.pg-calc-expl-card p {
    margin: 0 0 0.75rem 0;
    line-height: 1.6;
    color: var(--text-muted);
}
.pg-calc-expl-card p:last-child {
    margin-bottom: 0;
}
.pg-calc-faq-section {
    margin-top: 4rem;
    padding-top: 2rem;
    border-top: 1px solid var(--border-color);
}
.pg-calc-faq-section h2 {
    font-size: 1.6rem;
    font-weight: 700;
    text-align: center;
    margin-bottom: 2rem;
}
.pg-calc-faq-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 1.5rem;
}
.pg-calc-faq-item {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 1.5rem;
}
.pg-calc-faq-item h3 {
    font-size: 1.05rem;
    font-weight: 700;
    margin: 0 0 0.75rem 0;
}
.pg-calc-faq-item p {
    margin: 0;
    line-height: 1.6;
    color: var(--text-muted);
    font-size: 0.92rem;
}

/* ==========================================================================
   TAB-NAVIGATION (CMS / Admin / Public TabbedPage shared)
   ========================================================================== */
/* In base.css statt app.css, weil WebsiteLayout (Public-Frontend mit
   TabbedPage) app.css nicht laedt — siehe StandardLayout::cssFiles(). */
.cms-tab-bar {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--border-color, #e2e8f0);
  margin-bottom: 1.5rem;
}
.cms-tab {
  padding: 0.625rem 1.25rem;
  border: none;
  background: none;
  color: var(--text-muted, #64748b);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color 0.15s, border-color 0.15s;
}
.cms-tab:hover {
  color: var(--text, #1e293b);
}
.cms-tab--active {
  color: var(--btn-primary-bg, #3b82f6);
  border-bottom-color: var(--btn-primary-bg, #3b82f6);
  font-weight: 600;
}
.cms-tab-panels {
  min-height: 200px;
}
.cms-tab-panel {
  animation: cmsTabFadeIn 0.2s ease;
}
@keyframes cmsTabFadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Render-Helper für Tabellen-Zellen mit Status-Hints — und genau in Tabellen
   greifen sie ohne den zweiten Block NICHT: `.data-table td` und
   `.detail-kv-table td` setzen color mit (0,1,1) und schlucken die Utilities
   (0,1,0), unabhängig von der Reihenfolge. Dieselbe Falle wie bei .dl-empty
   (siehe app.css, .data-table td.dl-empty). Gruppiert, weil identischer Grund:
   Zell-Grundfarbe gegen Status-Hint durchsetzen. */
.text-success { color: var(--status-success-text); }
.text-danger  { color: var(--status-error-text); }
.text-muted   { color: var(--text-muted); }
.text-small   { font-size: 0.85rem; }
.data-table td.text-success, .detail-kv-table td.text-success { color: var(--status-success-text); }
.data-table td.text-danger,  .detail-kv-table td.text-danger  { color: var(--status-error-text); }
.data-table td.text-muted,   .detail-kv-table td.text-muted   { color: var(--text-muted); }

/* ── Generisches Standard-Modal (alle Formular-/Detail-Dialoge) ───────────── */
/* <dialog>-feel mit Backdrop und zentriertem Dialog. Einfache Variante: Inhalt
   direkt im __dialog (padded, scrollt als Ganzes). Gegliederte Variante für
   lange Inhalte: __header + __body + __footer (fixe Kopf-/Fußzeile, scrollender
   Body) — greift automatisch, sobald ein __body vorhanden ist. Geöffnet/
   geschlossen über data-modal-open / data-modal-close bzw. app.openModal/
   app.closeModal (siehe js/code.js). */
.app-modal {
  position: fixed;
  inset: 0;
  z-index: 10001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.app-modal[hidden] { display: none; }
.app-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
}
.app-modal__dialog {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  width: 720px;
  max-width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  padding: 20px 24px;
}
.app-modal__dialog > h3 {
  margin: 0 0 8px;
}
.app-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
}

/* Gegliederte Variante (__header/__body/__footer): Dialog wird zur Flex-Spalte
   mit fixem Kopf/Fuß und scrollendem Body. Greift automatisch bei vorhandenem
   __body, daher kein Modifier am Markup nötig. */
.app-modal__dialog:has(.app-modal__body) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.app-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color);
}
.app-modal__title {
  margin: 0;
  font-size: 1.1rem;
}
.app-modal__title code {
  background: var(--bg-app);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.95rem;
}
.app-modal__body {
  padding: 16px 20px;
  overflow-y: auto;
}
.app-modal__body h4 {
  margin: 12px 0 6px;
  color: var(--text-main);
}
.app-modal__body h4:first-child {
  margin-top: 0;
}
.app-modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 20px;
  border-top: 1px solid var(--border-color);
}

/* ==========================================================================
   COMPARISON PAGE — Broker/Depot Vergleichsrechner (financeads)
   ========================================================================== */

.comparison-page {
  padding: var(--space-lg) var(--space-lg) var(--space-2xl);
  max-width: 1080px;
  /* Linksbuendig (nicht zentriert) — Abstand zur Sidebar via padding-left */
  margin-inline: 0;
  /* Lokales overflow: nur wenn überbreite Tabelle/Form über den Container
     überhaengt, scrollt diese Page intern — andere Pages bleiben unberuehrt.
     Nicht visuell als Box markiert (kein Border/Background). */
  overflow-x: auto;
}

/* Hero-Header ─────────────────────────────────────────────────────────────── */
.comparison-hero {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-lg);
  background: linear-gradient(140deg, var(--surface-container-low) 0%, var(--bg-panel) 100%);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-bottom: none;
}
.comparison-hero__svg {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  color: var(--btn-primary-bg);
}
.comparison-hero__title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.2rem;
}
.comparison-hero__subtitle {
  font-size: 0.84rem;
  color: var(--text-muted);
  margin: 0;
  line-height: 1.45;
}

/* Kostenrechner-Form ─────────────────────────────────────────────────────── */
.comparison-calculator {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  padding: var(--space-lg);
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-top: none;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  margin-bottom: var(--space-xl);
}
.comparison-calc__field {
  flex: 1;
  min-width: 140px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.comparison-calc__label {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.comparison-calc__input-wrap {
  display: flex;
  align-items: center;
  border: 1.5px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-app);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.comparison-calc__input-wrap:focus-within {
  border-color: var(--btn-primary-bg);
  box-shadow: var(--shadow-focus);
}
.comparison-calc__input-wrap input {
  flex: 1;
  border: none;
  background: transparent;
  padding: 0.5rem;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--text-main);
  min-width: 0;
  outline: none;
  font-family: inherit;
}
.comparison-calc__unit {
  padding: 0 0.6rem 0 0;
  font-size: 0.82rem;
  color: var(--text-muted);
  pointer-events: none;
  user-select: none;
}
.comparison-calc__hint {
  font-size: 0.72rem;
  color: var(--text-muted);
  line-height: 1.3;
}
.comparison-calc__action {
  flex-shrink: 0;
  align-self: flex-end;
}

/* Ergebnis-Tabelle ───────────────────────────────────────────────────────── */
.comparison-results { margin-top: var(--space-sm); }
.comparison-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
  table-layout: auto;
}
.comparison-table thead tr {
  background: var(--surface-container-low);
  border-bottom: 2px solid var(--border-color);
}
.comparison-table th {
  padding: 0.55rem 0.6rem;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  /* Header umbrechen lassen, damit Tabelle nicht über Container hinauswaechst */
  white-space: normal;
  line-height: 1.2;
  vertical-align: bottom;
  hyphens: auto;
}
/* Daten-Cells: Geldwerte bleiben nowrap; Header der gleichen Spalten dürfen umbrechen */
.comparison-table td:not(:first-child):not(:last-child) {
  white-space: nowrap;
}
.comparison-table th:not(:first-child):not(:last-child) {
  white-space: normal;
}
.comparison-table tbody tr { border-bottom: 1px solid var(--border-color); transition: background 0.1s; }
.comparison-table tbody tr:not(.comparison-detail-row):hover { background: var(--surface-container-low); }
.comparison-table td {
  padding: 0.8rem 0.9rem;
  vertical-align: middle;
  color: var(--text-main);
}
/* Anbieter-Spalte: nur so breit wie das Logo + ggf. Produkt-Subtitle */
.comparison-provider {
  width: 1%;
  min-width: 0;
  white-space: normal;
}
.comparison-provider-link {
  display: inline-flex;
  flex-direction: column;
  gap: 3px;
  text-decoration: none;
  color: inherit;
}
.comparison-logo {
  max-height: 28px;
  max-width: 96px;
  object-fit: contain;
  display: block;
}
.comparison-provider-name { font-weight: 600; font-size: 0.88rem; }
.comparison-provider-product { font-size: 0.75rem; color: var(--text-muted); }
.comparison-cta { text-align: right; white-space: nowrap; }

/* visually-hidden — sichtbar für Screenreader, unsichtbar visuell (BFSG/WCAG-Pattern).
   Global, seit es einen zweiten Konsumenten gibt: app.toast() hängt seine beiden
   ARIA-Live-Regionen damit aus dem Layout (code.js, _ensureToastLiveRegions).
   Bewusst KEIN display:none und kein visibility:hidden — beides nähme das Element
   auch aus dem Accessibility-Baum, die Ansage fiele also ersatzlos aus.
   Die .comparison-table-Variante darunter ist dadurch redundant, bleibt aber
   stehen: sie ist spezifischer und damit unschädlich. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  /* clip ist deprecated, bleibt als Rückfall für alte Engines; clip-path ist der
     aktuelle Weg und gewinnt, wo beides unterstützt wird. */
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.comparison-table .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Tabellen-Caption — Werbe-Kennzeichnung, semantisch zur Tabelle gehoerig.
   Ergaenzt nur den primaeren Affiliate-Disclaimer (\app\DisclaimerBlock::affiliate(),
   \financeads\reports\ComparisonPage::html()), der VOR der Tabelle steht und die
   UWG-§5a-Pflicht (Kennzeichnung vor Kenntnisnahme) traegt — deshalb darf diese
   Caption unten und leise sein (Betreiber-Entscheidung 16.08.2026), ohne die
   Kennzeichnung selbst zu schwaechen. */
.comparison-table__caption {
  caption-side: bottom;
  text-align: left;
  padding: 0.5rem 0.6rem 0.2rem;
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--text-muted);
  background: transparent;
}

/* Detail-Region tabindex="-1" Fokus-Sprung — kein sichtbarer Outline-Wechsel */
.comparison-detail:focus { outline: none; }
.comparison-detail:focus-visible {
  outline: 2px solid var(--btn-primary-bg);
  outline-offset: 2px;
}

/* Asset-Matrix + Min-Order ─────────────────────────────────────────────── */
/* :not-Selektoren matchen die Specifity der Default-text-align-Regel oben */
.comparison-table th.comparison-col-compact:not(:first-child):not(:last-child),
.comparison-table td.comparison-col-compact:not(:first-child):not(:last-child) {
  width: 1%;
  padding: 0.6rem 0.3rem;
  text-align: center;
  font-size: 0.78rem;
}
/* Compact-Header gekippt — Wortanfang unten, von unten nach oben lesbar */
.comparison-table th.comparison-col-compact:not(:first-child):not(:last-child) {
  height: 7rem;
  padding: 0.4rem 0 0.5rem;
  vertical-align: bottom;
  white-space: nowrap;
}
.comparison-col-compact__label {
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  line-height: 1;
}
.comparison-col-compact__label[title] {
  cursor: help;
}
.comparison-flag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
}
.comparison-flag--yes {
  color: var(--status-success-text);
  background: color-mix(in srgb, var(--status-success-text) 14%, transparent);
}
.comparison-flag--no {
  color: var(--text-muted);
  background: var(--surface-container-low);
}
.comparison-min-order--has {
  color: var(--status-error-text);
  font-weight: 600;
}
.comparison-min-order--none {
  color: var(--text-muted);
}

/* ── Footer (global) ──────────────────────────────────────
   renderFooter() steckt in StandardLayout und erscheint damit auf ALLEN
   Layouts (Toolbar/Market/Sidebar/Website). Die Styles müssen deshalb global
   in base.css liegen — vorher standen sie nur in website.css und der Footer
   war auf Market-/Toolbar-Seiten (z. B. StockDetail) unstyled. CI-Farben über
   die Theme-Variablen, kleine Schrift. */
.site-footer {
  flex-shrink: 0;
  padding: 1.25rem 2rem;
  border-top: 1px solid var(--border-color);
  background: var(--bg-panel);
}
/* Footer-Platzierung (Toolbar/Sidebar/Market): seit dem Anzeige-Modus-Umbau
   rendert der Footer als Geschwister NEBEN dem scrollbaren .app-workspace (nicht
   mehr darin), siehe ToolbarLayout/SidebarLayout::render(). .app-shell bzw.
   .app-main sind Flex-Spalten mit fixer Viewport-Höhe → der Footer (flex-shrink:0)
   sitzt damit immer am unteren Rand und ist garantiert sichtbar, auch wenn der
   Content (oder ein innerer Scroller wie .pivot-table-container) überläuft. Kein
   Sticky/z-index nötig: der Content scrollt im Workspace OBERHALB des Footers,
   nichts wird verdeckt. Landing-/Website-Layout hatten den Footer schon immer als
   Geschwister außerhalb des Workspace. */
.footer-inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: nowrap;
}
.footer-copy {
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  flex-shrink: 0;
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}
.footer-links a {
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  opacity: 0.8;
  transition: opacity 0.15s, color 0.15s;
}
.footer-links a:hover {
  opacity: 1;
  color: var(--text-main);
}
/* Mobil als EINE horizontal wischbare Zeile statt mehrzeilig umbrechend — spart
   maximal Bauhöhe. Copyright entfällt mobil (Platz), die Rechtslinks bleiben in
   der Zeile erwischbar; Scrollbar ausgeblendet, Wischen bleibt aktiv. */
@media (max-width: 768px) {
  .site-footer {
    padding: 0.5rem 0.75rem;
  }
  .footer-inner {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 1rem;
    overflow-x: auto;
    scrollbar-width: none; /* Firefox */
  }
  .footer-inner::-webkit-scrollbar { display: none; } /* WebKit */
  .footer-copy { display: none; }
  .footer-links {
    flex-wrap: nowrap;
    gap: 1rem;
  }
  .footer-links a {
    /* Touch-Target über min-height sichern (Pflichtlinks Impressum/Datenschutz);
       bleibt in der nowrap-Wischzeile, erfüllt aber die 32px-Mindesthöhe. */
    min-height: 32px;
    display: inline-flex;
    align-items: center;
    padding: 4px 0;
    font-size: 0.62rem;
  }
}

/* ── Anzeige-Modus „Kompakt" (data-display-mode="mini") ─────────────────────
   Blendet den Footer aus und verdichtet die Darstellung für mehr Daten pro
   Bildschirm. Die Pflichtlinks (Impressum/Datenschutz/Kontakt) bleiben über das
   Header-Info-Menü (.info-menu) erreichbar — DDG §5. Scope über das <html>-Attribut,
   Specificity schlägt die Basisregeln ohne Important-Deklaration.
   Trägt der Footer eine Werbezeile (MarketLayout::renderFooter() rendert sie
   VOR .footer-inner, innerhalb von .site-footer), bleibt nur diese sichtbar —
   nur .footer-inner (Copyright/Pflichtlinks) verschwindet. Sonst verschwände
   die Werbung beim Umschalten für JEDEN Betrachter, nicht nur für die per
   feature.ad_free werbefreien Kunden (financeads\AdVisibilityPolicy). */
[data-display-mode="mini"] .site-footer { display: none; }
[data-display-mode="mini"] .site-footer:has(.ad-footer-row) {
  display: block;
  padding-bottom: 0;
}
[data-display-mode="mini"] .site-footer:has(.ad-footer-row) .footer-inner { display: none; }
[data-display-mode="mini"] .header-branding { padding-top: 0; padding-bottom: 0; }
[data-display-mode="mini"] .header-branding h1 { font-size: 1.125rem; padding: 2px 0; }
[data-display-mode="mini"] .data-table th,
[data-display-mode="mini"] .data-table td { padding: 4px 8px; }
[data-display-mode="mini"] .detail-table thead th,
[data-display-mode="mini"] .detail-table tbody td,
[data-display-mode="mini"] .detail-kv-table th,
[data-display-mode="mini"] .detail-kv-table td { padding: 4px 10px; }
[data-display-mode="mini"] .dashboard-container { padding: clamp(6px, 1vw, 14px); }
[data-display-mode="mini"] .dashboard-section { margin-bottom: 16px; }

/* ── Header-Info-Menü (Pflicht-/Service-Links, mode-unabhängig sichtbar) und
   Sprachumschalter. Identisches Aufklapp-Muster, deshalb geteilte Selektoren
   statt zweier gepflegter Kopien — abweichend ist nur, was unten steht. ────── */
.info-menu,
.lang-menu { position: relative; }
.info-menu > summary,
.lang-menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.info-menu > summary::-webkit-details-marker,
.lang-menu > summary::-webkit-details-marker { display: none; }
.info-menu-panel,
.lang-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 180px;
  display: flex;
  flex-direction: column;
  padding: 6px;
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  box-shadow: var(--shadow-md);
  z-index: 20;
}
.info-menu-link,
.lang-menu-link {
  padding: 8px 12px;
  font-size: 0.875rem;
  color: var(--text-main);
  text-decoration: none;
  border-radius: var(--radius-xs, 3px);
  white-space: nowrap;
}
.info-menu-link:hover,
.lang-menu-link:hover { background: var(--hover-bg, rgba(0,0,0,0.05)); }
/* Aktive Sprache: der Umschalter listet auch die eigene Fassung (der Nutzer
   muss sehen, wo er steht). Farbe allein wäre zu wenig — WCAG 1.4.1 verlangt,
   dass die Information nicht nur über Farbe transportiert wird, daher zusätzlich
   die Schriftstärke. Die Auszeichnung für Screenreader liegt am aria-current.
   --link-color statt --accent: bei 14px/600 gilt die 4,5:1-Schwelle (WCAG 1.4.3,
   „large text" beginnt erst bei 18,66px bold), und --accent liegt im hellen
   Basis-Theme bei 3,68:1 auf --bg-panel — ausgerechnet der aktive Eintrag wäre
   damit der am schlechtesten lesbare der Liste. --link-color trägt in allen fünf
   Sites und beiden Modi (≥5,3:1). */
.lang-menu-link--active {
  font-weight: 600;
  color: var(--link-color);
}
.lang-menu-label { text-transform: uppercase; }
@media (max-width: 768px) {
  .info-menu-label { display: none; }
}
/* Das Sprach-Kürzel hält sich länger als das Info-Label — ein Globus ohne Kürzel
   sagt nicht, in welcher Sprache man ist. Unter 480px muss es trotzdem weichen:
   die Zonenleiste kann nicht umbrechen (.site-header-actions ist flex-shrink:0)
   und die Ticker-Suche hat eine Mindestbreite, die aus BFSG-Gründen bleibt — mit
   Kürzel überliefe die Leiste die Viewport-Breite und das Dokument scrollte
   horizontal. Die Sprache steht dann weiterhin im title/aria-label des Summary. */
@media (max-width: 480px) {
  .lang-menu-label { display: none; }
}

/* ── Anzeige-Modus-Toggle: nur das Icon; der Button-Sockel teilt sich die
   gemeinsame .site-header-actions-Regel mit #btn-theme-toggle (s.o.). ───────── */
#btn-display-mode .display-mode-icon {
  display: inline-flex;
  align-items: center;
  color: var(--text-main);
  transition: transform 0.2s;
}
#btn-display-mode:hover .display-mode-icon { transform: scale(1.12); }

/* Detail-Toggle ─────────────────────────────────────────────────────────── */
.comparison-toggle-cell { width: 1%; text-align: center; white-space: nowrap; }
.comparison-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0.3rem 0.6rem;
  font-size: 0.75rem;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.comparison-toggle:hover {
  background: var(--surface-container-low);
  color: var(--text-main);
  border-color: var(--text-muted);
}
.comparison-toggle__chevron {
  display: inline-block;
  transition: transform 0.15s ease;
  font-size: 0.7rem;
  line-height: 1;
}
.comparison-toggle[aria-expanded="true"] .comparison-toggle__chevron {
  transform: rotate(180deg);
}
.comparison-detail-row > td {
  /* Bewusst anderer Hintergrund als tr:hover (var(--surface-container-low)) —
     visuelle Trennung „aktive Hauptzeile" vs. „aufgeklappter Detailbereich". */
  background: var(--bg-app);
  padding: var(--space-md) var(--space-lg);
  border-bottom: 1px solid var(--border-color);
  border-top: 2px solid var(--border-color);
}
.comparison-detail__header {
  margin: 0 0 var(--space-md);
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--border-color);
}
.comparison-detail__advertiser {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
  line-height: 1.2;
}
.comparison-detail__product {
  margin-top: 0.15rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.comparison-detail__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-md);
}
.comparison-detail__section h4 {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.comparison-detail__section p,
.comparison-detail__section li {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-main);
  margin: 0 0 0.3rem;
}
.comparison-detail__section ul {
  margin: 0;
  padding-left: 1.1rem;
}
.comparison-detail__dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 0.75rem;
  margin: 0;
  font-size: 0.85rem;
}
.comparison-detail__dl dt {
  color: var(--text-muted);
  font-weight: 500;
}
.comparison-detail__dl dd {
  margin: 0;
  color: var(--text-main);
}
.comparison-detail__empty {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin: 0;
}
.comparison-detail__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
/* Info-Badge (kein Link) — Affiliate-Tracking-Loch vermieden:
   App-Store-Links würden ohne Adspace-ID weiterleiten = keine Provision. */
.comparison-detail__app-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.3rem 0.7rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-main);
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}
.comparison-detail__seals {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
}
.comparison-detail__seal {
  max-height: 60px;
  max-width: 80px;
  object-fit: contain;
}
.comparison-detail__ratings { margin: 0; padding-left: 1.1rem; }
.comparison-detail__rating-count { color: var(--text-muted); font-size: 0.78rem; }

/* Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .comparison-hero { flex-direction: column; align-items: flex-start; }
  .comparison-calculator { flex-direction: column; }
  .comparison-calc__field { min-width: 0; }
  .comparison-calc__action { align-self: stretch; }
  .comparison-calc__action .btn { width: 100%; justify-content: center; }
  /* Mobile: alle compact-Spalten ausblenden (Asset-Matrix + Plaetze).
     Modifier-basiert statt :nth-child — robust gegen Spalten-Reorder. */
  .comparison-table th.comparison-col-compact,
  .comparison-table td.comparison-col-compact { display: none; }
  .comparison-detail__grid { grid-template-columns: 1fr; }
}
@media (max-width: 1024px) {
  /* Tablet: Header-Höhe der gekippten Spalten reduzieren */
  .comparison-table th.comparison-col-compact:not(:first-child):not(:last-child) {
    height: 5rem;
  }
}

/* ── Tastenkombinationen-Dialog (F1) ─────────────────────────────────── */
.kb-dialog-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    /* über Nav-Drawer (10000) + Backdrop (9999), Niveau Command-Palette —
       bewusst ausgelöstes Top-Overlay, unter Confirm (11000) */
    z-index: 10500;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: kb-fade-in 0.15s ease;
}
@keyframes kb-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.kb-dialog {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    width: min(580px, 92vw);
    max-height: 80vh;
    overflow-y: auto;
    animation: kb-slide-in 0.15s ease;
}
@keyframes kb-slide-in {
    from { transform: translateY(-10px); opacity: 0; }
    to   { transform: translateY(0);     opacity: 1; }
}
.kb-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px 14px;
    border-bottom: 1px solid var(--border-color);
    position: sticky;
    top: 0;
    background: var(--bg-panel);
    z-index: 1;
}
.kb-dialog-title {
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--text-main);
}
.kb-dialog-close {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    font-size: 1.3rem;
    line-height: 1;
    padding: 2px 7px;
    border-radius: var(--radius-sm);
    transition: background 0.12s, color 0.12s;
}
.kb-dialog-close:hover {
    background: var(--surface-container);
    color: var(--text-main);
}
.kb-dialog-body {
    padding: 16px 20px 24px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}
.kb-group-label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    margin-bottom: 10px;
}
.kb-list {
    display: flex;
    flex-direction: column;
}
.kb-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 7px 0;
    border-bottom: 1px solid var(--surface-container-low);
}
.kb-row:last-child { border-bottom: none; }
.kb-label {
    font-size: 0.83rem;
    color: var(--text-main);
}
.kb-keys {
    display: flex;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
}
.kb-keys-sep {
    font-size: 0.68rem;
    color: var(--text-muted);
    padding: 0 1px;
}
kbd.kb-key {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 24px;
    padding: 0 7px;
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-main);
    background: var(--surface-container-low);
    border: 1px solid var(--border-color);
    border-bottom: 2px solid var(--border-strong);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

/* ── Disclaimer-Blöcke (BaFin-Compliance) ─────────────────────────────
   Render via \app\DisclaimerBlock::render($type). Variant-Klassen (je TYPE_*-Konstante,
   SSoT ist \app\DisclaimerBlock::ALL_TYPES):
   --performance / --backtest / --signal / --sim_trading / --broker / --compact /
   --affiliate / --derivative / --educational / --ai_research / --ai_reviewed /
   --perf_signal / --macro / --calendar / --holdings / --strategy / --fundamentals
   Eine eigene Akzentfarbe haben nur die unten gelisteten; der Rest erbt den neutralen
   border-left aus .disclaimer-block. Das ist Absicht, kein Rückstand — die Farbe markiert
   den Risiko-Ton (warn/info/premium), nicht jede Fachvariante.

   ⚠ KEIN Warn-Icon (Betreiber-Entscheidung 16.08.2026). Ein ⚠-Symbol ist echten
   Aufmerksamkeits-Fällen vorbehalten, die NICHT über diese Klasse laufen — dem
   🔒-Gate-Banner (\reports\TierGatedReportPivot::gateBanner(), „kein Abo") und der
   Coverage-Warnung bei zu wenigen 13F-Meldungen fürs laufende Quartal
   (.coverage-warning/.sig-conf-badge, z. B. \reports\ComboSignal). Ein Pflicht-
   Disclaimer ist demgegenüber Dauerzustand auf jeder Seite — ein Warndreieck dort
   nutzt sich beim Leser ab und verdeckt genau die zwei Fälle, in denen ein Icon
   wirklich etwas bedeuten soll. „Klar und erkennbar" (Art. 50 Abs. 5 KI-VO,
   § 5a Abs. 1 UWG) verlangt keine Ikonografie — Rand/Tint/Fußnotenlinie genügen.

   Zustands-Klassen (NICHT mit den Varianten verwechseln):
   --is-compact (gestuft kompakt ausgespielt) / --dismissible / --dismissed

   Variant-Akzentfarben sind als block-lokale Tokens definiert und unter
   [data-theme="dark"] leicht aufgehellt — so bleiben sie semantisch
   (warn/info/premium) und passen sich dem Theme an.

   Aus app.css hierher verschoben (14.08.2026, offene-punkte.md): app.css kommt erst über
   ToolbarLayout::cssFiles() herein, WebsiteLayout (extends StandardLayout) lädt es nicht —
   der Pflichtblock rendert dort sonst völlig ungestylt. base.css lädt jedes Layout.

   ⚠ 12,5px IST DIE GRENZE für den gesamten Block INKLUSIVE seiner Kompakt-/Dismissed-
   Zustände (Container, --compact/--is-compact, --dismissed waren vorher bei 12px/11px) —
   Art. 50 Abs. 5 KI-VO und § 5a Abs. 1 UWG verlangen „klar und erkennbar", das ist ein
   Rechtsbegriff, kein Designspielraum. Nach unten ist damit für JEDEN Zustand Schluss. */
.disclaimer-block {
  --disclaimer-accent-warn:    #f59e0b;
  --disclaimer-accent-info:    #3b82f6;
  --disclaimer-accent-premium: #a855f7;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 16px 0;
  padding: 12px 16px;
  border-left: 3px solid var(--border-strong);
  background: var(--surface-container-low);
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.5;
  border-radius: 0 4px 4px 0;
}
.disclaimer-block__body {
  flex: 1 1 auto;
  min-width: 0;
}
/* Im Report-Kopf ist der Disclaimer ein Flex-Kind von .desc-wrapper (gap:10px) —
   die zusätzliche margin:16px-Eigen-Marge stapelt sich darauf zu ~26px Leerraum
   zwischen Beschreibungstext und Hinweis. Den Flex-Gap die Trennung machen lassen. */
.desc-wrapper > .disclaimer-block { margin-block: 0; }
[data-theme="dark"] .disclaimer-block {
  --disclaimer-accent-warn:    #fbbf24;
  --disclaimer-accent-info:    #60a5fa;
  --disclaimer-accent-premium: #c084fc;
}
.disclaimer-block strong { color: var(--text-main); }
.disclaimer-block a      { color: var(--link-color); }
.disclaimer-block--backtest,
.disclaimer-block--sim_trading,
.disclaimer-block--educational { border-left-color: var(--disclaimer-accent-warn); }
.disclaimer-block--performance,
.disclaimer-block--signal      { border-left-color: var(--disclaimer-accent-info); }
.disclaimer-block--broker      { border-left-color: var(--disclaimer-accent-premium); }
/* ── KI-Hinweis unter den Wochenausgaben: Fußnote, keine Warnung ───────────
   Gilt für BEIDE Fassungen — ai_research (ungeprüft) und ai_reviewed (nach
   redaktioneller Durchsicht). ⚠ Ohne die zweite Klasse in jedem der beiden
   Selektoren bekäme ausgerechnet die DURCHGESEHENE Ausgabe den vollen Kasten,
   während die ungeprüfte die stille Fußnote behält. Die Optik drehte damit
   die Aussage um.
   Die anderen Varianten stehen MITTEN im Report und unterbrechen den Lesefluss
   absichtlich — Kasten, farbiger Rand, fetter Einstieg (kein Icon mehr, das
   ist seit 16.08.2026 plattformweit weg, s. Klassenkopf). Dieser hier steht
   ganz am Fuß eines fertig gelesenen Artikels; dieselbe Lautstärke wirkt dort
   wie eine Warnung vor dem eigenen Text.

   Leiser gemacht wird über FORM, nicht über Größe: Kasten und Randbalken weg,
   stattdessen eine Haarlinie wie bei einem Fußnotenstrich, gedämpfte Farbe,
   und der fette Einstieg auf normale Stärke.

   ⚠ 12,5px IST DIE GRENZE, und sie wird hier ausdrücklich gesetzt statt sich auf die
   Basisregel zu verlassen (die inzwischen selbst 12,5px trägt, aber Defense-in-Depth
   gegen künftige Änderungen). Art. 50 Abs. 5 KI-VO und § 5a Abs. 1 UWG verlangen
   „klar und erkennbar"; das ist ein Rechtsbegriff, kein Designspielraum.

   ⚠ NICHT auf 14px hochziehen. Die Vorbehalts-Fußnoten der Reports wurden am
   04.08.2026 von 12,5px auf 14px gesetzt; das ist eine ANDERE Fußnote an einer
   anderen Stelle. Diese hier soll klein bleiben (Vorgabe 04.08.2026).

   ⚠ Sollte `ai_research` je in \app\DisclaimerBlock::GESTUFTE_TYPES wandern:
   `--is-compact` und `--dismissed` tragen inzwischen ebenfalls 12,5px (vorher 11px,
   siehe Fix vom 14.08.2026) — die frühere Rückholungs-Sorge an dieser Stelle ist damit
   gegenstandslos. */
.disclaimer-block--ai_research,
.disclaimer-block--ai_reviewed {
  border-left: 0;
  border-top: 1px solid var(--border-color);
  background: transparent;
  padding: 10px 0 0;
  border-radius: 0;
  margin-top: 24px;
  color: var(--text-muted);
  font-size: 12.5px;
}
/* Kein Fettdruck. „Klar und erkennbar" im Sinne von Art. 50 Abs. 5 KI-VO ist
   der Block selbst — eigenes <aside role="note">, abgesetzt durch die Haarlinie
   und die gedämpfte Farbe, klar getrennt vom Artikeltext darüber. Die
   Auszeichnung INNERHALB der Fußnote trägt dazu nichts bei; sie macht die
   Fußnote nur wieder zur Warntafel. Das <strong> im Markup bleibt trotzdem
   stehen: es gliedert den Block für Vorleseprogramme, und dort ist es kein
   Lautstärkeregler. */
.disclaimer-block--ai_research strong,
.disclaimer-block--ai_reviewed strong {
  font-weight: 400;
}
/* Kompakte Darstellung. ZWEI Auslöser, bewusst getrennt benannt:
   --compact    = Variante TYPE_COMPACT (der generische Wortlaut)
   --is-compact = Zustand der gestuften Anzeige (beliebiger Typ, kompakt ausgespielt)
   Vorher trug beides denselben Namen; ein variant-spezifisches Styling für TYPE_COMPACT
   hätte damit ungewollt jede kompakte Fassung getroffen. */
.disclaimer-block--compact,
.disclaimer-block--is-compact  { font-size: 12.5px; padding: 6px 10px; }
/* Wegklickbare Disclaimer-Blase (gestufter Vollblock, noch nicht bestätigt): ×-Button oben
   rechts; nach dem Klick kollabiert der Block via JS (.--dismissed) auf den kompakten
   Pflicht-Einzeiler (.__compact-fallback). Reiner UI-State, der Kurzhinweis bleibt sichtbar. */
.disclaimer-block--dismissible { position: relative; padding-right: 40px; }
.disclaimer-block__close {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.disclaimer-block__close:hover { background: var(--surface-container-high); color: var(--text-main); }
.disclaimer-block__close:focus-visible { outline: 2px solid var(--link-color); outline-offset: 1px; }
.disclaimer-block__compact-fallback { flex: 1 1 auto; min-width: 0; }
/* Das <aside> nimmt nach dem Wegklicken programmatisch den Fokus (der ×-Button verschwindet).
   :not(:focus-visible) ist hier zwingend: löst der Nutzer den ×-Button per Enter/Leertaste
   aus, ist die Fokusverschiebung tastaturinduziert, der Browser matcht :focus-visible auch
   auf dem programmatisch fokussierten <aside> — ein blankes :focus{outline:none} nähme ihm
   den Indikator genau dort weg, wo der Fokus bewusst verschoben wurde (WCAG 2.4.7). */
.disclaimer-block--dismissible:focus:not(:focus-visible) { outline: none; }
/* Kollabierter Zustand = der kompakte Pflicht-Einzeiler. Bewusst NICHT mit .--compact gruppiert:
   diese Regel muss in der Quelle NACH .--dismissible stehen, damit ihr padding-Shorthand das
   padding-right:40px überschreibt (gleiche Spezifität → Source-Order entscheidet). */
.disclaimer-block--dismissed { font-size: 12.5px; padding: 6px 10px; }
.disclaimer-block--dismissed .disclaimer-block__close { display: none; }
/* Sanfter Hintergrund-Tint passend zur Variant — verstärkt die Auffälligkeit
   ohne mit dem normalen Content-Block zu konkurrieren. */
.disclaimer-block--backtest,
.disclaimer-block--sim_trading,
.disclaimer-block--educational {
  background: color-mix(in srgb, var(--disclaimer-accent-warn) 8%, var(--surface-container-low));
}
.disclaimer-block--performance,
.disclaimer-block--signal {
  background: color-mix(in srgb, var(--disclaimer-accent-info) 8%, var(--surface-container-low));
}
.disclaimer-block--broker {
  background: color-mix(in srgb, var(--disclaimer-accent-premium) 8%, var(--surface-container-low));
}

/* App-Tooltip — generischer schöner Hover-Tooltip via public/js/tooltip.js.
   Bewusst dunkles Schema in beiden Themes: im Light-Mode erscheint der Tooltip
   wie ein dunkler "Knopf" mit maximalem Kontrast zum Body; im Dark-Mode wird
   das Background eine Stufe heller (--app-tooltip-bg im [data-theme="dark"]-
   Block unten), damit der Tooltip sich vom Dark-Hintergrund optisch abhebt.
   Werte als Custom Properties auf der Klasse selbst — vermeidet Hardcodes
   ohne weiteres base.css-Token einführen zu müssen. Wichtig: alle Kinder
   bekommen explizit color: inherit, damit globale ul/li/p-Stile den
   Tooltip-Text nicht überlagern (Inheritance hat keine Specificity).
   z-index 10050 sitzt eine Stufe über signal-config-overlay (10000, app.css)
   — der Tooltip ist immer top-most, ohne die globale Layer-Skala mit INT_MAX
   zu sprengen.
   Steht bewusst in base.css statt app.css: tooltip.js lädt über
   StandardLayout::jsFiles() auf JEDEM Layout (auch WebsiteLayout, das kein
   app.css einbindet) — die CSS-Datei muss deshalb ebenso universell sein wie
   das Skript, sonst fällt .app-tooltip auf position:static zurück und
   landet im Dokumentfluss statt an der berechneten Viewport-Position
   (Fund 26.08.2026, dozent.net: Nav-Tooltip erschien unter dem Footer). */
.app-tooltip {
  --app-tooltip-bg: #0f172a;
  --app-tooltip-fg: #ffffff;
  --app-tooltip-border: rgba(255,255,255,0.08);
  --app-tooltip-strong: #7dd3fc;
  /* fixed statt absolute: tooltip.js rechnet die Position in reinen
     Viewport-Koordinaten (kein scrollY/scrollX) — Ziele können in fixed-
     positionierten Containern liegen (z. B. mobile .app-sidebar). */
  position: fixed;
  z-index: 10050;
  max-width: 320px;
  padding: 8px 12px;
  background: var(--app-tooltip-bg);
  color: var(--app-tooltip-fg);
  border: 1px solid var(--app-tooltip-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35), 0 2px 6px rgba(0,0,0,0.2);
  font-size: 0.78rem;
  line-height: 1.45;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  white-space: normal;
  word-wrap: break-word;
}
[data-theme="dark"] .app-tooltip {
  --app-tooltip-bg: #1f2937;
  --app-tooltip-border: rgba(255,255,255,0.12);
  --app-tooltip-strong: #93c5fd;
}
.app-tooltip.is-visible {
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0);
}
/* Titel = Linktext, fett/leicht größer, optische Trennlinie zur Beschreibung
   darunter — sonst liest sich der Linktext wie ein Satzanfang der Beschreibung
   statt wie eine Überschrift (Fund 26.08.2026). Titel-only (kein data-tooltip,
   nur abgeschnittenes Label als Fallback): kein Border, es folgt nichts. */
.app-tooltip-title {
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.3;
}
.app-tooltip-title:has(+ .app-tooltip-desc) {
  margin-bottom: 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--app-tooltip-border);
}
/* Beschreibung deutlich kleiner als der Titel und leicht gedämpft — setzt sich
   dadurch als sekundäre Information ab, auch ohne dass die Trennlinie allein
   die Hierarchie tragen muss. */
.app-tooltip-desc {
  font-size: 0.75rem;
  opacity: 0.85;
}
/* Globale `p, li`-Regel (font-size 0.9375rem + padding 16px) zurücksetzen,
   sonst werden Tooltip-Texte größer als der umliegende Tabellen-Text. */
.app-tooltip p,
.app-tooltip ul,
.app-tooltip li {
  color: inherit;
  font-size: inherit;
  line-height: inherit;
  padding: 0;
}
.app-tooltip p {
  margin: 0 0 6px 0;
}
.app-tooltip p:last-child {
  margin-bottom: 0;
}
.app-tooltip strong {
  color: var(--app-tooltip-strong);
  font-weight: 700;
}
.app-tooltip ul {
  margin: 4px 0 6px 0;
  padding-left: 18px;
  list-style: none;
}
.app-tooltip ul:last-child {
  margin-bottom: 0;
}
.app-tooltip li {
  margin: 2px 0;
  position: relative;
}
.app-tooltip li::before {
  content: '•';
  position: absolute;
  left: -12px;
  color: var(--app-tooltip-strong);
}
.app-tooltip::before {
  content: '';
  position: absolute;
  width: 0; height: 0;
  border: 6px solid transparent;
  left: 14px;
}
.app-tooltip.placement-bottom::before {
  top: -12px;
  border-bottom-color: #0f172a;
}
.app-tooltip.placement-top::before {
  bottom: -12px;
  border-top-color: #0f172a;
}
[data-theme="dark"] .app-tooltip.placement-bottom::before {
  border-bottom-color: #1f2937;
}
[data-theme="dark"] .app-tooltip.placement-top::before {
  border-top-color: #4b5563;
}
