/*
 * Mockarty Design System — Design Tokens
 * ========================================
 * Single source of truth for all visual properties across 14+ UI applications.
 *
 * Usage:
 *   - External CSS apps: <link rel="stylesheet" href=".../tokens.css">
 *   - Inline CSS apps:   inject via designsystem.TokensCSS() Go helper
 *
 * DO NOT duplicate these values in individual app stylesheets.
 * Apps may override specific tokens for their context (e.g., website uses larger fonts).
 */

/* ────────────────────────────────────────────────
   Inter Font — Local Embed (no Google Fonts CDN)
   ──────────────────────────────────────────────── */

@font-face {
    font-family: 'Inter';
    src: url('fonts/Inter-Variable.woff2') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

/* ────────────────────────────────────────────────
   Responsive Breakpoints (standard reference)
   ──────────────────────────────────────────────────
   CSS custom properties cannot be used inside @media queries,
   so these values are documented here as the canonical reference.
   All component stylesheets MUST use these exact pixel values.

   sm:  480px  — mobile phones (portrait)
   md:  768px  — tablets (portrait)
   lg:  1024px — small desktops / tablets (landscape)
   xl:  1280px — desktops
   2xl: 1440px — large desktops / wide monitors
   ──────────────────────────────────────────────── */

/* ────────────────────────────────────────────────
   Color Palette — Semantic Colors
   ──────────────────────────────────────────────── */

:root {
    /* Global UI scale — shrinks the whole interface ~7% by default for denser,
       more readable layout (≈ working at 93% browser zoom). Applied via
       `html { zoom: var(--ui-scale) }` in main.css. Adjustable in one place. */
    --ui-scale: 0.93;

    /* Zoom-compensated viewport height. Under html{zoom:--ui-scale}, a literal
       var(--vh100) renders at scale×var(--vh100) and leaves a ~7% strip at the bottom of every
       full-height layout. Use var(--vh100) instead of var(--vh100) in height/max-height
       so containers fill the real screen. Works inside calc(): calc(var(--vh100)
       - 64px). One knob — change --ui-scale and both scale + heights track. */
    --vh100: calc(100vh / var(--ui-scale, 1));

    /* Backgrounds */
    --bg-primary: #ffffff;
    --bg-secondary: #f8fafc;
    --bg-tertiary: #e3eaf4;

    /* Elevated surfaces — aliases over the bg ramp. Defined as var()
       references so they follow the active theme automatically (custom
       properties resolve at use-time against the cascaded --bg-* value).
       Some components (tcm.css incl. the TCM "Views" modal) reference these
       directly; without a definition they fell back to a hard-coded #fff and
       rendered white in dark mode. */
    --surface-1: var(--bg-primary);
    --surface-2: var(--bg-secondary);

    /* Text */
    --text-primary: #0a1628;
    --text-secondary: #2a3f5c;
    --text-muted: #586f8e; /* a11y: was #5d7899 — 4.35:1 on --bg-secondary (panels) failed AA; this clears 4.5:1 on both white and the off-white panel bg */

    /* Borders */
    --border-color: #c8d6e8;

    /* Auto-hide scrollbar thumb (light). Paints only while scrolling / on hover. */
    --scrollbar-thumb: rgba(93, 120, 153, 0.45);
    --scrollbar-thumb-hover: rgba(93, 120, 153, 0.72);

    /* Accent */
    --accent-color: #1a73d4;
    --accent-hover: #155fb0;
    --accent-light: #e6f0fd;
    /* Accent colour for TEXT specifically. The brand accent (#1a73d4) is AA on
       pure white (4.7:1) but drops below 4.5:1 once it sits on a faint accent /
       blue tint (chips, selected pills, tinted headers, badge counters) — a
       recurring contrast miss. --accent-text is a slightly darker accent that
       clears AA on white AND on those tints (#1565c0 → 5.75:1 white / 4.75:1 on
       the strongest tint) while staying a recognisable accent blue. Fills,
       borders and icons keep --accent-color; only text routes here. Dark theme
       maps it back to --accent-color (the light-blue accent is already AA on the
       dark canvas). */
    --accent-text: #1565c0;
    /* Text/icon colour to place ON an accent fill (primary buttons, avatars,
       selected chips). Light theme: white on the #1a73d4 accent (4.7:1, AA).
       The dark theme overrides this to a near-black because its accent is a
       light blue (#64b5ff) where white text fails WCAG AA (2.2:1) — see .dark
       block. */
    --accent-contrast: #ffffff;
    /* Text/icon colour to place ON a BRIGHT status fill (success green, info
       cyan, warning amber). These fills are light in BOTH themes, so white text
       fails WCAG AA (success btn was 1.9:1) — use a fixed near-black. Theme-
       invariant on purpose (the fills don't darken in dark mode). */
    --on-bright-fill: #0a1628;
    /* Brand accent gradient — the blue panel/card header fill. Defined once so a
       designer can retune the brand sheen (angle + stops) in a single place. */
    --gradient-accent: linear-gradient(135deg, var(--accent-color), var(--accent-hover));
    /* Secondary accent — purple. Used for status pills on
       manual_pending / paused (audit P1-9). */
    --accent-purple: #9333ea;

    /* ── Selection (UNIFIED, readable) — light ──────────────────────────────
       The single source of truth for "this row/card is selected" everywhere
       (mock list, api-tester tree, TCM, pickers, …). A subtle accent WASH (not
       a saturated fill) + an accent edge: body text and coloured badges stay
       legible on top. Depth variants step the tone darker→lighter so nested
       selected rows still read as a hierarchy without losing contrast. */
    --selected-bg: rgba(45, 140, 240, 0.16);   /* depth 0 / flat lists */
    --selected-bg-2: rgba(45, 140, 240, 0.11); /* nested one level */
    --selected-bg-3: rgba(45, 140, 240, 0.07); /* nested deeper */
    --selected-border: var(--accent-color);
    --selected-text: var(--text-primary);      /* readable on the wash */

    /* Status */
    --success-color: #10b981;
    --danger-color: #ef4444;
    --warning-color: #f59e0b;
    --info-color: #06b6d4;
    /* Severity scale (5 tiers) — fuzzing/security/contract/findings use a finer
       ramp than the 4 status colours. Single source so CSS and the Go report
       exporters agree (they had diverged: fuzzing #ea580c, contract #dc2626…).
       solid = dot/bar/badge fill; -bg = soft chip tint. */
    --severity-critical: #dc2626;
    --severity-high: #ea580c;
    --severity-medium: #d97706;
    --severity-low: #0891b2;
    --severity-info: #64748b;
    --severity-critical-bg: rgba(220, 38, 38, 0.12);
    --severity-high-bg: rgba(234, 88, 12, 0.12);
    --severity-medium-bg: rgba(217, 119, 6, 0.12);
    --severity-low-bg: rgba(8, 145, 178, 0.12);
    --severity-info-bg: rgba(100, 116, 139, 0.12);
    /* Short aliases — a few component styles reference the bare names
       (e.g. TCM steward severity dots, filter chip hovers); map them to the
       canonical -color tokens so those elements aren't left colourless. */
    --success: var(--success-color);
    --danger: var(--danger-color);
    --warning: var(--warning-color);
    --info: var(--info-color);

    /* Legacy structural aliases. Several component stylesheets (the TCM data
       designer .tcm-data__*, TCM list borders, the test-plans tree picker
       .mty-tree-picker__*, a few admin rules) reference these short names with
       NO var() fallback — they were never defined anywhere, so the property was
       invalid → transparent bg / default-black text, ignoring the theme in BOTH
       light and dark. Alias them to the canonical theme-aware tokens here (one
       place) so every bare usage resolves and adapts per theme. New code should
       use the canonical names directly. */
    --bg: var(--bg-primary);
    --fg: var(--text-primary);
    --text: var(--text-primary);
    --card: var(--bg-secondary);
    --surface: var(--bg-secondary);
    --surface2: var(--bg-tertiary);
    --bg-surface: var(--bg-secondary);
    --accent: var(--accent-color);
    --primary-color: var(--accent-color);
    --muted: var(--text-secondary);
    --fail: var(--danger-color);
    --border: var(--border-color);
    --border-default: var(--border-color);
    --border-subtle: var(--border-color);

    /* Status pill backgrounds + text. Alpha tints so they read correctly over
       BOTH the light and dark surfaces (a solid pastel would be wrong in dark).
       These were previously only ever supplied via inline var() fallbacks;
       defining them centrally fixes the bare usages (e.g. the TCM runs-list
       status pills rendered with no background) and harmonises the scattered
       fallbacks. */
    --success-bg: rgba(16, 185, 129, 0.12);
    /* Status TEXT tokens are darkened on light theme so status text meets WCAG
       AA (4.5:1) on white — the raw --*-color values are tuned for borders/
       fills/icons (3:1) and fail as small text: success #10b981=2.54,
       warning #f59e0b=2.15, info #06b6d4=2.43. Dark theme keeps the bright
       --*-color values (they're already ~10:1 on the dark base). */
    --success-text: #047857;
    --danger-bg: rgba(239, 68, 68, 0.12);
    /* Danger TEXT (small inline errors / failed-status labels) needs WCAG AA
       (4.5:1) for <18px text — but --danger-color #ef4444 on white is only
       3.77:1. Use a darker red here (#dc2626 = 4.74:1 on #fff). The border/glow
       keep --danger-color (non-text → 3:1 is fine). Dark theme overrides this
       to the lighter #f87171 (~6.5:1 on the dark base). */
    --danger-text: #dc2626;
    --info-bg: rgba(6, 182, 212, 0.12);
    --info-text: #0e7490;

    /* Warning banner */
    --warning-bg: #fef3c7;
    --warning-fg: #92400e;
    --warning-text: #b45309;

    /* ── Badge / chip / tag / pill SHAPE (U3 unification) ───────────────────
       The colour system above (status -bg/-text) is solid; what drifts across
       the ~300 bespoke badge classes is the BOX (padding/radius/font). These
       are the canonical .badge metrics — bespoke badges migrate onto them wave
       by wave so every pill reads at the same scale. Values = current canon,
       so wiring is a zero-shift change. */
    --badge-pad-y: 2px;
    --badge-pad-x: var(--space-2);   /* 8px */
    --badge-radius: var(--radius-pill);
    --badge-font: var(--font-xs);
    --badge-weight: 500;
    /* Two legitimate badge SHAPES: pill (above, status/info) and TAG —
       a rectangular label for protocol/method/type (HTTP, GET, …). The tag
       shape is its own canon so method/protocol pills stay square; values =
       the current protocol/method metrics (zero-shift migration). */
    --badge-tag-radius: var(--radius-xs);   /* 4px */
    --badge-tag-pad-y: 0.15rem;             /* ≈2.4px */
    --badge-tag-pad-x: 0.4rem;              /* ≈6.4px */

    /* Shadows — the base surfaces stay flat by design (--shadow-sm/--shadow/
       --shadow-lg = none). These are kept for compatibility. */
    --shadow-sm: none;
    --shadow: none;
    --shadow-hover: none;
    --shadow-lg: none;

    /* Elevation scale — refined, low-opacity drop shadows for surfaces that
       genuinely FLOAT (popovers, dropdowns, modals, drawers, lightbox). The
       single source so a designer retunes depth everywhere from here; dark
       theme overrides these with stronger values below. 1=resting card,
       2=popover, 3=dropdown/menu, 4=modal, 5=full-screen overlay. */
    --shadow-1: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.10);
    --shadow-2: 0 2px 8px rgba(15, 23, 42, 0.10);
    --shadow-3: 0 6px 18px rgba(15, 23, 42, 0.14);
    --shadow-4: 0 12px 32px rgba(15, 23, 42, 0.18);
    --shadow-5: 0 24px 60px rgba(15, 23, 42, 0.26);
    /* Focus ring — one token for the keyboard/active focus glow. */
    --focus-ring: 0 0 0 3px rgba(45, 140, 240, 0.18);
    --focus-ring-danger: 0 0 0 3px rgba(239, 68, 68, 0.22);

    /* Z-index scale — the app's global overlay layers, value-preserving (each
       token == the magic number it replaced, so stacking order is unchanged).
       Local component stacking (<800: badges over cards, sticky cells) stays
       inline — it's contextual, not a global layer. */
    --z-raised: 900;
    --z-dropdown: 1000;
    --z-popover: 1300;
    --z-overlay: 9000;
    --z-modal: 10000;
    --z-modal-content: 10001;
    --z-modal-popover: 10050;
    --z-toast: 100000;

    /* Hover — single standard hover style */
    --hover-overlay: rgba(0, 0, 0, 0.04);
    --hover-overlay-strong: rgba(0, 0, 0, 0.07);

    /* Typography — base 15px, step 2px (11-13-15-17-19-21-25) */
    --font-xs: 0.6875rem;   /* 11px — captions, micro-labels */
    --font-sm: 0.8125rem;   /* 13px — secondary text, labels */
    --font-base: 0.9375rem; /* 15px — body, main content */
    --font-md: 1.0625rem;   /* 17px — emphasized body, subheads */
    --font-lg: 1.1875rem;   /* 19px — section titles */
    --font-xl: 1.3125rem;   /* 21px — page headings */
    --font-2xl: 1.5625rem;  /* 25px — large headings */
    --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;

    /* U3: font-weight scale. 815 hardcoded weights across the tree (600×454,
       500×167, 700×127, 400×36) and no token before. Values == the current
       dominant weights, so wiring them on is zero-shift; one knob to retune the
       whole type system's emphasis (the Apple/JetBrains direction uses a
       different weight ramp). */
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;

    /* Spacing */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-8: 3rem;

    /* Border Radius */
    --radius-xs: 4px;
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 16px;
    --radius-modal: 12px;
    --radius-pill: 999px;

    /* Modal width scale — single source for BOTH the MockartyModal component
       (.mockarty-modal-dialog) and the legacy .modal-content system. Retune
       every modal width here. Owner directive (KIT-1): modals were too wide —
       the scale is sized down toward a compact default; pick the smallest size
       that fits the content. */
    --modal-w-xs: 360px;   /* confirm/prompt, single-field */
    --modal-w-sm: 400px;   /* small forms */
    --modal-w-md: 520px;   /* default */
    --modal-w-lg: 760px;   /* wide forms / 2-col */
    --modal-w-xl: 940px;   /* tables / import preview */
    /* Modal backdrop — one scrim for every overlay so dimming + blur are tuned
       in one place (the MockartyModal canon value). */
    --modal-backdrop: rgba(0, 0, 0, 0.45);
    --modal-backdrop-blur: 6px;

    /* U1: ONE shared radius for interactive controls (buttons, inputs, selects,
       textareas). Owner 2026-06-16: 6px. Change here → every control updates.
       Radius-only, so no box-model shift. */
    --control-radius: var(--radius-sm); /* 6px */

    /* U1: shared box for text controls (input/select/textarea). Values are the
       CURRENT dominant metrics (form-input height 36px, font-md 15px) so wiring
       a control to these tokens is a zero-shift migration. One knob to align the
       input↔select drift (U0 discrepancy #1) and, later, to retune density. */
    --control-h: 36px;
    --control-font: var(--font-md); /* 15px */
    --control-pad-x: var(--space-3); /* 12px */

    /* Shared panel-header height — keeps the first divider aligned across the
       API-tester's three columns (search / request name bar / response header). */
    --at-header-h: 53px;

    /* U1: icon size scale. 513 hardcoded icon sizes across the tree (~10 values,
       dominant 14px) and no token before. These cover the real range; migrate
       `.icon` width/height onto them wave by wave. --icon-sm == current default. */
    --icon-xs: 12px;
    --icon-sm: 14px;
    --icon-md: 16px;
    --icon-lg: 20px;

    /* Button heights (canonical sizes — use .btn .btn-xs/.btn-sm/.btn-md/.btn-lg).
       Align with height tokens: xs=26px, sm=32px, md=36px, lg=44px. */
    --btn-h-xs: 26px;
    --btn-h-sm: 32px;
    --btn-h-md: 36px;
    --btn-h-lg: 44px;
    --btn-pad-x-xs: var(--space-2);
    --btn-pad-x-sm: var(--space-3);
    --btn-pad-x-md: var(--space-4);
    --btn-pad-x-lg: var(--space-5);

    /* Protocol colors */
    --protocol-http: #4A90E2;
    --protocol-grpc: #00BCD4;
    --protocol-mcp: #9C27B0;
    --protocol-soap: #FF9800;
    --protocol-graphql: #E10098;
    --protocol-sse: #43A047;
    --protocol-socket: #795548;
    --protocol-kafka: #212121;
    --protocol-rabbitmq: #FF6F00;
    --protocol-smtp: #1565C0;
    --protocol-s3: #FF9900;

    /* Disabled state — one opacity for every disabled control, so the muted
       look of a disabled button/input/tab tunes in one place. */
    --disabled-opacity: 0.5;

    /* Icon size scale — inline heroicon/svg sizing. */
    --icon-xs: 12px;
    --icon-sm: 14px;
    --icon-md: 16px;
    --icon-lg: 18px;

    /* Line-height scale — body vs heading vs dense rows tune from here. */
    --leading-tight: 1.3;
    --leading-snug: 1.4;
    --leading-normal: 1.5;
    --leading-relaxed: 1.6;

    /* Letter-spacing scale — chiefly for uppercase eyebrows/labels/badges. */
    --tracking-tight: 0.02em;
    --tracking-normal: 0.03em;
    --tracking-wide: 0.04em;
    --tracking-wider: 0.05em;

    /* Transition */
    --transition-fast: 0.15s ease;
    --transition-base: 0.2s ease;
    --transition-slow: 0.3s ease;

    /* Aliases (used by desktop/settings/stores templates) */
    --accent-primary: var(--accent-color);
    --accent-primary-subtle: rgba(45, 140, 240, 0.08);
    --surface-primary: var(--bg-primary);
    --border-primary: var(--border-color);
    --text-tertiary: var(--text-muted);
    /* Compat aliases for non-canonical token names that several pages
       referenced without a fallback (var(--X) with --X undefined → the
       property silently dropped / lost theme-awareness). Mapped to the real
       theme-aware tokens so they resolve correctly in every theme. Prefer the
       canonical name in new code. (Standalone templates with their own :root —
       pdf-report.html, chaos.html — are fixed locally; see BACKLOG.) */
    --text-color: var(--text-primary);
    --bg-hover: var(--bg-secondary);
    --surface-secondary: var(--bg-secondary);
    --surface-tertiary: var(--bg-tertiary);
    --code-bg: var(--bg-secondary);
    --accent-red: var(--danger-color);
    --border-radius-md: var(--radius-md);
}

/* ────────────────────────────────────────────────
   Light Theme
   ──────────────────────────────────────────────── */

.light {
    --bg-primary: #ffffff;
    --bg-secondary: #f8fafc;
    --bg-tertiary: #e3eaf4;
    --text-primary: #0a1628;
    --text-secondary: #2a3f5c;
    --text-muted: #586f8e; /* a11y: was #5d7899 — 4.35:1 on --bg-secondary (panels) failed AA; this clears 4.5:1 on both white and the off-white panel bg */
    --border-color: #c8d6e8;
    --accent-color: #1a73d4;
    --accent-text: #1565c0; /* a11y: darker accent for TEXT, AA on white + accent tints (see :root note) */
    --accent-hover: #155fb0;
    --accent-light: #e6f0fd;
    --accent-contrast: #ffffff;
    --accent-purple: #9333ea;
    /* Selection (light) — see :root for rationale. */
    --selected-bg: rgba(45, 140, 240, 0.16);
    --selected-bg-2: rgba(45, 140, 240, 0.11);
    --selected-bg-3: rgba(45, 140, 240, 0.07);
    --selected-border: var(--accent-color);
    --selected-text: var(--text-primary);
    --success-color: #10b981;
    --danger-color: #ef4444;
    --warning-color: #f59e0b;
    --info-color: #06b6d4;
    --warning-bg: #fef3c7;
    --warning-fg: #92400e;
    --shadow-sm: none;
    --shadow: none;
    --shadow-hover: none;
    --shadow-lg: none;
    --hover-overlay: rgba(0, 0, 0, 0.04);
    --hover-overlay-strong: rgba(0, 0, 0, 0.07);
    --protocol-kafka: #212121;
    --protocol-smtp: #1565C0;
    --accent-primary: var(--accent-color);
    --accent-primary-subtle: rgba(45, 140, 240, 0.08);
    --surface-primary: var(--bg-primary);
    --border-primary: var(--border-color);
    --text-tertiary: var(--text-muted);
}

/* ────────────────────────────────────────────────
   Dark Theme
   ──────────────────────────────────────────────── */

.dark {
    --bg-primary: #080d18;
    --bg-secondary: #0e1524;
    --bg-tertiary: #151e30;
    --text-primary: #d8e4f4;
    --text-secondary: #7e9abb;
    /* #4d6a8a was ~3.2:1 on the dark base — below WCAG AA (4.5:1), the root of
       "muted text is hard to read in dark theme" app-wide. #6b86a6 lifts it to
       ~5:1 while staying clearly de-emphasised vs --text-secondary. Dark-only;
       no layout impact. */
    --text-muted: #7790b0;
    --border-color: #1a2740;
    /* Auto-hide scrollbar thumb (dark). */
    --scrollbar-thumb: rgba(107, 134, 166, 0.5);
    --scrollbar-thumb-hover: rgba(107, 134, 166, 0.82);
    --accent-color: #64b5ff;
    --accent-text: var(--accent-color); /* dark: the light-blue accent is already AA on the dark canvas — no darkening */
    --accent-hover: #2d8cf0;
    --accent-light: rgba(45, 140, 240, 0.12);
    /* Dark accent (#64b5ff) is a LIGHT blue — white text on it is only 2.2:1.
       Pair accent fills with near-black text instead (~8.5:1 on #64b5ff,
       ~5.5:1 on the #2d8cf0 hover). Owner-approved 2026-06-17. */
    --accent-contrast: #0d1424;
    --accent-purple: #c084fc;
    /* Selection (dark) — brighter accent wash so the wash is visible on the
       dark canvas while text/badges stay readable. Depth darker→lighter. */
    --selected-bg: rgba(100, 181, 255, 0.22);
    --selected-bg-2: rgba(100, 181, 255, 0.15);
    --selected-bg-3: rgba(100, 181, 255, 0.09);
    --selected-border: var(--accent-color);
    --selected-text: var(--text-primary);
    --success-color: #34d399;
    --danger-color: #f87171;
    /* Dark status TEXT = the bright --*-color values (all ~10:1 on the dark
       base → AA), so routing text from --*-color to --*-text is a no-op on
       dark; only light theme darkens (where the raw colours failed AA). */
    --danger-text: #f87171;
    --warning-color: #fbbf24;
    --info-color: #22d3ee;
    /* Severity — lighter on the dark canvas for legibility; tints a touch stronger. */
    --severity-critical: #f87171;
    --severity-high: #fb923c;
    --severity-medium: #fbbf24;
    --severity-low: #22d3ee;
    --severity-info: #94a3b8;
    --severity-critical-bg: rgba(248, 113, 113, 0.16);
    --severity-high-bg: rgba(251, 146, 60, 0.16);
    --severity-medium-bg: rgba(251, 191, 36, 0.16);
    --severity-low-bg: rgba(34, 211, 238, 0.16);
    --severity-info-bg: rgba(148, 163, 184, 0.16);
    --success-text: #34d399;
    --warning-text: #fbbf24;
    --info-text: #22d3ee;
    --warning-bg: #422006;
    --warning-fg: #fde68a;
    --shadow-sm: none;
    --shadow: none;
    --shadow-hover: none;
    --shadow-lg: none;
    /* Dark theme: shadows must be deeper (cast against a near-black bg) and the
       focus ring uses the lighter dark-accent. */
    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.40), 0 1px 3px rgba(0, 0, 0, 0.30);
    --shadow-2: 0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow-3: 0 6px 18px rgba(0, 0, 0, 0.50);
    --shadow-4: 0 12px 32px rgba(0, 0, 0, 0.55);
    --shadow-5: 0 24px 60px rgba(0, 0, 0, 0.65);
    --focus-ring: 0 0 0 3px rgba(100, 181, 255, 0.30);
    --focus-ring-danger: 0 0 0 3px rgba(248, 113, 113, 0.30);
    --hover-overlay: rgba(255, 255, 255, 0.04);
    --hover-overlay-strong: rgba(255, 255, 255, 0.07);
    --protocol-kafka: #424242;
    /* Keep the deeper SMTP blue in dark too: the lighter #1E88E5 dropped the
       white badge text to 3.7:1 (the badge keeps white text). #1565C0 = 5.8:1. */
    --protocol-smtp: #1565C0;
    --accent-primary: var(--accent-color);
    --accent-primary-subtle: rgba(100, 181, 255, 0.12);
    --surface-primary: var(--bg-primary);
    --border-primary: var(--border-color);
    --text-tertiary: var(--text-muted);
}
