/* ============================================================
   Bock Maschinenbau GmbH – Design Tokens (Single Source of Truth)
   ============================================================
   ARCHITEKTUR (in dieser Reihenfolge lesen):

     1. RAW CHANNELS   →  die EINZIGE Stelle, an der eine Farbe als
                          Zahl existiert. Format: "R G B" (Leerzeichen,
                          KEIN rgb()-Wrapper) — damit daraus per
                          rgb(var(--c-x) / <alpha>) jede Transparenz
                          abgeleitet werden kann.
     2. DERIVED TOKENS →  semantische Tokens (--color-*, --glow-*, …),
                          die NUR aus den Kanälen abgeleitet werden.
     3. THEME SWITCH   →  [data-theme="…"] überschreibt NUR die Kanäle.
                          Eine Zeile = die ganze Seite umgefärbt.

   REGEL: Niemals einen Hex-/rgb()-Zahlenwert ausserhalb von
   "RAW CHANNELS" schreiben. Brauchst du eine Farbe → leite sie aus
   einem Kanal ab. So bleibt das Styling skalierbar statt Chaos.
   ============================================================ */

:root {

  /* ════════════════════════════════════════════════════════
     1 · RAW CHANNELS  —  HIER und NUR HIER Farben definieren
     Werte als "R G B" (Space-Syntax). Ableitung via
     rgb(var(--c-name))  oder  rgb(var(--c-name) / 0.5)
     ════════════════════════════════════════════════════════ */

  /* ── Marke: Rot (Bock-Rot — DIE Markenfarbe) ──────────── */
  --c-red:          215 0 43;       /* #d7002b  Bock-Rot · role:brand */
  --c-red-light:    232 52 90;      /* #e8345a  helleres Rot/Mid · role:brand */
  --c-red-dark:     176 0 35;       /* #b00023  dunkleres Rot · role:brand */
  /* Marken-Rot als TEXT/Fokus auf DUNKEL: #d7002b erreicht dort nur 3.48:1 (AA=4.5);
     dieser Ton besteht AA auf allen Dunkel-Flächen (6.2/5.7/4.8:1) und bleibt in der
     Rot-Familie. Nur INK (--color-accent-text), nie Fläche. Guard: tests/styling/_contrast.py */
  --c-red-200:      255 90 114;     /* #ff5a72  helleres Marken-Rot (Text/Fokus, on-dark) · role:brand */

  /* ── Glow-Stützfarben — NEUTRALISIERT (kein Rosé/Pink mehr).
       Bleiben als Tokens bestehen, zeigen aber neutral/off-white. */
  --c-rose:         200 205 208;    /* neutral statt Rosé · role:decor */
  --c-blush:        225 228 230;    /* neutral statt Blush · role:decor */
  --c-blush-soft:   235 237 238;    /* neutral · role:decor */
  --c-wash:         245 244 241;    /* #f5f4f1  neutral Off-White · role:decor */

  /* ── Sekundär-Akzent „Ember" — auf Marken-Rot vereinheitlicht
       (keine zusätzliche Orange-Markenfarbe; bleibt ein roter Akzent). */
  --c-ember:        215 0 43;       /* = Bock-Rot · role:brand */
  --c-ember-dark:   176 0 35;       /* = Rot dunkel · role:brand */

  /* ── Graphit / Primary (dunkler Anker – Dark Sections, Nav, Headings)
       Champions-League-Industrie-Look: tiefes Graphit statt Blau/Navy.   */
  --c-navy:         25 27 29;       /* #191b1d  Graphit (Anker) · role:neutral-surface */
  --c-navy-light:   45 49 53;       /* #2d3135  Graphit hell · role:neutral-surface */
  --c-navy-dark:    17 19 21;       /* #111315  Graphit dunkel · role:neutral-surface */
  --c-ink:          35 38 42;       /* #23262a  technischer Text · role:neutral-text */

  /* ── Neutrale Schatten-Basis (Graphit, kein Blaustich) ── */
  --c-shadow:       25 27 29;       /* #191b1d  Graphit-Schatten · role:shadow */
  --c-shadow-deep:  10 11 12;       /* #0a0b0c  Tiefe (neutral) · role:shadow */
  --c-black:        0 0 0;          /* #000000 · role:scrim */
  --c-white:        255 255 255;    /* #ffffff · role:neutral-surface */
  --c-gray-50:      247 247 248;    /* #f7f7f8  (alpha-fähig) · role:neutral */
  --c-gray-100:     240 240 241;    /* #f0f0f1  (alpha-fähig) · role:neutral */
  /* Zinc-Neutralskala 200–900 (alpha-fähig; kanalisiert für Dark-Flip) */
  --c-gray-200:     228 228 231;    /* #e4e4e7 · role:neutral */
  --c-gray-300:     215 218 220;    /* #d7dadc · role:neutral */
  --c-gray-400:     161 161 170;    /* #a1a1aa · role:neutral */
  --c-gray-500:     113 113 122;    /* #71717a · role:neutral */
  --c-gray-600:     82 82 91;       /* #52525b · role:neutral */
  --c-gray-700:     63 63 70;       /* #3f3f46 · role:neutral */
  --c-gray-800:     39 39 42;       /* #27272a · role:neutral */
  --c-gray-900:     24 24 27;       /* #18181b · role:neutral */
  --c-personal:     165 180 252;    /* #a5b4fc  Deko (Personal-Badge) · role:decor */
  --c-personal-ink: 199 210 254;    /* #c7d2fe  Deko-Text · role:decor */

  /* ── Neutrale Flächen & Scrims (Graphit-Familie, Dark-Sections) ──
     Neutral-technisch, kein Blaustich. */
  --c-scrim:        20 22 24;       /* #141618  tiefer Graphit-Scrim · role:scrim */
  --c-scrim-soft:   38 42 46;       /* #262a2e  hellerer Scrim · role:scrim */
  --c-surface:      245 244 241;    /* #f5f4f1  neutral-warmes Off-White · role:neutral-surface */
  --c-slate-200:    223 225 226;    /* #dfe1e2  helle Neutral (Text) · role:neutral-text */
  /* = --color-text-muted. War #70777d → nur 4.13:1 auf Off-White-Alt #f5f4f1 (AA=4.5); jetzt 4.6:1. */
  --c-slate-400:    104 111 117;    /* #686f75  Steel (Sekundärinfo) · role:neutral-text */
  --c-slate-800:    25 27 29;       /* #191b1d  Graphit dunkel · role:neutral-surface */
  --c-line:         217 221 222;    /* #d9ddde  technische Trennlinie · role:neutral-border */
  --c-line-hover:   197 202 203;    /* #c5cacb  Karten-/Feld-Hover-Linie · role:neutral-border */
  /* Tertiärtext (de-emphasized). War #9aa0a4 = 2.65:1 auf Weiß (unter jeder Schwelle);
     jetzt ≥3:1 (AA_LARGE — für Hints/Divider/Captions, nicht Fließtext). */
  --c-text-light:   130 135 139;    /* #82878b  Tertiärtext · role:neutral-text */

  /* ── Status (semantisch — Erfolg/Warnung/Fehler/Info) ──── */
  --c-success:      16 185 129;     /* #10b981  Grün · role:status */
  --c-success-light:52 211 153;     /* #34d399  helleres Grün · role:status */
  --c-warning:      245 158 11;     /* #f59e0b  Amber · role:status */
  --c-error:        239 68 68;      /* #ef4444  Rot (Fehler) · role:status */
  --c-info:         59 130 246;     /* #3b82f6  Blau (Info/Fokus) · role:status */
  /* Status-Tints (Border/BG/Dark je Status) — Zahl lebt HIER, nicht im Derived-Layer */
  --c-success-border: 110 231 183;  /* #6ee7b7 · role:status */
  --c-success-bg:     209 250 229;  /* #d1fae5 · role:status */
  --c-success-dark:   6 95 70;      /* #065f46 · role:status */
  --c-warning-bg:     255 251 235;  /* #fffbeb · role:status */
  --c-warning-dark:   180 83 9;     /* #b45309 · role:status */
  --c-error-strong:   220 38 38;    /* #dc2626 · role:status */
  --c-error-light:    248 113 113;  /* #f87171  Fehler-TEXT auf Dunkel-Tint (#ef4444=4.28:1 → 5.8:1) · role:status */
  --c-error-border:   252 165 165;  /* #fca5a5 · role:status */
  --c-error-bg:       254 226 226;  /* #fee2e2 · role:status */
  --c-error-bg-soft:  254 242 242;  /* #fef2f2 · role:status */
  --c-error-dark:     153 27 27;    /* #991b1b · role:status */


  /* ════════════════════════════════════════════════════════
     2 · DERIVED TOKENS  —  alles unten leitet aus Kanälen ab.
     NIE hier Zahlen ändern, sondern oben den Kanal.
     ════════════════════════════════════════════════════════ */

  /* ── Brand Colors ─────────────────────────────────────── */
  --color-primary:        rgb(var(--c-navy));        /* Tiefes Navy – Nav / Dark Sections (FLÄCHE, flippt NICHT) */
  --color-primary-light:  rgb(var(--c-navy-light));
  --color-primary-dark:   rgb(var(--c-navy-dark));
  /* Überschrift/Label als TEXT (Headings, Keys, Outline-Button-Label). Hell = Primary-Navy
     (zero-visual), Dark = Weiß. --color-primary selbst ist eine FLÄCHE und flippt NICHT →
     als Text auf Dunkel unsichtbar; darum diese eigene, flippende Text-Rolle. */
  --color-heading:        var(--color-primary);
  --color-accent:         rgb(var(--c-red));         /* Bock-Rot – Akzent / CTAs (FLÄCHE: Button-BG, weiß darauf) */
  --color-accent-light:   rgb(var(--c-red-light));
  --color-accent-dark:    rgb(var(--c-red-dark));
  /* Marken-Rot als TEXT/Link (color:, fill:, text-decoration-color:). Hier = Brand-Rot
     (identisch zu --color-accent im Hellen → zero-visual). Auf dunklen Flächen (Dark-Mode
     + .dark-section) flippt es zu einem HELLEREN Rot, weil #d7002b als Text auf Dunkel nur
     3.48:1 erreicht (AA=4.5). Getrennt von der FLÄCHE, weil kein einziges Rot gleichzeitig
     als Text-auf-Dunkel UND als Button-Fläche-mit-weiß AA besteht. Guard: _contrast.py. */
  --color-accent-text:    var(--color-accent);
  --color-accent-bg:      rgb(var(--c-red) / 0.06);  /* Subtiler Rot-Ton */
  --color-accent-bg-hover:rgb(var(--c-red) / 0.10);
  --color-primary-bg:     rgb(var(--c-navy) / 0.05); /* Subtiler Graphit-Ton (parallel zu accent-bg) */

  /* ── Sekundär-Akzent (Ember) ──────────────────────────── */
  --color-ember:          rgb(var(--c-ember));
  --color-ember-dark:     rgb(var(--c-ember-dark));

  /* ── Grays (Zinc – neutral, kein Blaustich) ─────────── */
  --color-gray-50:   rgb(var(--c-gray-50));
  --color-gray-100:  rgb(var(--c-gray-100));
  --color-gray-200:  rgb(var(--c-gray-200));
  --color-gray-300:  rgb(var(--c-gray-300));
  --color-gray-400:  rgb(var(--c-gray-400));
  --color-gray-500:  rgb(var(--c-gray-500));
  --color-gray-600:  rgb(var(--c-gray-600));
  --color-gray-700:  rgb(var(--c-gray-700));
  --color-gray-800:  rgb(var(--c-gray-800));
  --color-gray-900:  rgb(var(--c-gray-900));

  /* ── Semantische Farben ───────────────────────────────── */
  --color-bg:           rgb(var(--c-white));      /* Weiß – primäre Fläche       */
  --color-bg-alt:       rgb(var(--c-surface));    /* #f5f4f1 – Off-White-Rhythmus */
  --color-bg-dark:      var(--color-primary);
  --color-text:         rgb(var(--c-ink));        /* technischer Graphit-Text    */
  --color-text-muted:   rgb(var(--c-slate-400));  /* Steel – Sekundärinfos (=#70777d) */
  --color-text-light:   rgb(var(--c-text-light));
  --color-text-inverse: rgb(var(--c-white));
  --color-border:       rgb(var(--c-line));       /* neutrale technische Linie   */
  --color-border-dark:  var(--color-gray-700);

  /* ── Status-Farben (semantisch — Toasts, Formulare, Hinweise) ──
     Status-Töne sind bewusst NICHT vom Brand-Theme abhängig (Grün bleibt
     Grün). Exakte Scale-Werte = single source; via Token referenzieren. */
  --color-success:        rgb(var(--c-success));    /* #10b981 */
  --color-success-light:  rgb(var(--c-success-light)); /* #34d399 */
  --color-success-border: rgb(var(--c-success-border));
  --color-success-bg:     rgb(var(--c-success-bg));
  --color-success-dark:   rgb(var(--c-success-dark));
  --color-warning:        rgb(var(--c-warning));    /* #f59e0b */
  --color-warning-bg:     rgb(var(--c-warning-bg));
  --color-warning-dark:   rgb(var(--c-warning-dark));
  --color-error:          rgb(var(--c-error));      /* #ef4444 */
  --color-error-strong:   rgb(var(--c-error-strong));
  --color-error-border:   rgb(var(--c-error-border));
  --color-error-bg:       rgb(var(--c-error-bg));
  --color-error-bg-soft:  rgb(var(--c-error-bg-soft));
  --color-error-dark:     rgb(var(--c-error-dark));
  --color-info:           rgb(var(--c-info));       /* #3b82f6 (ambient/Fokus) */

  /* ── Typografie ───────────────────────────────────────────────────────────
     SSOT der Schrift. Selbst gehostet (assets/css/fonts.css + assets/fonts/),
     null Fremd-Hosts (CSP/DSGVO-sauber). IBM Plex Sans = professionelle B2B-/
     Engineering-Familie, deckt Latin/Latin-ext/Kyrillisch/Griechisch ab (alle
     20 Sprachen). EINE Familie für Text UND Überschriften.
     TAUSCH = hier (--font-base) + assets/css/fonts.css + Preload in base.html.jinja. */
  --font-base:    'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  --font-display: var(--font-base);           /* eine Familie (früher Space Grotesk) */
  --font-mono:    'JetBrains Mono', 'Fira Code', ui-monospace, monospace;

  --text-xs:   0.75rem;   /* 12px */
  --text-sm:   0.875rem;  /* 14px */
  --text-base: 1rem;      /* 16px */
  --text-lg:   1.125rem;  /* 18px */
  --text-xl:   1.25rem;   /* 20px */
  --text-2xl:  1.5rem;    /* 24px */
  --text-3xl:  1.875rem;  /* 30px */
  --text-4xl:  2.25rem;   /* 36px */
  --text-5xl:  3rem;      /* 48px */
  --text-6xl:  3.75rem;   /* 60px */
  --text-7xl:  4.5rem;    /* 72px */

  --leading-tight:  1.25;
  --leading-snug:   1.375;
  --leading-normal: 1.5;
  --leading-relaxed:1.625;
  --leading-loose:  2;

  /* ── Letter-Spacing / Tracking ─────────────────────────── */
  --tracking-tighter: -0.08em;
  --tracking-tight:   -0.02em;
  --tracking-snug:     0.025em;
  --tracking-wide:     0.05em;
  --tracking-wider:    0.09em;
  --tracking-widest:   0.12em;

  /* Weights auf die 3 selbst gehosteten Schnitte (400/600/700) gemappt — IBM Plex
     Sans hat kein 800/900. Semantische Token-Namen bleiben stabil (kein Call-Site-
     Umbau); zum Font-Wechsel mit mehr Schnitten nur diese Werte + fonts.css ändern. */
  --font-weight-light:    400;   /* Plex Light nicht gehostet → Regular */
  --font-weight-normal:   400;
  --font-weight-medium:   600;   /* 500→600 (heavier, bewusst; wie Alt-Projekt) */
  --font-weight-semibold: 600;
  --font-weight-bold:     700;
  --font-weight-extrabold:700;   /* 800→700 (Plex-Maximum) */
  --font-weight-black:    700;   /* 900→700 (Plex-Maximum) */

  /* ── Spacing (8px Raster) ─────────────────────────────── */
  --space-1:  0.25rem;   /* 4px  */
  --space-2:  0.5rem;    /* 8px  */
  --space-3:  0.75rem;   /* 12px */
  --space-4:  1rem;      /* 16px */
  --space-5:  1.25rem;   /* 20px */
  --space-6:  1.5rem;    /* 24px */
  --space-7:  1.75rem;   /* 28px */
  --space-8:  2rem;      /* 32px */
  --space-10: 2.5rem;    /* 40px */
  --space-12: 3rem;      /* 48px */
  --space-14: 3.5rem;    /* 56px */
  --space-16: 4rem;      /* 64px */
  --space-20: 5rem;      /* 80px */
  --space-24: 6rem;      /* 96px */
  --space-32: 8rem;      /* 128px */

  /* ── Radien ───────────────────────────────────────────── */
  /* Präzise, technische Radien (keine Pillen, keine weichen Lifestyle-Karten). */
  --radius-sm:   5px;
  --radius-md:   7px;    /* Buttons / Felder – ingenieurhaft       */
  --radius-lg:   9px;    /* Karten – konstruktiv, ruhig            */
  --radius-xl:   8px;    /* ehem. Pill-Button → jetzt präzise      */
  --radius-2xl:  11px;
  --radius-full: 9999px; /* echte Kreise/Avatare – bleibt          */

  /* ── Blur (filter / backdrop-filter) ──────────────────── */
  --blur-xs: 2px;
  --blur-sm: 4px;
  --blur-md: 8px;
  --blur-lg: 12px;
  --blur-xl: 24px;

  /* ── Schatten (subtil & architektonisch – Graphit, kein Spektakel) ─
     DARK-FLIP: Farbe kommt ausschliesslich aus dem Kanal --c-shadow. Ein
     Dark-Theme setzt --c-shadow (→ tieferes Schwarz) und/oder redefiniert die
     5 --shadow-*-Token für höhere Alpha; auf dunklem Grund trägt aber primär
     die HELLERE Fläche (Elevation-via-Surface) die Tiefe, nicht der Schlag-
     schatten. Details: docs/styling/dark-mode-readiness.md. */
  --shadow-sm:  0 1px 2px rgb(var(--c-shadow) / 0.05), 0 1px 1px rgb(var(--c-shadow) / 0.04);
  --shadow-md:  0 4px 12px rgb(var(--c-shadow) / 0.07);
  --shadow-lg:  0 12px 28px rgb(var(--c-shadow) / 0.09);
  --shadow-xl:  0 20px 44px rgb(var(--c-shadow) / 0.11);
  --shadow-2xl: 0 24px 50px -14px rgb(var(--c-shadow) / 0.18);

  /* ── Interactive Glow System (Cards + Forms) ──────────── */
  --glow-speed: 220ms;
  --glow-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);   /* Material-Standard-Easing */

  /* Glow-System NEUTRALISIERT: keine dekorativen Rot/Rosé-Glows mehr.
     Hover-Tiefe = subtil-architektonisch (Graphit). Fokus bleibt klar rot. */
  --glow-red-core: rgb(var(--c-shadow) / 0.12);
  --glow-red-mid:  rgb(var(--c-shadow) / 0.10);
  --glow-rose:     rgb(var(--c-shadow) / 0.08);
  --glow-blush:    rgb(var(--c-shadow) / 0.06);
  --glow-wash:     rgb(var(--c-white) / 0);

  --glow-brand:      0 12px 28px -10px rgb(var(--c-shadow) / 0.16);
  --glow-brand-soft: 0 8px 20px -10px rgb(var(--c-shadow) / 0.12);
  --glow-layer-card: none;                 /* dekorative Farb-Ebene entfernt */
  --glow-layer-opacity: 0;
  --glow-focus-ring:        0 0 0 3px rgb(var(--c-red) / 0.30);  /* klarer roter Fokus */
  --glow-focus-ring-strong: 0 0 0 3px rgb(var(--c-red) / 0.45);

  /* ── DER zentrale Hover-Glow (SSOT) ───────────────────────────────────────
     EIN roter Halo für ALLES (Galerie-Kacheln, Leistungs-Cards, Job-Cards und
     künftige Stellen). Hier den Wert ändern → überall zieht es nach. Angewendet
     wird er performant: als opacity-animierte ::after-Ebene (GPU-composited, kein
     box-shadow-Repaint pro Frame) über die .u-glow-Utility bzw. – wo das Element
     overflow:hidden ist (Job-Cards) – als Element-box-shadow mit demselben Wert.
     Tempo/Easing kommen aus --glow-speed/--glow-ease. */
  --glow: 0 0 0 1px rgb(var(--c-red-light) / 0.50),
          0 6px 16px rgb(var(--c-black) / 0.20),
          0 16px 40px rgb(var(--c-red-light) / 0.38);

  --card-glow-shadow:      0 0 0 0 transparent;   /* keine farbigen Seiten-Glows */
  --card-glow-shadow-soft: 0 0 0 0 transparent;

  --card-surface: var(--color-bg);
  --card-border: var(--color-border);
  --card-border-hover: rgb(var(--c-line-hover)); /* klare Linie statt Glow */
  --card-shadow: var(--shadow-sm);
  --card-shadow-hover: 0 8px 22px rgb(var(--c-shadow) / 0.10);
  --card-shadow-hover-soft: 0 6px 16px rgb(var(--c-shadow) / 0.08);
  --card-shadow-hover-dark: 0 10px 26px rgb(var(--c-shadow) / 0.22);
  --card-border-hover-dark: rgb(var(--c-red) / 0.40);

  /* ── Interaktive Card (SSOT): Lift + Bild-Zoom ───────────────────────────────
     EINE Quelle für das einheitliche Hover-Verhalten JEDER verlinkten Card
     (Leistungs-/Job-/Maschinen-/Werte-/Branchen-Cards, Galerie, künftige via
     .u-card): anheben + Bild leicht heranzoomen. Der rote Halo kommt aus --glow
     (oben). Hier zentral ändern → überall. Glow + Lift + Zoom = das "smarte,
     abgerundete" Karten-Gefühl der ganzen Seite. */
  --card-lift:           translate3d(0, -4px, 0);   /* einheitliches Anheben      */
  --card-hover-transform: var(--card-lift);          /* Alias (bestehende Aufrufer)*/
  --card-img-zoom:       1.05;                        /* einheitlicher Bild-Zoom    */
  --card-img-zoom-speed: 450ms;                       /* Zoom-Dauer                 */
  --card-img-zoom-ease:  var(--glow-ease);            /* Zoom-Easing (= Glow-Ease)  */

  /* ── Icons (Komponente: components/icons.css) ──────────────────────────────
     Akzent-Modell lebt jetzt vollständig in icons.css: der Akzent-Layer folgt
     standardmäßig der Icon-Farbe (currentColor, an .bm-icon gesetzt) → nie
     unsichtbar. Bock-Rot als Akzent ist Opt-in via .bm-icon--spark (nur auf
     neutralem Grund). Kein globales --icon-accent-Token mehr nötig. */

  /* ── Buttons (Komponente: components/buttons.css) ──────────────────────────
     Kleiner Varianten-Satz: primary, secondary, ghost, outline + sm/lg. Layout
     und mobile Zentrierung werden dort zentral gesteuert; Werte bleiben hier. */
  --button-radius: var(--radius-md);
  --button-gap: var(--space-2);
  --button-group-gap: var(--space-4);
  --button-group-gap-compact: var(--space-3);
  --button-border-width: 2px;
  --button-min-height: 2.75rem;
  --button-min-height-sm: 2.25rem;
  --button-min-height-lg: 3.25rem;
  --button-padding-y: var(--space-3);
  --button-padding-x: var(--space-6);
  --button-padding-y-sm: var(--space-2);
  --button-padding-x-sm: var(--space-4);
  --button-padding-y-lg: var(--space-4);
  --button-padding-x-lg: var(--space-8);
  --button-mobile-max: 22rem;
  --button-primary-bg: rgb(var(--c-red));          /* FLACH, kein Verlauf */
  --button-shadow: 0 1px 2px rgb(var(--c-shadow) / 0.10);
  /* Hover-Glow: subtil & ROT (on-brand, kontrolliert) – Graphit-Lift + roter Halo.
     Kein Rosé/Pink-Feuerwerk; signalisiert klar „aktiv/klickbar". */
  --button-shadow-hover:      0 7px 18px rgb(var(--c-shadow) / 0.15), 0 7px 24px -5px rgb(var(--c-red) / 0.42);
  --button-shadow-hover-soft: 0 5px 14px rgb(var(--c-shadow) / 0.12), 0 5px 18px -5px rgb(var(--c-red) / 0.32);
  --button-shadow-dark-hover: 0 8px 20px rgb(var(--c-shadow) / 0.24), 0 7px 24px -5px rgb(var(--c-red) / 0.48);
  --button-focus-shadow: var(--glow-focus-ring-strong);
  --button-hover-transform: translate3d(0, -1px, 0);

  --field-bg: var(--color-bg);
  --field-border: var(--color-border);
  --field-radius: var(--radius-md);
  --field-shadow: 0 1px 2px rgb(var(--c-shadow) / 0.04);
  --field-hover-bg: rgb(var(--c-white));           /* clean, kein Rosé-Wash */
  --field-hover-border: rgb(var(--c-line-hover));
  --field-hover-shadow: 0 4px 12px rgb(var(--c-shadow) / 0.08);
  --field-error-shadow: 0 0 0 3px rgb(var(--c-error) / 0.14);
  --checkbox-hover-shadow: 0 4px 12px rgb(var(--c-shadow) / 0.08);
  --checkbox-control-hover-shadow:
    0 0 0 3px rgb(var(--c-red) / 0.14),
    0 4px 10px rgb(var(--c-shadow) / 0.08);
  --upload-hover-shadow: 0 4px 12px rgb(var(--c-shadow) / 0.08);
  --sticky-card-shadow: 0 10px 26px rgb(var(--c-shadow) / 0.16);
  --sticky-card-shadow-hover: var(--glow);   /* Hover = zentraler roter Glow (SSOT), Tiefe inklusive */

  /* ── Popover / Dropdown-Menü (dunkle Nav-Dropdowns – Sprachumschalter & Co.) ──
     SSOT für JEDES über der dunklen Nav schwebende Menü. Bewusst KANTIG-
     technisch statt weich/„KI": flachere Radien als Lifestyle-Cards (Panel 7px,
     Zeile 5px), architektonischer Graphit-Schatten statt schwarzem Spektakel,
     Hairline-Borders aus Weiß-Alpha (nicht Schwarz). Eine Stelle ändern → jedes
     Dropdown folgt. Pendant zu den card- und field-Token-Familien (DUNKLE Fläche). */
  --menu-surface:           rgb(var(--c-navy) / 0.98);
  --menu-radius:            var(--radius-md);       /* 7px – Panel: technisch, nicht weich */
  --menu-border:            rgb(var(--c-white) / 0.10);
  --menu-shadow:            0 16px 40px -14px rgb(var(--c-shadow-deep) / 0.60),
                            0 2px 8px rgb(var(--c-shadow-deep) / 0.40);
  --menu-item-radius:       var(--radius-sm);       /* 5px – kantige Zeile statt Pille */
  --menu-item-color:        rgb(var(--c-white) / 0.78);
  --menu-item-hover-bg:     rgb(var(--c-white) / 0.08);
  --menu-item-hover-color:  rgb(var(--c-white));
  --menu-item-active-bg:    rgb(var(--c-white) / 0.07);

  /* Trigger-Chip (aktuelle Sprache) – 7px Technik-Radius statt Pille */
  --menu-trigger-radius:        var(--radius-md);
  --menu-trigger-bg:            rgb(var(--c-white) / 0.05);
  --menu-trigger-border:        rgb(var(--c-white) / 0.12);
  --menu-trigger-hover-bg:      rgb(var(--c-white) / 0.10);
  --menu-trigger-hover-border:  rgb(var(--c-white) / 0.22);
  --menu-trigger-open-bg:       rgb(var(--c-white) / 0.12);
  --menu-trigger-open-border:   rgb(var(--c-white) / 0.26);

  /* Flaggen-Chip – crisp, minimal gerundet, dünner Trennring */
  --menu-flag-radius: 2px;
  --menu-flag-ring:   0 0 0 1px rgb(var(--c-black) / 0.20);

  /* ── Badges & Galerie-Filter (SSOT — Hero, Story, Galerie/Einblicke) ────────
     EIN zentraler Ort für die FORM aller kleinen Pill-Badges und der Galerie-
     Filter-Pills. --badge-radius gilt für JEDES Badge (Hero „Seit 1963", Story-
     Card-Badge, Galerie-Kategorie-Tag, „Ansehen"-Chip, Lightbox-Badge); die
     --gallery-filter-*-Tokens steuern die Einblicke-Filterleiste. Bewusst
     KANTIG/ingenieurhaft statt Pille – im Einklang mit dem Menü- und Card-System.
     Zum Ausprobieren einfach hier den Radius ändern → alle betroffenen Chips
     ziehen automatisch nach (für rund wieder var(--radius-full), scharf = 0). */
  --badge-radius:                var(--radius-sm);   /* ALLE Badges: Hero/Story/Kategorie/Ansehen/Lightbox */
  --gallery-filter-bar-radius:   var(--radius-lg);   /* Filter-Leiste (Container)               */
  --gallery-filter-btn-radius:   var(--radius-sm);   /* Filter-Buttons (vorher Pille → eckig)   */
  --gallery-filter-count-radius: var(--radius-sm);   /* Zähler-Chip im Filter-Button            */
  --gallery-filter-count-bg:     rgb(var(--c-black) / 0.10);
  /* dunkler statt weiß-transluzent: weiße Zahl auf weiß-über-Rot war nur 2.84:1;
     schwarz-transluzent über dem roten Aktiv-Button hält die weiße Zahl AA-lesbar. */
  --gallery-filter-count-active-bg: rgb(var(--c-black) / 0.28);
  --gallery-filter-count-active-color: var(--color-text-inverse);

  /* ── Google-Maps-Consent-Mock (DSGVO-Platzhalter vor der iframe-Einbettung) ──────────
     Bewusst im GOOGLE-Look (nicht Marken-Look), darum die Google-eigenen Hex — aber ab
     jetzt als THEME-AWARE Tokens an EINER Stelle (Dark-Override unten), statt hartkodiert
     im Consumer. War die zweite, nicht-SSOT-Map-Logik neben der themen-SSOT-Reichweiten-
     karte. Der Consumer (main.css) nutzt nur noch diese Tokens → Farb-Guard deckt ihn
     wieder ab (self-healing). Nur die Foreign-Brand-Rohwerte hier sind gehatcht. */
  /* ssot-ok:block-start — Google-Maps-Mock: Google-eigene Farbpalette (Foreign-Brand-Decor), theme-aware light/dark, Consumer bleibt guard-abgedeckt */
  --consent-chrome-bg:      #ffffff;   /* Suchleiste / Zoom / Karte-Fläche  */
  --consent-chrome-ink:     #3c4043;   /* Suchtext                          */
  --consent-chrome-icon:    #5f6368;   /* Icons / Beschreibung              */
  --consent-chrome-divider: #dadce0;   /* Zoom-Trennlinie                   */
  --consent-logo-bg:        #f1f3f4;   /* Logo-Kreis                        */
  --consent-link:           #1a73e8;   /* „Einstellungen"-Link (Google-Blau)*/
  --consent-link-hover:     #174ea6;
  --consent-shadow:         32 33 36;  /* Google-Schatten-Ton (als Kanal für rgb(... / a)) */
  --consent-preview-filter: none;      /* map-preview.svg im Hellen unverändert */
  /* ssot-ok:block-end — Google-Maps-Mock-Palette */

  /* ── Karten-Einbettung: Desktop-Höhe (SSOT) ─────────────────────────────────
     EIN Knopf für die vertikale Höhe der Google-Maps-Einbettung auf Desktop.
     Alle Vollkarten (Kontaktseite .contact-map-section + Home .contact-grid)
     ziehen aus diesem Token → hier einmal ändern = alle Karten ziehen mit.
     clamp(): Mobil-Boden bleibt niedrig (360px), Desktop wächst bis 840px
     (≈ +50 % ggü. der früheren 550/560px-Höhe). Die kompakten CTA-Band-
     Streifen skalieren proportional in ihren eigenen (schmaleren) Regeln. */
  --map-embed-h-desktop: clamp(360px, 50vw, 630px);

  /* Hochformat-Zuschnitt der festen Reichweitenkarte (Mobil-Variante: Region +
     Deutschland übereinander). Der Wert ist KEINE freie Design-Wahl — er spiegelt
     die Render-Geometrie des Generators (seo_engine/pdf/reach_map.py: _MOBILE_W
     × Panel-Crops ⇒ 636 × ~993). Ändert der Generator den Zuschnitt, MUSS dieser
     Token mitziehen; alle CSS-Nutzer (Mobil-Ansicht + schmale contact_cta-Spalte)
     ziehen aus diesem EINEN Knopf. */
  --reachmap-portrait-ratio: 636 / 993;

  /* ── Galerie: Kachel-Glow + Lightbox-Bühne (SSOT — /einblicke/) ──────────────
     EIN Ort für (a) den performanten Hover-Glow der Galerie-Kacheln und (b) die
     Lightbox-Bühne. Der Glow ist bewusst NUR eine opacity-animierte Pseudo-Ebene
     mit fertig gerendertem box-shadow → GPU-composited, KEIN box-shadow-Repaint
     pro Frame (das macht die Leistungs-Cards laggy). Die Lightbox-Höhe steuert,
     wie eng sich der Rahmen ans Bild schmiegt – Rahmen folgt der echten Bildhöhe,
     ragt also nicht mehr unten heraus. */
  --gallery-tile-radius:   14px;                     /* Kachel-Radius (auch Glow-Radius)        */
  /* Galerie-Kacheln nutzen den zentralen --glow (siehe Glow-System oben).        */

  /* ── Galerie: Hover-Bildunterschrift (SSOT — untere „Titel/Beschreibung"-Leiste)
     EIN Ort für die weiße, gut lesbare Caption-Leiste, die beim Hover (bzw. auf
     Touch dauerhaft) unten über der Kachel erscheint. Bewusst WEISS/heller Scrim
     statt dunkel: die Kurzbeschreibung muss überall lesbar sein, auch über hellen
     Bildpartien. Radius folgt der Kachel; Farben zentral hier ändern. */
  --gallery-label-bg:      rgb(var(--c-white) / 0.94); /* weißer, lesbarer Grund   */
  --gallery-label-text:    var(--color-text);          /* Graphit, hoher Kontrast  */
  --gallery-label-blur:    var(--blur-md);
  --gallery-label-shadow:  0 -6px 18px rgb(var(--c-black) / 0.14); /* Abhebung vom Bild */

  --lightbox-max-w:        1380px;                    /* Bühnen-/Panel-Breite                    */
  /* EINHEITLICHE Bühne: jedes Bild erscheint in EXAKT derselben 3:2-Box (= Format
     der Fotos → füllen randlos; andere Seitenverhältnisse werden sauber
     zentriert). Die Bühne ist so groß wie möglich, aber so begrenzt, dass Bühne +
     Bildunterschrift IMMER in 96vh passen und NICHTS unten herausragt. Die vier
     min()-Terme deckeln gegen: Maximalhöhe, Höhen-Budget (Platz für Caption),
     Viewport-Breite (3:2 bleibt sichtbar) und Maximalbreite.
     Das Seitenverhältnis steht als ZAHLENPAAR hier (EINE Quelle): daraus leiten
     sich sowohl die CSS-`aspect-ratio` als auch jede Breiten/Höhen-Umrechnung ab
     — sonst wandert „2 / 3" als stummes Literal durch die Komponente. */
  --lightbox-aspect-w:     3;                         /* Bühnen-Format: Breitenanteil            */
  --lightbox-aspect-h:     2;                         /* Bühnen-Format: Höhenanteil              */
  --lightbox-aspect:       var(--lightbox-aspect-w) / var(--lightbox-aspect-h);
  --lightbox-stage-h:      min(84vh,
                               calc(96vh - 12.5rem),
                               calc((97vw - 3rem) * var(--lightbox-aspect-h) / var(--lightbox-aspect-w)),
                               calc(var(--lightbox-max-w) * var(--lightbox-aspect-h) / var(--lightbox-aspect-w)));
  /* Rahmen-Chrome als Tokens, weil die Panel-BREITE daraus berechnet wird
     (Bühne + beide Polster) — Padding und Breite dürfen nicht auseinanderlaufen. */
  --lightbox-panel-pad:    clamp(0.75rem, 2vw, 1.15rem);   /* Panel → Rahmen           */
  --lightbox-frame-pad:    clamp(0.75rem, 1.5vw, 1rem);    /* Rahmen → Bühne           */
  --lightbox-frame-radius: 22px;                      /* Rahmen (Figure)                         */
  --lightbox-img-radius:   var(--gallery-tile-radius);/* Bild im Rahmen (= Kachel-Radius)        */
  --lightbox-frame-border: rgb(var(--c-white) / 0.18);
  --lightbox-frame-shadow: 0 40px 80px rgb(var(--c-black) / 0.55),
                           0 0 0 1px rgb(var(--c-white) / 0.08),
                           0 0 46px rgb(var(--c-red-light) / 0.16);   /* Tiefe + dezenter Rot-Halo */

  /* ── Video-Showcase (Skiper-Popover, SSOT) ───────────────────────────────
     EIN Ort für das klickbare Bewegtbild-Thumbnail (.bm-vshow) + den
     cineastischen Vollbild-Popover (.bm-vpop). Motiv-neutrale, wiederverwendbare
     Tokens — jedes künftige Showcase-Video (per video_showcase-Macro) zieht
     automatisch nach. Klick auf das Thumbnail zieht den Player per clip-path aus
     der Mitte auf (wie Skiper-UI Skiper67), Backdrop blurrt, native Controls. */
  --vshow-thumb-radius:    var(--radius-lg);            /* Thumbnail-Rahmen                    */
  --vshow-thumb-shadow:    var(--shadow-xl);            /* Ruhe-Schatten der Karte             */
  --vshow-thumb-shadow-hover: 0 26px 56px -18px rgb(var(--c-shadow) / 0.34),
                              0 0 40px -12px rgb(var(--c-red-light) / 0.30); /* Lift + Rot-Halo */
  --vshow-cursor-bg:       rgb(var(--c-white));         /* „Play"-Pill (mix-blend-exclusion)   */
  --vshow-cursor-text:     rgb(var(--c-white));         /* Text via exclusion → immer lesbar   */
  --vshow-cursor-radius:   var(--radius-full);
  --vshow-badge-bg:        rgb(var(--c-white) / 0.92);  /* Touch-Fallback: statisches Play-Badge */
  --vshow-badge-text:      var(--color-text);
  /* Popover: Bühne folgt dem ECHTEN Video-Seitenverhältnis (--vpop-aspect = w/h,
     per JS aus videos.yaml gesetzt) → EIN Baustein für Hoch- UND Querformat.
     So groß wie möglich, nie über 92vh/96vw hinaus. */
  --vpop-backdrop:         rgb(var(--c-scrim) / 0.86);
  --vpop-backdrop-blur:    var(--blur-lg);
  --vpop-stage-radius:     var(--radius-lg);
  --vpop-stage-shadow:     0 40px 90px rgb(var(--c-black) / 0.60),
                           0 0 0 1px rgb(var(--c-white) / 0.08);
  /* clip-path-Aufzieher = KRITISCH GEDÄMPFTER Feder-Nachbau (Skiper67: framer-
     spring stiffness 100 / damping 20 / mass 1 → ζ=1, ω=10 → weiche, lang
     ausklingende Verzögerung, ~0,9 s). linear() bildet die Feder-Kurve nach
     (Sample der Sprungantwort x(t)=1−(1+ωt)·e^−ωt); Fallback alter Engines: ease. */
  --vpop-open-duration:    0.9s;
  --vpop-open-ease:        linear(
                             0, 0.228 10%, 0.537 20%, 0.751 30%, 0.874 40%,
                             0.939 50%, 0.971 60%, 0.987 70%, 0.994 80%, 0.997 90%, 1
                           );

  /* Kontakt-Pills (Telefon-/E-Mail-Badges auf den Ansprechpartner-Karten).
     Teilen die zentrale Badge-FORM (--badge-radius → kantig, ingenieurhaft) und
     bündeln ihre kompakten Maße HIER. Radius zentral über --badge-radius ändern
     → Hero/Story/Kontakt-Pills ziehen gemeinsam nach; Größe nur für die Pills
     über die folgenden Tokens. */
  --badge-pill-radius:    var(--badge-radius);       /* Form folgt dem zentralen Badge-Radius   */
  --badge-pill-padding-y: 0.4rem;                    /* vertikaler Innenabstand                 */
  --badge-pill-padding-x: 0.85rem;                   /* horizontaler Innenabstand               */
  --badge-pill-gap:       0.4rem;                    /* Icon ↔ Text                             */
  --badge-pill-font-size: var(--text-sm);            /* Beschriftungsgröße                      */

  /* ── On-Dark / Glass / Scrim (SSOT — dunkle Panels, Media, Carousel) ───────
     Ein gemeinsamer Satz für Text, Hairlines, leichte Glasflächen und dunkle
     Scrims auf Bild-/Dark-UI. Das ersetzt verstreute rgba(255,255,255,...) und
     rgba(0,0,0,...) Werte in Consumer-CSS. Carousel nutzt darauf aufbauend seine
     spezifischen Card-/Control-Tokens. */
  --on-dark-text:          rgb(var(--c-white));
  --on-dark-text-high:     rgb(var(--c-white) / 0.92);
  --on-dark-text-soft:     rgb(var(--c-white) / 0.82);
  --on-dark-text-muted:    rgb(var(--c-white) / 0.72);
  --on-dark-text-subtle:   rgb(var(--c-white) / 0.62);
  --on-dark-text-faint:    rgb(var(--c-white) / 0.45);
  --on-dark-text-quiet:    rgb(var(--c-white) / 0.25);

  --on-dark-surface-faint:  rgb(var(--c-white) / 0.04);
  --on-dark-surface-soft:   rgb(var(--c-white) / 0.06);
  --on-dark-surface:        rgb(var(--c-white) / 0.08);
  --on-dark-surface-strong: rgb(var(--c-white) / 0.10);
  --on-dark-surface-glass:  rgb(var(--c-white) / 0.12);
  --on-dark-surface-solid:  rgb(var(--c-white) / 0.20);

  --on-dark-border-faint:   rgb(var(--c-white) / 0.08);
  --on-dark-border-soft:    rgb(var(--c-white) / 0.10);
  --on-dark-border:         rgb(var(--c-white) / 0.12);
  --on-dark-border-strong:  rgb(var(--c-white) / 0.20);
  --on-dark-border-glass:   rgb(var(--c-white) / 0.36);
  --on-dark-border-heavy:   rgb(var(--c-white) / 0.45);
  --on-dark-border-bright:  rgb(var(--c-white) / 0.60);

  --scrim-overlay-soft:    rgb(var(--c-black) / 0.28);
  --scrim-overlay:         rgb(var(--c-black) / 0.45);
  --scrim-overlay-strong:  rgb(var(--c-black) / 0.60);
  --scrim-control:         rgb(var(--c-black) / 0.42);
  --scrim-control-hover:   rgb(var(--c-black) / 0.65);
  --scrim-media-chip:      rgb(var(--c-scrim) / 0.50);
  --scrim-media-chip-strong: rgb(var(--c-scrim) / 0.55);
  --media-bottom-scrim: linear-gradient(to top,
    rgb(var(--c-black) / 0.85) 0%,
    var(--scrim-overlay-strong) 50%,
    transparent 100%);

  --glass-on-dark-bg:      var(--on-dark-surface-solid);
  --glass-on-dark-border:  var(--on-dark-border-glass);
  --glass-on-dark-sheen:   linear-gradient(130deg, rgb(var(--c-white) / 0.28), rgb(var(--c-white) / 0) 42%);

  --media-image-scrim:
    linear-gradient(180deg, rgb(var(--c-scrim) / 0.03) 14%, rgb(var(--c-scrim) / 0.72) 66%, rgb(var(--c-scrim) / 0.95) 100%),
    radial-gradient(circle at 82% 12%, rgb(var(--c-red-light) / 0.30), transparent 42%);
  /* Directional hero image scrims (darken a hero photo for text legibility —
     theme-independent media treatment; consumers reference the token). */
  --media-hero-scrim:       linear-gradient(to right, rgb(var(--c-navy-dark) / 0.85) 0%, rgb(var(--c-navy) / 0.5) 100%);
  --media-hero-scrim-light: linear-gradient(to right, rgb(var(--c-navy-dark) / 0.7) 0%, rgb(var(--c-navy) / 0.3) 100%);
  --media-hero-overlay:     linear-gradient(135deg, rgb(var(--c-navy-dark) / 0.85) 0%, rgb(var(--c-navy) / 0.6) 60%, rgb(var(--c-navy) / 0.3) 100%);
  /* Verlaufs-TEXT: der Text maskiert den Verlauf (background-clip:text). Die Technik
     steht EINMAL in components/effects.css (.u-text-gradient); hier leben nur die
     Werte. Bewusst über --color-text gebaut, nicht über einen Rohkanal: der Startton
     flippt im Dark-Mode automatisch mit. Consumer wählen per --text-gradient.
       accent  = Marken-Akzent (Rubrik-/Kategorie-Titel)
       primary = Navy-Fläche (Kennzahlen) */
  --gradient-text-accent:   linear-gradient(135deg, var(--color-text) 0%, var(--color-accent-light) 100%);
  --gradient-text-primary:  linear-gradient(135deg, var(--color-text), var(--color-primary));
  /* Bild-Abdunklung: helle Fotoflächen wirken im Dark gegen die dunkle UI grell. HELL = none
     (zero-visual); der Dark-Block setzt ein sanftes brightness/contrast. Consumer: Raster-Fotos
     (SVG/Logos/Icons ausgenommen), main.css. */
  --media-dim:              none;
  --carousel-showcase-bg:
    radial-gradient(circle at 12% 8%, rgb(var(--c-red) / 0.24), transparent 34%),
    radial-gradient(circle at 92% 0%, rgb(var(--c-white) / 0.12), transparent 26%),
    radial-gradient(circle at 64% 82%, rgb(var(--c-scrim-soft) / 0.55), transparent 48%),
    linear-gradient(145deg, rgb(var(--c-scrim)) 0%, rgb(var(--c-scrim-soft)) 54%, rgb(var(--c-scrim)) 100%);
  --carousel-card-radius: clamp(16px, 2vw, var(--radius-2xl));
  --carousel-card-radius-mobile: 22px;
  --carousel-card-border: rgb(var(--c-white) / 0.20);
  --carousel-card-border-mobile: rgb(var(--c-white) / 0.30);
  --carousel-card-border-hover: rgb(var(--c-red-light) / 0.38);
  --carousel-card-border-active-mobile: rgb(var(--c-red-light) / 0.34);
  --carousel-card-shadow:
    0 24px 54px rgb(var(--c-shadow-deep) / 0.52),
    inset 0 1px 0 rgb(var(--c-white) / 0.20),
    0 0 0 1px rgb(var(--c-white) / 0.06);
  --carousel-card-shadow-hover:
    0 24px 54px rgb(var(--c-shadow-deep) / 0.58),
    var(--glow);
  --carousel-card-shadow-active:
    0 28px 68px rgb(var(--c-shadow-deep) / 0.66),
    inset 0 1px 0 rgb(var(--c-white) / 0.20),
    var(--glow);
  --carousel-card-shadow-mobile:
    0 18px 38px rgb(var(--c-shadow-deep) / 0.48),
    inset 0 1px 0 rgb(var(--c-white) / 0.18),
    0 0 0 1px rgb(var(--c-white) / 0.08);
  --carousel-card-shadow-active-mobile:
    0 18px 38px rgb(var(--c-shadow-deep) / 0.52),
    inset 0 1px 0 rgb(var(--c-white) / 0.18),
    0 0 0 1px rgb(var(--c-red-light) / 0.30),
    0 0 16px rgb(var(--c-red-light) / 0.24),
    0 0 28px rgb(var(--c-red-light) / 0.12);
  --carousel-slide-transition: transform 620ms cubic-bezier(.2, .78, .2, 1), opacity 620ms cubic-bezier(.2, .78, .2, 1);
  --carousel-card-transition: border-color 280ms var(--ease-standard), box-shadow 280ms var(--ease-standard);
  /* Asymmetrisch: Kopfraum oben für den skalierten Active-Slide + Glow, unten
     bewusst knapp – die aktive Karte sitzt am TRACK-Top, d.h. jede Pixel unten
     ist Leerraum zwischen Karussell und den Pfeilen. Bottom klein halten. */
  --carousel-enhanced-padding: 56px 0 26px;
  --carousel-mobile-padding: var(--space-7) 0 var(--space-8);
  --carousel-mobile-tight-padding: 30px 0 36px;

  /* ── Karussell-Steuerung (SSOT — Story- & Jobs-Carousel-Controls) ───────────
     Prev/Next-Buttons + Zähler („4 / 6"). EIN Token-Satz steuert BEIDE Carousels
     (Story + Jobs, via :is()-Selektoren in carousel.css). Hier zentral Größe/Form
     ändern → beide ziehen nach. Mobil werden dieselben Tokens kompakter über-
     schrieben (siehe @media in carousel.css) – behebt das „auf Mobil zu breit".
     Für den eckigen/AWS-Look: -btn-radius + -bar-radius auf var(--radius-sm). */
  --carousel-ctrl-bar-radius:   var(--radius-full);  /* Pill-Container um die Controls          */
  --carousel-ctrl-bar-padding:  0.42rem;             /* Innenabstand des Pill-Containers        */
  --carousel-ctrl-gap:          0.6rem;              /* Abstand Button–Zähler–Button            */
  --carousel-ctrl-btn-size:     2.6rem;              /* Kantenlänge Prev/Next-Button            */
  --carousel-ctrl-btn-radius:   var(--radius-full);  /* Button-Form (full = rund)               */
  --carousel-ctrl-counter-min:  4.2rem;              /* Mindestbreite Zähler (kein Springen)    */
  /* Erscheinungsbild – cleaner AWS-Pill, ABER mit Bock-Glow-Schatten (Signature) */
  --carousel-ctrl-bar-bg:           rgb(var(--c-scrim) / 0.94);  /* flach-dunkler Pill, solide   */
  --carousel-ctrl-bar-border:       rgb(var(--c-white) / 0.10);  /* dezente Hairline             */
  --carousel-ctrl-bar-border-hover: rgb(var(--c-red-light) / 0.30); /* roter Rand bei Hover       */
  --carousel-ctrl-btn-hover-bg:     rgb(var(--c-white) / 0.12);  /* dezenter Hover-Kreis (Ghost) */
  /* Tiefe + roter Glow – DAS ist der Signature-Glow, der bleiben muss.
     Schon im Ruhezustand sanft sichtbar, bei Hover kräftiger. */
  --carousel-ctrl-bar-shadow:
    inset 0 1px 0 rgb(var(--c-white) / 0.16),
    0 14px 32px rgb(var(--c-black) / 0.34),
    0 0 0 1px rgb(var(--c-white) / 0.06),
    0 0 18px rgb(var(--c-red-light) / 0.13);
  --carousel-ctrl-bar-shadow-hover:
    inset 0 1px 0 rgb(var(--c-white) / 0.16),
    0 12px 28px rgb(var(--c-black) / 0.30),
    0 0 0 1px rgb(var(--c-red-light) / 0.16),
    0 0 24px rgb(var(--c-red-light) / 0.26);

  /* ── Übergänge (cubic-bezier – Michi-Design) ─────────── */
  --transition-fast:   150ms var(--ease-standard);
  --transition-base:   300ms var(--ease-standard);
  --transition-slow:   600ms var(--ease-standard);
  --transition-slower: 600ms var(--ease-standard);

  /* ── Layout ───────────────────────────────────────────── */
  --container-max:  1280px;
  --container-wide: 1400px;
  /* Equal-column grid track: schrumpft unter Content-Minimum statt bei langen
     Wörtern / CTA-Zeilen horizontal zu überlaufen. Für repeat(N, …)-Grids. */
  --grid-track-fluid: minmax(0, 1fr);
  /* Zentrierte Fließtext-/Lede-Breite (Section-Subtitle, Intro-Absätze).
     Konsolidiert die früher driftenden Inline-Breiten (640/660/680px) auf
     EINEN Wert → über .u-measure referenziert. Hier zentral steuerbar. */
  --measure:        680px;
  /* Lange Lesetexte: zeichenbasiertes Lese-Maß (optimale Zeilenlänge). */
  --measure-text:   72ch;
  --nav-height:     64px;   /* leaner bar (war 72px) — EIN Token, hero/offset folgen automatisch */
  /* Höhe des Sprachvorschlag-Banners (.bm-ls-banner). Standard 0; nur wenn der
     Banner per JS eingeblendet wird, setzt das Skript hier die gemessene Höhe.
     So stapelt sich der Banner ÜBER der Navbar, statt sie zu überdecken. */
  --ls-banner-h:    0px;
  /* Gesamthöhe des fixierten Header-Stacks (Banner + Navbar) = die Stelle, an
     der der Seiteninhalt beginnt. EINE Quelle für Body-Offset, Navbar-Top,
     Hero-Höhe, Anker-Offset und die nav-verankerten Menüs. */
  --header-offset:  calc(var(--ls-banner-h) + var(--nav-height));
  --section-py:     var(--space-20);

  /* ── Prozess-Schiene (.section--rail / .proc-index--rail) ──────────────
     Die Sprung-Navi als STICKY Fortschrittsleiste unter dem Header statt
     als frei schwebendes Pillen-Band (das verlor gemessen 208 von 258 px
     Höhe an Luft, 1280 px, 2026-08-04). EIN Ort für Rhythmus + Knotenmaß.
     --rail-h ist nur der JS-freie Vorgabewert für scroll-padding-top;
     main.js zieht ihn auf die real gemessene Höhe nach (Zoom, Umbruch,
     Sprachbanner ändern sie). */
  --rail-py:        var(--space-3);
  --rail-max:       940px;  /* Breite bis 6 Schritte; darüber greift die
                               Mengen-Query in sticky-cards.css */
  --rail-node:      30px;   /* Durchmesser des nummerierten Knotens */
  --rail-line:      2px;    /* Stärke der durchgehenden Schiene     */
  --rail-h:         56px;   /* Fallback-Höhe, bis das JS nachmisst  */
  --rail-z:         calc(var(--z-nav) - 1);

  /* ── Hero / Media ─────────────────────────────────────── */
  /* Shared design tokens for ALL hero videos (homepage .hero +
     subpage .page-hero). Central control — change once, every hero
     follows. The mobile breakpoint (767px) is mirrored in main.css
     @media and assets/js/main.js matchMedia; keep the three in sync.
     Bytes/encodes live in content/videos.yaml (the video SSOT). */
  --hero-min-height:      640px;      /* homepage full-bleed hero floor   */
  --hero-video-fade:      1.2s;       /* poster → video cross-fade         */
  --hero-poster-position: center 30%; /* homepage poster focal point       */
  /* BILD-Karussell-Hero (optional, ≥2 hero_images) — Crossfade-Dauer der
     Slides. Das Auto-Advance-Intervall (--hero-carousel-interval) setzt das JS
     aus seiner EINEN Konstante (SSOT), damit Dot-Fortschritt & Wechsel synchron
     laufen; Fallback hier für No-JS/Print. */
  --hero-carousel-fade:     0.9s;
  --hero-carousel-interval: 6s;
  /* Text-Schutz über (farbwechselnden) Video-Heroes — garantiert Lesbarkeit
     auf JEDEM Frame (weiß-auf-weiß-Problem). Reines CSS = 0 PageSpeed-Kosten.
     Zentral hier steuerbar: Scrim-Stärke + Textschatten. */
  --hero-scrim: linear-gradient(             /* dunkler Verlauf hinter dem Text */
                  to top right,
                  rgb(var(--c-shadow-deep) / 0.82) 0%,
                  rgb(var(--c-shadow-deep) / 0.55) 45%,
                  rgb(var(--c-shadow-deep) / 0.22) 100%);
  --hero-text-shadow: 0 2px 10px rgb(var(--c-shadow-deep) / 0.55),
                      0 1px 2px  rgb(var(--c-shadow-deep) / 0.65);
  /* Neutraler Marken-Backdrop für Video-Heroes, der das Seitenverhältnis hält:
     füllt die Pillar-/Letterbox-Ränder (Hochformat-Video bzw. contain) und liegt
     unsichtbar hinter Vollbild-Videos. */
  --hero-media-backdrop: linear-gradient(
                  180deg,
                  rgb(var(--c-shadow-deep) / 0.94) 0%,
                  rgb(var(--c-shadow-deep) / 0.80) 42%,
                  rgb(var(--c-shadow-deep) / 0.94) 100%);
  /* GESTACKTER Video-Hero (Video-Band oben, Text-Panel darunter) gilt auf ALLEN
     Breakpoints. Auf Mobil/Tablet wächst das Band mit dem Seitenverhältnis;
     auf Desktop wird es zu einem „Cinematic Banner" gedeckelt (sonst wäre ein
     16:9-Video bildschirmhoch). EIN Token = die Bandhöhe auf Desktop zentral
     steuerbar. Querformat füllt das Band (cover), Hochformat zeigt den ganzen
     Frame (contain, Ränder = --hero-media-backdrop). */
  --hero-band-height: clamp(440px, 62vh, 680px);
  /* BILD-Hero (Unterseiten, Text-Overlay): der bewährte Cover-Look bleibt; die
     Hero-Höhe wird pro Seite moderat angehoben, wenn das Bild quadratisch/hoch
     ist (sonst harter vertikaler Crop). Den Wert (--page-hero-h) berechnet das
     page_hero-Macro automatisch aus den Bildmaßen (build_site _make_page_hero_
     height, Bereich 50–68vh). Diese Variable ist nur der Fallback-Boden. */
  --page-hero-h: 50vh;
  /* MOBIL-SOLO Bild-Hero (page_hero mobile_solo=true, Default): auf Mobil wird der
     Bild-Hero — exakt wie der Video-Hero der Startseite — GESTACKT: Bild als
     freistehendes Querformat-Band OBEN (kein Text-Overlay), Text-Panel darunter
     auf dunklem Grund. Das feste Querformat-Band vermeidet den harten Hochformat-
     Crop und jedes Quer↔Hoch-Springen. EIN Token = die Band-HÖHE (= 16:9 der
     vollen Breite: 100vw × 9/16). Steuert zugleich die Dot-Verankerung an der
     Band-Unterkante (die Dots liegen absolut zur Section, das Band ist deren
     oben bündiges erstes Kind) → EINE Quelle, kein Desync. Pro Seite via inline
     --hero-solo-band überschreibbar. Gilt nur ≤767px; ab 768px Overlay-Look. */
  --hero-solo-band: 56.25vw;
  /* …ENTHÄLT die Sequenz ein HOCHFORMAT-Medium (Karussell-Video hochkant), wird
     das Band von 16:9 auf 4:3 vertieft (100vw × 3/4). Grund: der hochkant gezeigte
     Frame ist nur so breit wie das Band hoch ist — in einem 16:9-Band bliebe er
     mickrig (45 % der Breite), in 4:3 füllt er 60 %. Die Querformat-Bilder
     derselben Sequenz kostet das ~11 % Randbeschnitt (3:2 → 4:3). Greift NUR auf
     Seiten mit Hochformat-Medium; alle anderen Heroes bleiben unberührt. */
  --hero-solo-band-portrait: 75vw;
  /* Kantenlänge der runden Hero-Bedienelemente (WCAG-Pause/Play). 44 px ist das
     Touch-Mindestziel. EIN Token, weil die Größe zweimal gebraucht wird: für den
     Button selbst UND für seine Verankerung an der Band-Unterkante im Mobil-Solo-
     Layout (top = Bandhöhe − Buttonhöhe − Rand). Zwei Literale wären genau die
     Art Desync, die den Button unter das Band rutschen lässt. */
  --hero-control-size: 44px;
  /* FÜLL-EBENE für ein contain-gezeigtes Hochformat-Medium (.bm-media-fill):
     die frei bleibenden Seitenflächen zeigen eine weich unscharfe, abgedunkelte
     Kopie DESSELBEN Frames statt toter schwarzer Balken — das Band wirkt gefüllt,
     der Clip bleibt vollständig. Unschärfe stark genug, dass nichts vom Motiv
     ablenkt; Abdunklung hält den scharfen Frame vorn. Der leichte Maßstab
     verdeckt die weichen Kanten, die blur() am Rand erzeugt. */
  --hero-fill-blur:  var(--blur-xl);
  --hero-fill-dim:   0.55;
  --hero-fill-scale: 1.12;

  /* ── Navbar (IMMER solide & frosted – nie transparent) ───────────────
     Entscheidung: der Header trägt auf JEDER Seite und in JEDEM Scroll-Zustand
     einen dezent geblurrten Graphit-Hintergrund. Weiß-auf-Graphit ist damit
     bombensicher lesbar — egal welches Hero-Bild/Video dahinter liegt; kein
     Moduswechsel, kein Lesbarkeits-Glücksspiel. Beim Scrollen verdichtet sich
     die Fläche minimal und gewinnt einen Schatten (Elevation). Hier zentral
     dosierbar — Pendant zu den card- und field-Token-Familien für die Nav. */
  --nav-bg:               rgb(var(--c-navy) / 0.92);   /* frosted: leicht durchscheinend + Blur */
  --nav-bg-scrolled:      rgb(var(--c-navy) / 0.97);   /* bei Scroll etwas dichter             */
  --nav-blur:             var(--blur-lg);
  --nav-border:           rgb(var(--c-white) / 0.08);  /* feine untere Trennlinie              */
  --nav-border-scrolled:  rgb(var(--c-white) / 0.10);
  --nav-shadow-scrolled:  var(--shadow-lg);            /* Elevation erst nach dem Lösen vom Top */

  /* ── Z-Index Ebenen ───────────────────────────────────── */
  --z-base:     0;
  --z-overlay:  10;
  --z-nav:      100;
  --z-dropdown: 150;  /* nav-anchored menus (Sprachumschalter) – über Nav, unter Modal */
  --z-modal:    200;
  --z-toast:    300;
}

/* ── Dark Section Override ────────────────────────────── */
.dark-section {
  --color-bg:        var(--color-primary);
  --color-text:      var(--color-text-inverse);
  --color-text-muted:var(--color-gray-300);
  --color-border:    var(--color-border-dark);
  /* Akzent-Text/Links auf dem dunklen Band → helleres Rot (Brand-Rot #d7002b erreicht auf
     diesem Band nur 3.23:1). Gilt in BEIDEN Themes (das Band ist immer dunkel). */
  --color-accent-text: rgb(var(--c-red-200));
  /* Überschriften/Labels auf dem dunklen Band → hell (sonst Navy-auf-Navy). */
  --color-heading:     var(--color-text-inverse);
}

/* ── Honorary-Dark-Bänder (KEINE .dark-section) ───────────────────────────────
   Diese Bänder setzen ihre Navy-/Schwarz-Fläche SELBST über --color-bg-dark bzw.
   einen Primary-Gradient (dunkel in BEIDEN Themes), sind aber nicht .dark-section.
   Darum flippen hier die KONTEXT-abhängigen Ink-Tokens nicht automatisch → ohne
   diesen Block löst --color-accent-text/-heading zum HELLEN Wert auf (dunkelrot/
   navy auf Navy). Nur die Ink-Rollen flippen; die Fläche managen die Bänder selbst. */
.karriere-banner,
.usp-strip {
  --color-accent-text: rgb(var(--c-red-200));
  --color-heading:     var(--color-text-inverse);
  /* Diese Bänder sind in BEIDEN Themes dunkel → Body-/Muted-Text muss in beiden hell
     sein. Ohne dies erben Komponenten (.usp-text, .karriere-text) die kontext-flippenden
     Text-Tokens, die im Dark auf dunkles Grau kippen (grau-auf-dunkel). Auf on-dark-
     Tokens (fix, nicht-flippend) umgebogen → immer hell auf dem dunklen Band. */
  --color-text:       var(--on-dark-text);
  --color-text-muted: var(--on-dark-text-muted);
}

/* ════════════════════════════════════════════════════════
   3 · THEME SWITCH  —  ganze Paletten testen, ohne den Rest anzufassen
   ════════════════════════════════════════════════════════
   Mechanik: setze data-theme="<name>" am <html> (über config.yaml →
   site.theme). Überschreibe in einem [data-theme]-Block NUR die RAW
   CHANNELS — das komplette abgeleitete System folgt automatisch.
   Aktivieren:  config.yaml → site.theme: classic-navy   (dann neu bauen)

   Default (kein data-theme) = der aktuelle Champions-League-Look:
   Rot + Weiß + neutrales Off-White + Graphit.
   ════════════════════════════════════════════════════════ */

/* „classic-navy" – der frühere Look (tiefes Navy statt Graphit).
   Nur als Rückfall/Vergleich; nicht der Default. */
[data-theme="classic-navy"] {
  --c-navy:        26 39 68;        /* #1a2744 · role:neutral-surface */
  --c-navy-light:  36 53 96;        /* #243560 · role:neutral-surface */
  --c-navy-dark:   15 26 46;        /* #0f1a2e · role:neutral-surface */
  --c-scrim:        8 15 28;        /* #080f1c · role:scrim */
  --c-scrim-soft:  15 32 66;        /* #0f2042 · role:scrim */
  --c-shadow:      15 23 42;        /* Slate-Schatten · role:shadow */
  --c-slate-800:   30 41 59;  /* role:neutral-surface */
}

/* ════════════════════════════════════════════════════════
   DARK MODE  —  Opt-in (KEIN OS-Auto). Das externe assets/js/theme-init.js setzt
   data-theme="dark" pre-paint aus localStorage['bm-theme']; Default (ohne Attribut)
   = der helle Champions-League-Look. Der Toggle sitzt im Header (nav.html.jinja).

   Überschreibt NUR die KONTEXT-FLIPPENDE Ebene (--color-*) + invertiert die
   Grau-Kanäle. Die FIXEN oberflächen-relativen Tokens (--on-dark-*/--scrim-*/
   --glass-*/--media-*) bleiben absichtlich unverändert — eine dunkle Insel
   (Lightbox, Hero-Scrim, Ghost-Button) ist in beiden Modi dunkel. Siehe
   docs/styling/dark-mode-readiness.md (Zwei-Schichten-Modell).
   ════════════════════════════════════════════════════════ */
:root { color-scheme: light; }

:root[data-theme="dark"] {
  color-scheme: dark;

  /* ── Flächen: Graphit-Elevationsleiter 17 → 25 → 38 (Tiefe via hellerer Fläche) ── */
  --color-bg:        rgb(var(--c-navy-dark));   /* #111315 tiefster Grund      */
  --color-bg-alt:    rgb(var(--c-navy));        /* #191b1d subtil angehoben    */
  --color-bg-dark:   rgb(var(--c-black));       /* #000000 tiefste Fläche      */

  /* ── Text: weiches Weiß (On-Dark-Muster, bewusst kanal-unabhängig) ── */
  --color-text:        rgb(var(--c-white) / 0.92);
  --color-text-muted:  rgb(var(--c-white) / 0.62);
  --color-text-light:  rgb(var(--c-white) / 0.45);
  /* --color-text-inverse bleibt Weiß (Text auf Akzent-Rot in beiden Modi) */

  /* ── Akzent-Text/Links/Fokus → helleres Rot (Brand-Rot #d7002b nur 3.48:1 auf Dunkel).
       Die FLÄCHE (--color-accent, Button-BG) bleibt sattes Brand-Rot (Weiß darauf = 5.35:1). ── */
  --color-accent-text: rgb(var(--c-red-200));

  /* Überschrift/Label-Text → Weiß (im Hellen = Primary-Navy). --color-primary bleibt als
     FLÄCHE dunkel; nur diese Text-Rolle flippt. */
  --color-heading:     rgb(var(--c-white));

  /* ── Ränder: feine helle Haarlinie auf Dunkel ── */
  --color-border:      rgb(var(--c-white) / 0.12);
  --color-border-dark: rgb(var(--c-white) / 0.22);

  /* ── Neutral-Grauskala invertiert (hell↔dunkel), damit grau-basierte Flächen
       kippen. --on-dark-* nutzt KEINE Grays → bleibt unberührt. ── */
  --color-gray-50:   rgb(var(--c-navy-dark));
  --color-gray-100:  rgb(var(--c-scrim));
  --color-gray-200:  rgb(var(--c-scrim-soft));
  --color-gray-300:  rgb(var(--c-gray-600));
  --color-gray-400:  rgb(var(--c-gray-500));
  --color-gray-500:  rgb(var(--c-gray-400));
  --color-gray-600:  rgb(var(--c-gray-300));
  --color-gray-700:  rgb(var(--c-gray-200));
  --color-gray-800:  rgb(var(--c-gray-100));
  --color-gray-900:  rgb(var(--c-gray-50));

  /* ── Status: dunkle Tints statt blasser Flächen; „dark"-Text (auf Tint) → hell ── */
  --color-success-bg:    rgb(var(--c-success) / 0.15);
  --color-success-dark:  rgb(var(--c-success-light));
  --color-warning-bg:    rgb(var(--c-warning) / 0.15);
  --color-warning-dark:  rgb(var(--c-warning));
  --color-error-bg:      rgb(var(--c-error) / 0.15);
  --color-error-bg-soft: rgb(var(--c-error) / 0.08);
  --color-error-dark:    rgb(var(--c-error-light));  /* #ef4444 auf Tint nur 4.28:1 → heller */

  /* ── Subtile Marken-/Primär-Tints auf Dunkel etwas kräftiger ── */
  --color-accent-bg:       rgb(var(--c-red) / 0.14);
  --color-accent-bg-hover: rgb(var(--c-red) / 0.20);
  --color-primary-bg:      rgb(var(--c-white) / 0.05);

  /* ── Formularfelder auf Dunkel: die Hell-Defaults (--field-hover-bg = reines Weiß!,
       feine graue Linie) bringen im Dark weiß-auf-weiß bzw. unsichtbare Felder. Hier
       auf angehobene dunkle Fläche + wahrnehmbare helle Ränder umgestellt. ── */
  --field-hover-bg:     rgb(var(--c-scrim-soft));   /* #262a2e statt Weiß */
  --field-border:       rgb(var(--c-white) / 0.30);
  --field-hover-border: rgb(var(--c-white) / 0.45);

  /* Foto-Abdunklung im Dark: sanft, nimmt Blendung ohne Detailverlust (Logos/Icons = SVG,
     ausgenommen). Consumer-Regel in main.css. */
  --media-dim:          brightness(0.92) contrast(1.02);

  /* Gallery-Hover-Caption: der Balken --gallery-label-bg ist im Hellen fixes Weiß (c-white),
     die Schrift --gallery-label-text = --color-text flippt im Dark auf Weiß → weiß-auf-weiß.
     Balken hier auf dunkle Fläche umstellen (Schrift bleibt --color-text = weiß) → weiß-auf-
     dunkel. Spiegelt den bereits vorhandenen Mobil-Fix (@media(hover:none)) fürs Desktop. */
  --gallery-label-bg:   rgb(var(--c-navy) / 0.94);

  /* Video-Showcase Touch-Play-Badge: die Scheibe --vshow-badge-bg ist eine FIXE weiße Insel
     (in beiden Themes weiß) → ihr Vordergrund muss ebenfalls fix sein, nicht das flippende
     --color-text (das im Dark zu Weiß wird = weiß-auf-weiß). Auf fixes Ink umgestellt. */
  --vshow-badge-text:   rgb(var(--c-ink));

  /* Google-Maps-Consent-Mock → Google-DARK-Look (Maps hat selbst einen Dark-Mode), damit die
     Consent-Zone im Dark keine grelle helle Insel neben der themen-korrekten Reichweitenkarte
     ist. Der helle map-preview.svg wird per Filter abgedunkelt (ein Asset, via data-theme). */
  /* ssot-ok:block-start — Google-Maps-Mock: Google-Dark-Palette (Foreign-Brand-Decor) */
  --consent-chrome-bg:      #303134;
  --consent-chrome-ink:     #e8eaed;
  --consent-chrome-icon:    #9aa0a6;
  --consent-chrome-divider: #5f6368;
  --consent-logo-bg:        #3c4043;
  --consent-link:           #8ab4f8;
  --consent-link-hover:     #aecbfa;
  --consent-preview-filter: brightness(0.60) saturate(0.9) contrast(1.05);
  /* ssot-ok:block-end — Google-Maps-Mock-Dark-Palette */

  /* ── Schatten auf Dunkel: reines Schwarz (Tiefe trägt v.a. die hellere Fläche) ── */
  --c-shadow: 0 0 0;
}

/* `.dark-section` im Dark Mode = HELLERE Kontrast-Sektion (Rhythmus INVERTIERT):
   im hellen Fluss ein dunkles Band → im dunklen Fluss ein angehobenes helleres
   (Elevation), Text/Akzente bleiben on-dark. Owner-Entscheidung 2026-07-09. */
:root[data-theme="dark"] .dark-section {
  --color-bg:         rgb(var(--c-scrim-soft));  /* #262a2e — angehoben ggü. #191b1d */
  --color-text:       rgb(var(--c-white) / 0.92);
  --color-text-muted: rgb(var(--c-white) / 0.62);
  --color-border:     rgb(var(--c-white) / 0.14);
}
