/* === Brand tokens — Abyssal palette =======================================
   Token names preserved for back-compat (every .vt-* rule still resolves).
   --copper* tokens now carry teal #00BFFF; --navy* surfaces shift to the
   abyssal three-tier scale (#0A0F24 → #151B33 → #212B45). Headings adopt
   Plus Jakarta Sans (per vornin_brand_system.md); body stays Inter.
   ===========================================================================

   ## !important policy

   This stylesheet overrides MudBlazor 8.x component internals (.mud-*).
   The 2026-05-02 purge dropped !important from ~110 → 11 by raising
   selector specificity via a [data-mud-theme] root prefix (Mud writes that
   attribute on its theme provider). Specificity 0,2+,X beats Mud's 0,1,X
   class-only rules without needing the cascade override.

   When adding new rules:

   1. Pure .vt-* rules: NEVER use !important.
   2. Mud-internal overrides: prefix with [data-mud-theme] first. Only fall
      back to !important when Mud writes the property INLINE (style="..."),
      not via its stylesheet.
   3. The 11 surviving !important declarations are documented inline. Each
      fights an inline style or a hardcoded transition that no specificity
      bump can beat:
        - .mud-icon-root font-size overrides (Mud sets icon size inline)
        - prefers-reduced-motion suppression (Mud's transitions are baked)
        - .vt-vulns-grid sticky thead background + backdrop-filter
        - .mud-main-content mobile padding (Mud uses inline padding)
   4. If a rule fights another !important elsewhere in this file, refactor
      the loser instead of adding a third !important — search before adding.

   Last surveyed 2026-05-02. Total !important count is 11. A future Mud
   upgrade should retest each surviving declaration.
   =========================================================================== */
:root {
    /* Surfaces — three tiers from deepest to shallowest (abyssal) */
    --navy: #151B33;            /* mid surface (panels, dialogs)  — was #111827 */
    --navy-dark: #0A0F24;       /* base canvas (hero, page bg)    — was #0b0f1a */
    --navy-deep: #070b1c;       /* deepest (drawer, modals)        — was #070a13 */
    --card: #212B45;            /* lifted card surface (KPI tiles, table-head) */

    /* Accent — teal supersedes copper. Token names retained for back-compat.
       Aligned with vornin_brand_system.md §1: teal-hover lighter teal #33CCFF,
       teal-dim 7% opacity. ice #4D94FF reserved for gradient endpoints only. */
    --copper: #00BFFF;
    --copper-hover: #33CCFF;
    --copper-dim: rgba(0,191,255,0.07);
    --teal: #00BFFF;
    --teal-hover: #33CCFF;
    --teal-dim: rgba(0,191,255,0.07);
    --ice: #4D94FF;

    /* Text + muted scale (matches vornin_brand_system.md §1 ink scale) */
    --off-white: #ffffff;
    --steel: #B0B8C4;                    /* primary muted (mockup --ink-2) */
    --muted: rgba(176,184,196,0.75);     /* tertiary muted (mockup --ink-3) */
    --muted-2: rgba(255,255,255,0.75);

    /* Light-mode slate scale */
    --slate-50: #F4F6F9;
    --slate-100: #E8ECF1;
    --slate-200: #D5DBE5;
    --slate-600: #475569;
    --slate-700: #334155;
    --slate-900: #0F172A;

    /* Borders — hairline teal-tinted on dark */
    --border-dark: rgba(46,58,89,0.70);
    --border-dark-2: rgba(46,58,89,1);
    --border-light: rgba(15,23,42,0.08);

    /* CTA chrome — primary fill is teal per vornin_brand_system.md §3 */
    --btn-bg: #00BFFF;        /* teal — primary fill */
    --btn-hover: #33CCFF;     /* lighter teal — hover */
    --btn-ink: #0A0F24;       /* abyss — primary text */

    --radius: 8px;
    --radius-lg: 12px;
    --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-display: 'Plus Jakarta Sans', 'Inter', sans-serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', monospace;

    /* Surface elevation system — three tiers, used by Panel/KpiTile/inset components. */
    --surface-hero: var(--navy-dark);
    --surface-panel: var(--mud-palette-surface);
    --surface-inset: rgba(15,23,42,0.03);

    /* Animation tokens */
    --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
    --ease-out: cubic-bezier(0.0, 0, 0.2, 1);
    --dur-quick: 120ms;
    --dur-base: 200ms;
    --dur-slow: 320ms;

    /* Shadow scale — black-tinted, three meaningful levels (deeper for v3 dark canvas) */
    --shadow-1: 0 1px 2px rgba(0,0,0,0.20), 0 1px 1px rgba(0,0,0,0.10);
    --shadow-2: 0 4px 16px rgba(0,0,0,0.30), 0 2px 4px rgba(0,0,0,0.15);
    --shadow-3: 0 24px 48px rgba(0,0,0,0.50), 0 8px 16px rgba(0,0,0,0.25);

    /* Severity semantic tokens — canonical (panels, badges, attr-states, tag chips).
       Sourced from vornin_brand_system.md §2. RGB values preserved exactly.
       Single source of truth: edit here, .vt-severity / .vt-attr-state / .vt-tag /
       .vt-kpi-value / .vt-vulns-clean all pick up the change. */
    --sev-critical: #B85A66;
    --sev-critical-bg: rgba(184,90,102,0.16);
    --sev-critical-border: rgba(184,90,102,0.36);
    --sev-high: #DB7884;
    --sev-high-bg: rgba(219,120,132,0.12);
    --sev-high-border: rgba(219,120,132,0.30);
    --sev-medium: #C98B3F;
    --sev-medium-bg: rgba(201,139,63,0.10);
    --sev-medium-border: rgba(201,139,63,0.28);
    --sev-low: #4CAD7E;
    --sev-low-bg: rgba(76,173,126,0.10);
    --sev-low-border: rgba(76,173,126,0.28);
    --sev-none: rgba(255,255,255,0.55);
    --sev-none-bg: rgba(192,200,212,0.06);
    --sev-none-border: rgba(192,200,212,0.18);

    /* Severity SOFT variants — used by .vt-vuln.* row pills inside dense tables.
       Lower alpha keeps pills from competing with row text. Variance is intentional;
       do not unify with canonical tokens above. */
    --sev-high-bg-soft: rgba(219,120,132,0.05);
    --sev-high-border-soft: rgba(219,120,132,0.20);
    --sev-medium-bg-soft: rgba(201,139,63,0.07);
    --sev-medium-border-soft: rgba(201,139,63,0.22);
    --sev-none-bg-soft: rgba(192,200,212,0.04);
    --sev-none-border-soft: rgba(192,200,212,0.15);

    /* Age-warning amber — 7-30 day vuln age cell on VulnTable. Distinct hue from
       --sev-medium so the "aging, but not breaching" state reads at a glance. */
    --age-warning: #C2A13A;
    --age-warning-bg: rgba(194,161,58,0.10);
    --age-warning-border: rgba(194,161,58,0.30);

    /* .vt-tag.ransom — distinct from canonical critical (lighter bg/border).
       Dedicated tokens preserve the deliberate drift. */
    --tag-ransom-bg: rgba(184,90,102,0.12);
    --tag-ransom-border: rgba(184,90,102,0.28);

    /* Semantic split of the formerly-overloaded rgba(192,200,212,0.06).
       Same value today; decoupled identities so future drift is intentional. */
    --hairline: rgba(192,200,212,0.06);
    --muted-fill: rgba(192,200,212,0.06);

    /* Sidebar gradient (consumed by MainLayout.razor.css). Not part of --navy*
       scale — #060F20 / #091529 sit slightly below --navy-deep / --navy. Kept
       distinct so the existing render is preserved pixel-exact. */
    --sidebar-grad-start: #060F20;
    --sidebar-grad-end: #091529;
}

/* Dark-mode surface tints — recessed surfaces use a deeper canvas for hierarchy. */
.mud-theme-dark, [data-mud-theme="dark"] {
    --surface-inset: rgba(0,0,0,0.35);
}

/* === Base === */
html, body {
    font-family: var(--font);
    margin: 0;
    padding: 0;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

code, pre, kbd, samp, .mud-typography-caption code {
    font-family: var(--font-mono);
}

/* === Scrollbar — steel on dark, slate on light === */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: rgba(176,184,196,0.18);
    border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
    background: rgba(0,191,255,0.45);
}

/* === MudBlazor Overrides ===
   All selectors below prefix with [data-mud-theme] to gain a 0,2,X specificity
   that beats Mud 8's class-only rules (typically 0,1,X) without !important. */

/* AppBar — translucent navy with blur to match public site nav */
[data-mud-theme] .mud-appbar {
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border-dark);
}

/* Nav links — rounded, subtle hover, copper for active */
[data-mud-theme] .mud-nav-link {
    border-radius: var(--radius);
    margin: 1px 8px;
    transition: background 0.15s ease, color 0.15s ease;
    letter-spacing: -0.005em;
}
[data-mud-theme] .mud-nav-link.active {
    background: var(--copper-dim);
    color: var(--copper);
}
[data-mud-theme] .mud-nav-link.active .mud-nav-link-icon {
    color: var(--copper);
}

/* Data grid refinements */
[data-mud-theme] .mud-table-cell {
    font-size: 0.85rem;
}
[data-mud-theme] .mud-table-head .mud-table-cell {
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.7;
}

/* Paper / card hover */
.mud-paper {
    transition: box-shadow 0.2s ease, border-color 0.2s ease;
}
[data-mud-theme] .mud-paper.mud-paper-outlined:hover {
    border-color: rgba(0,191,255,0.25);
}

/* Chips */
[data-mud-theme] .mud-chip {
    font-weight: 600;
    letter-spacing: 0.02em;
}

/* Buttons — contrast text handled via MudTheme PrimaryContrastText etc. */
[data-mud-theme] .mud-button-root {
    transition: all 0.15s ease-out;
    letter-spacing: -0.005em;
}
.mud-button-filled.mud-button-filled-primary:hover {
    transform: translateY(-1px);
}

/* Inputs — copper focus ring */
[data-mud-theme] .mud-input.mud-input-underline:after,
[data-mud-theme] .mud-input-outlined-border {
    transition: border-color 0.15s ease-out;
}
[data-mud-theme] .mud-input-label.mud-input-label-inputcontrol.mud-focused,
[data-mud-theme] .mud-input-label-animated.mud-focused {
    color: var(--copper);
}

/* Dialog */
[data-mud-theme] .mud-dialog {
    border-radius: var(--radius-lg);
}

/* Tab indicators — copper */
[data-mud-theme] .mud-tab-slider {
    background: var(--copper);
}
[data-mud-theme] .mud-tab.mud-tab-active {
    color: var(--copper);
}

/* Switches + checkboxes pick up the copper primary automatically via MudTheme */

/* Uppercase nav-brand vibe for AppBar text (opt-in via class) */
.nav-brand-caps {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
}

/* ==========================================================================
   Vornin Operations Console — reusable page chrome
   Hero strip, KPI tiles, sector rail, navy panel. Classes all vt-* prefixed.
   Apply anywhere — any .razor page can drop these in.
   ========================================================================== */

.vt-hero {
    position: relative; overflow: hidden;
    padding: 32px 36px;
    background: var(--navy-dark);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    margin-bottom: 24px;
}
/* Abyssal: triangle-grid texture masked to top, with a teal radial glow */
.vt-hero::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: url('triangle-grid.jpg') center top / cover no-repeat;
    opacity: 0.22;
    -webkit-mask-image: radial-gradient(ellipse 80% 100% at 50% 20%, black 0%, black 30%, transparent 72%);
            mask-image: radial-gradient(ellipse 80% 100% at 50% 20%, black 0%, black 30%, transparent 72%);
}
.vt-hero::after {
    content: ''; position: absolute; pointer-events: none;
    top: -40px; left: 50%; transform: translateX(-50%);
    width: 600px; height: 260px;
    background: radial-gradient(ellipse, rgba(0,191,255,0.10) 0%, rgba(77,148,255,0.05) 50%, transparent 75%);
    filter: blur(48px);
}
.vt-hero-title-row {
    position: relative; z-index: 1;
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 24px; flex-wrap: wrap;
}
.vt-hero-title-row.has-kpis { margin-bottom: 28px; }
.vt-eyebrow {
    font-family: var(--font-mono);
    font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase;
    color: var(--copper);
    display: inline-flex; align-items: center; gap: 8px;
    margin-bottom: 12px;
}
/* Abyssal: pulsing teal dot marker */
.vt-eyebrow::before {
    content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--teal);
    animation: vt-eyebrow-pulse 2s infinite;
}
@keyframes vt-eyebrow-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.3; }
}
.vt-hero h1,
.vt-hero .vt-hero-title {
    margin: 0; font-family: var(--font-display);
    font-size: 2rem; font-weight: 700;
    letter-spacing: -0.025em; color: var(--off-white); line-height: 1.08;
}
.vt-hero h1 em,
.vt-hero .vt-hero-title em { font-style: normal; color: var(--teal); }
.vt-hero-sub {
    margin: 8px 0 0; max-width: 580px;
    color: var(--steel); font-size: 0.95rem; line-height: 1.55;
}
.vt-hero-actions { display: flex; gap: 12px; flex-shrink: 0; flex-wrap: wrap; }

/* Mobile hero — drop padding + scale typography */
@media (max-width: 600px) {
    .vt-hero {
        padding: 20px 16px;
        margin-bottom: 16px;
    }
    .vt-hero h1,
    .vt-hero .vt-hero-title { font-size: 1.4rem; }
    .vt-hero-sub { font-size: 0.85rem; }
    .vt-eyebrow {
        font-size: 0.62rem;
        letter-spacing: 0.18em;
        margin-bottom: 8px;
    }
    .vt-eyebrow::before { width: 18px; }
    .vt-hero-title-row { gap: 12px; }
    .vt-hero-title-row.has-kpis { margin-bottom: 16px; }
}

/* Filter bar — sticky on desktop, static on mobile so it doesn't eat the viewport */
.vt-filter-bar {
    position: sticky;
    top: 64px;
    z-index: 5;
    background: var(--mud-palette-surface);
}
@media (max-width: 768px) {
    .vt-filter-bar { position: static; }
}

/* Preset chip row — wraps on narrow viewports without breaking the search field. */
.vt-preset-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

/* Collapsed filter panel — fixed-width grid so every select lines up
   regardless of label length. Each cell auto-sizes inputs to 100%. */
.vt-filter-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 12px 14px;
    align-items: end;
}
.vt-filter-grid > * {
    width: 100%;
    min-width: 0;
}

.vt-kpis {
    position: relative; z-index: 1;
    display: grid; grid-template-columns: repeat(4, 1fr);
    border-top: 1px solid var(--border-dark);
}
.vt-kpis.cols-3 { grid-template-columns: repeat(3, 1fr); }
.vt-kpis.cols-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 720px) {
    .vt-kpis, .vt-kpis.cols-3, .vt-kpis.cols-5 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
    .vt-kpis, .vt-kpis.cols-3, .vt-kpis.cols-5 { grid-template-columns: 1fr; }
    .vt-kpi {
        border-right: none;
        border-bottom: 1px solid var(--hairline);
        padding: 14px 16px 4px;
    }
    .vt-kpi:last-child { border-bottom: none; }
    .vt-kpi-value { font-size: 1.6rem; }
}
.vt-kpi {
    padding: 20px 24px 6px;
    border-right: 1px solid var(--hairline);
}
.vt-kpi:last-child { border-right: none; }
/* Anchor-shaped KPI (e.g. clickable SLA Breached tile that routes to /vulnerabilities). */
a.vt-kpi.vt-kpi-link {
    display: block;
    color: inherit;
    text-decoration: none;
    transition: background 0.15s ease;
}
a.vt-kpi.vt-kpi-link:hover { background: rgba(0,191,255,0.06); }
.vt-kpi-label {
    font-family: var(--font-mono);
    font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
    /* Bumped 2026-05-02 from rgba(...,0.55) to 0.72 — meets WCAG AA at small sizes on --navy-dark. */
    color: rgba(255,255,255,0.72);
}
.vt-kpi-value {
    margin-top: 8px;
    font-size: 2.1rem; font-weight: 700; line-height: 1.1;
    letter-spacing: -0.03em; color: var(--off-white);
    display: flex; align-items: baseline; gap: 10px;
}
.vt-kpi-value.accent { color: var(--copper); }
.vt-kpi-value.alert  { color: var(--sev-high); }
.vt-kpi-value.success { color: var(--sev-low); }
.vt-kpi-unit {
    font-size: 0.8rem; font-weight: 500; letter-spacing: 0;
    color: rgba(255,255,255,0.55);
}

/* Inline severity bar + breakdown rendered inside a .vt-kpi tile.
   Used on the Vulnerabilities page Open KPI to fold what was previously
   a standalone "Open by severity" Paper into the hero. */
.vt-kpi-sevbar {
    display: flex; gap: 2px;
    margin-top: 10px;
    height: 4px; width: 100%;
    border-radius: 2px; overflow: hidden;
    background: rgba(255,255,255,0.06);
}
.vt-kpi-sevbar-seg {
    height: 100%;
    cursor: pointer;
    transition: opacity 0.15s;
    border: 0;
    padding: 0;
}
.vt-kpi-sevbar-seg:hover { opacity: 0.8; }
.vt-kpi-sevcounts {
    display: flex; flex-wrap: wrap; gap: 10px;
    margin-top: 8px;
    font-family: var(--font-mono);
    font-size: 0.7rem; letter-spacing: 0.04em;
    color: rgba(255,255,255,0.65);
}
.vt-kpi-sevcounts button {
    background: transparent; border: 0; padding: 0;
    cursor: pointer;
    color: inherit; font: inherit; letter-spacing: inherit;
}
.vt-kpi-sevcounts button:hover { color: var(--off-white); }
.vt-kpi-sevcounts strong { color: var(--off-white); font-weight: 600; }

/* Panel with operations-console header (for grids, lists, etc.).
   Edge-lit chrome: cold teal hairline along the top edge + hover lift +
   cold drop-shadow on hover. Brand spec §6 — "cold light emerging from
   darkness." Eyebrow ink-2 (teal reserved for action per §1). */
.vt-panel {
    background: var(--navy-dark);
    border: 1px solid var(--border-dark);
    border-radius: 10px; /* MD scale per vornin_brand_system.md §4 */
    overflow: hidden;
    min-width: 0;
    margin-bottom: 16px;
    position: relative;
    transition: border-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                transform var(--dur-quick) var(--ease-out);
}
.vt-panel::before {
    content: "";
    position: absolute; left: 0; right: 0; top: 0; height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(0,191,255,0.55) 22%,
        rgba(0,191,255,0.55) 78%,
        transparent 100%);
    opacity: 0.55;
    pointer-events: none;
    z-index: 1;
}
.vt-panel:hover {
    border-color: rgba(0,191,255,0.40);
    box-shadow: 0 0 16px rgba(0,191,255,0.18),
                0 12px 28px -16px rgba(0,191,255,0.30);
    transform: translateY(-1px);
}
.vt-panel:hover::before { opacity: 0.85; }
.vt-panel-head {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-dark);
}
.vt-panel-head-label {
    font-family: var(--font-mono);
    font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase;
    color: var(--steel); /* ink-2; teal reserved for action */
}
.vt-panel-head-count {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--muted);
    letter-spacing: 0.04em;
    background: var(--teal-dim);
    border: 1px solid var(--border-dark);
    padding: 2px 10px;
    border-radius: 999px;
}

/* Data grid re-chrome inside .vt-panel — selector is already 0,2,2+ which
   beats Mud's table rules (0,2,1). No !important needed. */
[data-mud-theme] .vt-panel .mud-table { background: transparent; box-shadow: none; }
[data-mud-theme] .vt-panel .mud-table-head .mud-table-cell {
    background: transparent;
    color: rgba(255,255,255,0.55);
    font-family: var(--font-mono);
    font-size: 0.66rem; font-weight: 500;
    letter-spacing: 0.16em; text-transform: uppercase;
    border-bottom: 1px solid var(--border-dark);
    padding: 14px 18px;
}
[data-mud-theme] .vt-panel .mud-table-body .mud-table-row {
    background: transparent;
    border-left: 2px solid transparent;
    transition: background 0.12s ease, border-left-color 0.12s ease;
}
[data-mud-theme] .vt-panel .mud-table-body .mud-table-row:hover {
    background: rgba(0,191,255,0.04);
    border-left-color: var(--copper);
}
[data-mud-theme] .vt-panel .mud-table-body .mud-table-cell {
    background: transparent;
    color: var(--off-white);
    border-bottom: 1px solid var(--hairline);
    padding: 14px 18px;
    font-size: 0.9rem;
}
[data-mud-theme] .vt-panel .mud-table-body .mud-table-row:last-child .mud-table-cell { border-bottom: none; }
[data-mud-theme] .vt-panel .mud-table-pagination { background: transparent; border-top: 1px solid var(--hairline); }

/* Mono monospace utility for hosts, counts, timestamps */
.vt-mono {
    font-family: var(--font-mono);
    letter-spacing: -0.005em;
}

/* Modal eyebrow — used on MudDialog TitleContent across the app */
.vt-modal-eyebrow {
    font-family: var(--font-mono);
    font-size: 0.62rem; letter-spacing: 0.22em; text-transform: uppercase;
    color: var(--copper); margin-bottom: 4px;
}
.vt-modal-title { font-size: 1.1rem; font-weight: 600; color: var(--off-white); letter-spacing: -0.01em; }

/* Empty state */
.vt-empty {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    text-align: center;
    padding: 72px 24px;
    border: 1px dashed rgba(0,191,255,0.35);
    border-radius: var(--radius-lg);
    background: radial-gradient(ellipse 70% 60% at 50% 20%, rgba(0,191,255,0.06), transparent 70%);
    margin: 24px;
}
.vt-empty-icon {
    width: 64px; height: 64px; border-radius: 50%;
    background: rgba(0,191,255,0.10);
    display: flex; align-items: center; justify-content: center;
    color: var(--copper);
    margin-bottom: 20px;
}
.vt-empty h3 {
    margin: 0 0 8px; color: var(--off-white);
    font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em;
}
.vt-empty p {
    margin: 0 0 24px; max-width: 420px;
    color: rgba(255,255,255,0.55); font-size: 0.92rem; line-height: 1.5;
}
.vt-empty-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

/* Severity pills for vuln counts */
.vt-vulns { display: flex; gap: 4px; flex-wrap: wrap; }
.vt-vuln {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 8px; border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em;
    border: 1px solid transparent;
}
.vt-vuln.c { background: var(--sev-high-bg);      color: var(--sev-high);   border-color: var(--sev-high-border); }
.vt-vuln.h { background: var(--sev-high-bg-soft); color: var(--sev-high);   border-color: var(--sev-high-border-soft); }
.vt-vuln.m { background: var(--sev-medium-bg-soft); color: var(--sev-medium); border-color: var(--sev-medium-border-soft); }
.vt-vuln.l { background: var(--sev-none-bg-soft); color: var(--sev-none);  border-color: var(--sev-none-border-soft); }
.vt-vulns-clean {
    font-family: var(--font-mono);
    font-size: 0.72rem; color: var(--sev-low); letter-spacing: 0.1em;
}

/* === Error UI === */
#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,...) no-repeat 1rem/1.8rem;
    padding: 1rem 1rem 1rem 3.7rem;
    color: #b32121;
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* =========================================================================
   Command Palette (Cmd+K)
   Centered floating panel; dark backdrop; keyboard-driven.
   ========================================================================= */

.cmdk-backdrop {
    position: fixed; inset: 0; z-index: 1500;
    background: rgba(6, 11, 24, 0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex; align-items: flex-start; justify-content: center;
    padding-top: 14vh;
    animation: cmdk-fade-in 120ms ease-out;
}

@keyframes cmdk-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.cmdk-panel {
    width: 100%; max-width: 640px;
    margin: 0 16px;
    background: #0F172A;
    border: 1px solid rgba(192, 200, 212, 0.12);
    border-radius: 12px;
    box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6),
                0 0 0 1px rgba(0, 191, 255,0.06);
    overflow: hidden;
    animation: cmdk-slide-in 140ms ease-out;
}

@keyframes cmdk-slide-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.cmdk-input-row {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid rgba(192, 200, 212, 0.08);
}
.cmdk-input-icon { color: var(--copper, #00BFFF); flex-shrink: 0; }
.cmdk-input {
    flex: 1; min-width: 0;
    background: transparent; border: none; outline: none;
    color: #FFFFFF;
    font: 500 0.98rem 'Inter', sans-serif;
    letter-spacing: -0.005em;
}
.cmdk-input::placeholder { color: rgba(192, 200, 212, 0.35); }
.cmdk-kbd, .cmdk-footer kbd {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.66rem;
    color: rgba(192, 200, 212, 0.55);
    background: rgba(192, 200, 212, 0.06);
    border: 1px solid rgba(192, 200, 212, 0.12);
    border-radius: 4px;
    padding: 2px 6px;
    letter-spacing: 0.04em;
}

.cmdk-results {
    max-height: 56vh;
    overflow-y: auto;
    padding: 6px;
}
.cmdk-results::-webkit-scrollbar { width: 6px; }
.cmdk-results::-webkit-scrollbar-thumb { background: rgba(192, 200, 212, 0.18); border-radius: 3px; }

.cmdk-empty {
    padding: 32px 14px;
    text-align: center;
    color: rgba(192, 200, 212, 0.45);
    font-size: 0.88rem;
}

.cmdk-group-label {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.62rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(192, 200, 212, 0.45);
    padding: 12px 12px 4px;
}
.cmdk-group-label:first-child { padding-top: 6px; }

.cmdk-item {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    padding: 9px 12px;
    background: transparent; border: none;
    border-radius: 6px;
    color: #B0B8C4;
    font: 500 0.92rem 'Inter', sans-serif;
    letter-spacing: -0.005em;
    cursor: pointer;
    text-align: left;
    transition: background 80ms ease;
}
.cmdk-item-active,
.cmdk-item:hover {
    background: rgba(0, 191, 255,0.10);
    color: #FFFFFF;
}
.cmdk-item-icon { color: rgba(192, 200, 212, 0.55); flex-shrink: 0; font-size: 1.05rem !important; }
.cmdk-item-active .cmdk-item-icon { color: var(--copper, #00BFFF); }
.cmdk-item-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmdk-item-sub {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.72rem;
    color: rgba(192, 200, 212, 0.45);
    letter-spacing: 0.005em;
    flex-shrink: 0;
    max-width: 260px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.cmdk-footer {
    display: flex; gap: 14px;
    padding: 8px 14px;
    border-top: 1px solid rgba(192, 200, 212, 0.08);
    font-size: 0.72rem;
    color: rgba(192, 200, 212, 0.45);
}
.cmdk-footer kbd { margin-right: 4px; }

/* =========================================================================
   Micro-interactions — focus ring, row-hover, button-press, first-paint stagger.
   These run app-wide; opt-out via .no-anim on a parent if needed.
   ========================================================================= */

/* Focus ring: 2px copper outline + 4px halo. Works across inputs, buttons, table rows.
   [data-mud-theme] prefix raises specificity above Mud's own focus styles. */
[data-mud-theme] .mud-input.mud-focused .mud-input-outlined-border {
    border-color: var(--copper);
    border-width: 2px;
    box-shadow: 0 0 0 4px var(--copper-dim);
}
[data-mud-theme] .mud-button-root:focus-visible,
[data-mud-theme] .mud-icon-button:focus-visible,
[data-mud-theme] .mud-nav-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--copper), 0 0 0 6px var(--copper-dim);
}

/* Button press — momentary 1px scale-down, copper-aware. */
[data-mud-theme] .mud-button-root:active:not(:disabled) {
    transform: translateY(0) scale(0.985);
    transition-duration: 50ms;
}

/* Generic table row hover — mirrors the .vt-panel pattern outside of vt panels. */
.mud-table-body .mud-table-row {
    border-left: 2px solid transparent;
    transition: background var(--dur-quick) var(--ease-out),
                border-left-color var(--dur-quick) var(--ease-out);
}
.mud-table-body .mud-table-row:hover {
    border-left-color: var(--copper);
}

/* Entry stagger — KPI tiles, table rows, cards fade-up on first paint.
   Apply .vt-stagger on the parent; children animate with 30ms cumulative delay. */
@keyframes vt-fade-up {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
.vt-stagger > * {
    animation: vt-fade-up var(--dur-base) var(--ease-emphasized) both;
}
.vt-stagger > *:nth-child(1) { animation-delay: 0ms; }
.vt-stagger > *:nth-child(2) { animation-delay: 30ms; }
.vt-stagger > *:nth-child(3) { animation-delay: 60ms; }
.vt-stagger > *:nth-child(4) { animation-delay: 90ms; }
.vt-stagger > *:nth-child(5) { animation-delay: 120ms; }
.vt-stagger > *:nth-child(6) { animation-delay: 150ms; }
.vt-stagger > *:nth-child(7) { animation-delay: 180ms; }
.vt-stagger > *:nth-child(8) { animation-delay: 210ms; }
.vt-stagger > *:nth-child(9) { animation-delay: 240ms; }
.vt-stagger > *:nth-child(10) { animation-delay: 270ms; }
.vt-stagger > *:nth-child(n+11) { animation-delay: 300ms; }

@media (prefers-reduced-motion: reduce) {
    .vt-stagger > *,
    .mud-button-root:active:not(:disabled),
    .mud-table-body .mud-table-row {
        animation: none !important;
        transition: none !important;
        transform: none !important;
    }
}

/* =========================================================================
   <Panel> component — used as a Razor wrapper around .vt-panel chrome.
   Adds slot-based header (label + count + actions) and an optional non-navy
   variant for light-mode pages.
   ========================================================================= */

.vt-panel-head-actions {
    margin-left: auto;
    display: flex; align-items: center; gap: 8px;
}
.vt-panel-head-count + .vt-panel-head-actions { margin-left: 12px; }
.vt-panel-body { padding: 0; }
.vt-panel-body.padded { padding: 16px 20px; }

/* Panel surface variant — adapts to light/dark via Mud surface tokens. */
.vt-panel.surface {
    background: var(--surface-panel);
    border-color: var(--mud-palette-lines-default);
}
.vt-panel.surface .vt-panel-head {
    border-bottom-color: var(--mud-palette-lines-default);
}
.vt-panel.surface .vt-panel-head-label { color: var(--copper); }

/* =========================================================================
   Density tokens — replace inline styles for opacity/letter-spacing/SLA colors.
   ========================================================================= */

.vt-meta-label {
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    opacity: 0.6;
    text-transform: uppercase;
}
.vt-meta-value { font-weight: 600; }
.vt-meta-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1rem 1.5rem;
}
.vt-muted { opacity: 0.6; }
.vt-muted-strong { opacity: 0.75; }
.vt-sla-breached { color: var(--vt-alert, #DB7884); font-weight: 700; }
.vt-sla-warning { color: #C98B3F; font-weight: 600; }
.vt-sla-ok { color: var(--vt-success, #4CAD7E); font-weight: 600; }
.vt-mono-block {
    background: var(--mud-palette-background);
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: 0.85rem;
    white-space: pre-wrap;
    line-height: 1.6;
    border-radius: 4px;
}
.vt-help-icon {
    font-size: 0.95rem;
    opacity: 0.55;
    cursor: help;
    vertical-align: middle;
    margin-left: 6px;
}
.vt-vornin-insights {
    background: var(--mud-palette-background);
    border-left: 3px solid var(--mud-palette-secondary);
}
.vt-vornin-insights-pending {
    background: var(--mud-palette-background);
    border-left: 3px solid var(--mud-palette-lines-default);
}
.vt-prose {
    white-space: pre-wrap;
    line-height: 1.7;
    opacity: 0.8;
}
.vt-section-title { font-weight: 700; }
.vt-tab-bordered { border-top: 1px solid var(--mud-palette-lines-default); }
.vt-evidence-card {
    background: var(--mud-palette-background);
    border-radius: 4px;
}
.vt-evidence-pre {
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: 0.82rem;
    white-space: pre-wrap;
    line-height: 1.5;
    margin: 0;
}
.vt-meta-footer { opacity: 0.5; }
.vt-mono { font-family: monospace; }
.vt-changelog-content { white-space: pre-line; }
.vt-setup-complete-copy { max-width: 480px; }
.vt-wish-vote-col { min-width: 60px; }
.vt-wish-vote-count { line-height: 1; }
.vt-wish-description { white-space: pre-wrap; }
.vt-error-cell { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-chart-donut-wrap { min-height: 300px; }
.vt-num-cell { text-align: right; }
.vt-meta-secondary { opacity: 0.6; font-size: 0.85em; }
.vt-as-host { font-size: 13px; }
.vt-as-target { font-size: 11px; opacity: 0.6; margin-top: 2px; }
.vt-risk-score { font-weight: 600; font-size: 13px; }
.vt-risk-score.critical { color: var(--sev-critical); }
.vt-risk-score.high { color: var(--sev-high); }
.vt-risk-score.medium { color: var(--sev-medium); }
.vt-risk-score.low { color: var(--sev-low); }
.vt-risk-score-empty { opacity: 0.4; font-size: 12px; }
.vt-report-iframe { width: 100%; height: 80vh; border: none; }
.vt-scan-running-card { cursor: pointer; }
.vt-agent-dot-inline { color: var(--steel); }
.vt-agent-dot-inline.online { color: var(--sev-low); }
.vt-agent-dot-inline.busy { color: var(--sev-medium); }
.vt-repo-branch-select { max-width: 200px; }
.vt-repo-branch-select-narrow { max-width: 180px; }
.vt-repo-branch-chip { cursor: pointer; }
.vt-repo-branch-spinner { width: 14px; height: 14px; margin-left: 4px; }
.vt-repo-import-row { margin-bottom: 8px; }
.vt-scan-name-edit { max-width: 400px; }
.vt-prewrap { white-space: pre-wrap; }
.vt-break-all { word-break: break-all; }
.vt-row-clickable { cursor: pointer; }
.vt-cvss-score-num { font-weight: 700; }
.vt-tooltip-content { max-width: 280px; }
.vt-tooltip-list { padding-left: 18px; margin: 6px 0 0; }
.vt-evidence-pre { font-family: var(--font-mono); font-size: 0.8rem; white-space: pre-wrap; margin: 0; }
.vt-evidence-pre-body { max-height: 400px; overflow-y: auto; }
.vt-evidence-pre-json { overflow-x: auto; }
.vt-badge-preview { padding: 16px; border-radius: var(--radius); }
.vt-badge-preview-light { background: #FFFFFF; border: 1px solid var(--slate-100); }
.vt-badge-preview-dark { background: #1A1A2E; border: 1px solid rgba(255,255,255,0.10); }
.vt-badge-code { padding: 12px; background: var(--muted-fill); border-radius: var(--radius); overflow-x: auto; }
.vt-badge-code-text { font-size: 0.8rem; white-space: pre-wrap; word-break: break-all; }
.vt-scanner-card { border: 1px solid var(--mud-palette-lines-default); }
.vt-compliance-card { height: 100%; box-shadow: var(--shadow-2); }
.vt-qr-frame { padding: 12px; background: #FFFFFF; border-radius: var(--radius); max-width: 220px; }
.vt-totp-field { max-width: 200px; }
.vt-attr-id { font-size: 0.85rem; }
.vt-status-cell { width: 6px; height: 22px; margin-right: 1px; border-radius: 1px; }
.vt-incident-update { border-left: 2px solid var(--mud-palette-lines-default); padding-left: 8px; }
.vt-panel-accent-warning { border-left: 4px solid var(--mud-palette-warning); }
.vt-panel-accent-info { border-left: 4px solid var(--mud-palette-info); }
.vt-compliance-card-head {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}
.vt-compliance-card-title {
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
}
.vt-compliance-card-title .mud-typography-h6 {
    line-height: 1.25;
    word-break: break-word;
}
.vt-compliance-card-score {
    flex-shrink: 0;
    white-space: nowrap;
    line-height: 1;
}

/* =========================================================================
   <KpiTile> component — standalone card variant of .vt-kpi (works outside .vt-hero).
   ========================================================================= */

.vt-kpi-tile {
    padding: 18px 22px;
    background: var(--surface-panel);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--radius-lg);
    transition: border-color var(--dur-quick) var(--ease-out),
                box-shadow var(--dur-quick) var(--ease-out);
    display: flex; flex-direction: column; gap: 8px;
    min-width: 0;
}
.vt-kpi-tile:hover {
    border-color: rgba(0,191,255,0.35);
    box-shadow: var(--shadow-2);
}
.vt-kpi-tile-head {
    display: flex; align-items: center; gap: 10px;
}
.vt-kpi-tile-icon {
    color: var(--copper);
    font-size: 1rem !important;
    width: 18px; height: 18px;
}
.vt-kpi-tile-label {
    font-family: var(--font-mono);
    font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}
.vt-kpi-tile-value {
    font-size: 2rem; font-weight: 700; line-height: 1.1;
    letter-spacing: -0.03em;
    color: var(--mud-palette-text-primary);
    display: flex; align-items: baseline; gap: 8px;
}
.vt-kpi-tile-unit {
    font-size: 0.78rem; font-weight: 500; letter-spacing: 0;
    color: var(--mud-palette-text-secondary);
}
.vt-kpi-tile-delta {
    font-family: var(--font-mono);
    font-size: 0.74rem; letter-spacing: 0.04em;
    display: inline-flex; align-items: center; gap: 4px;
}
.vt-kpi-tile-delta.up    { color: #4CAD7E; }
.vt-kpi-tile-delta.down  { color: #DB7884; }
.vt-kpi-tile-delta.flat  { color: var(--mud-palette-text-secondary); }
/* Placeholder rendered when ReserveTrailSlots=true and Delta is absent. Reserves
   the same vertical footprint as a real delta line so KPI tiles stay uniform. */
.vt-kpi-tile-delta-empty { visibility: hidden; }
.vt-kpi-tile-trend { margin-top: 2px; opacity: 0.75; }

/* Accent variants for the value (mirrors .vt-kpi-value classes inside hero) */
.vt-kpi-tile-value.accent  { color: var(--copper); }
.vt-kpi-tile-value.alert   { color: #DB7884; }
.vt-kpi-tile-value.success { color: #4CAD7E; }

/* =========================================================================
   Severity bar list — replaces dense table on dashboard "Open by Severity"
   panel. Each row is a flex row: SeverityBadge + bar track + count, all
   wrapped in an anchor that filters /vulnerabilities. Bars use the brand
   semantic palette (red / orange / green) — teal stays action-only.
   ========================================================================= */
.vt-sev-list {
    display: flex; flex-direction: column;
    gap: 0;
}
.vt-sev-row {
    display: flex; align-items: center; gap: 14px;
    padding: 12px 18px;
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid rgba(46,58,89,0.30);
    transition: background var(--dur-quick) var(--ease-out);
    cursor: pointer;
}
.vt-sev-row:last-child { border-bottom: none; }
.vt-sev-row:hover { background: var(--teal-dim); }
.vt-sev-track {
    flex: 1;
    height: 6px;
    background: rgba(46,58,89,0.40);
    border-radius: 3px;
    overflow: hidden;
    min-width: 0;
}
.vt-sev-fill {
    height: 100%;
    transition: width var(--dur-base) var(--ease-out);
}
.vt-sev-fill.critical { background: #DB7884; }
.vt-sev-fill.high     { background: #DB7884; opacity: 0.78; }
.vt-sev-fill.medium   { background: #C98B3F; }
.vt-sev-fill.low      { background: #4CAD7E; }
.vt-sev-fill.info     { background: rgba(176,184,196,0.55); }
.vt-sev-count {
    font-family: var(--font-mono);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--off-white);
    min-width: 36px;
    text-align: right;
    flex-shrink: 0;
}

/* Sparkline — cold teal stroke + faint area fill. Renders 30-day trend
   inline below the KPI value. SVG viewBox is 100x24, scaled non-uniformly
   to fill the row width. */
.vt-kpi-tile-spark {
    margin-top: 4px;
    display: flex; align-items: center; gap: 8px;
}
.vt-kpi-tile-spark svg {
    flex: 1;
    height: 24px;
    width: 100%;
    display: block;
}
.vt-kpi-tile-spark-line {
    fill: none;
    stroke: var(--teal);
    stroke-width: 1.4;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}
.vt-kpi-tile-spark-fill {
    fill: rgba(0,191,255,0.12);
    stroke: none;
}
.vt-kpi-tile-spark-label {
    font-family: var(--font-mono);
    font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--muted);
    flex-shrink: 0;
}
/* Placeholder rendered when ReserveSparkSlot=true and Spark data is absent.
   Reserves the same vertical footprint as the real spark so KPI tiles stay
   uniform height across a row. */
.vt-kpi-tile-spark-empty {
    height: 24px;
}

/* =========================================================================
   <SectionHeader> — secondary header (eyebrow + title + actions) used inside
   pages between hero and content.
   ========================================================================= */

.vt-section-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin: 24px 0 12px;
}
.vt-section-head-title {
    margin: 4px 0 0; font-size: 1.15rem; font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--mud-palette-text-primary);
}
.vt-section-head-sub {
    margin: 4px 0 0; font-size: 0.85rem; color: var(--mud-palette-text-secondary);
}
.vt-section-head-actions { display: flex; gap: 8px; }

/* =========================================================================
   <TagBadge> — compact icon-only tag for KEV / EXPLOIT / RANSOM / REACHED markers.
   Tooltip carries the label; the badge itself is just iconography.
   ========================================================================= */

.vt-tag {
    display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    width: 22px; height: 22px;
    border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 0.66rem; font-weight: 700; letter-spacing: 0.04em;
    border: 1px solid transparent;
    cursor: default;
    text-transform: uppercase;
}
.vt-tag .mud-icon-root { font-size: 0.95rem !important; }
/* Text variant — shows the label inline (e.g. "KEV", "REACHED"). */
.vt-tag.with-text {
    width: auto;
    height: 20px;
    padding: 0 8px;
    letter-spacing: 0.06em;
}
.vt-tag.kev       { background: var(--sev-high-bg);   color: var(--sev-high);     border-color: var(--sev-high-border); }
.vt-tag.exploit   { background: var(--sev-medium-bg); color: var(--sev-medium);   border-color: var(--sev-medium-border); }
.vt-tag.ransom    { background: var(--tag-ransom-bg); color: var(--sev-critical); border-color: var(--tag-ransom-border); }
.vt-tag.reached   { background: rgba(0,191,255,0.10); color: var(--copper);       border-color: rgba(0,191,255,0.30); }
.vt-tag.unreached { background: var(--sev-none-bg);   color: var(--sev-none);     border-color: var(--sev-none-border); }

.vt-tags { display: inline-flex; gap: 4px; flex-wrap: nowrap; }

/* =========================================================================
   Vulnerability priority chip (table column + mobile card + drawer header).
   Inline `--prio-color` is set from C# so the same markup can adopt any of
   the four severity-token colors without a class explosion.
   ========================================================================= */
.vt-priority {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--prio-color, var(--sev-none)) 36%, transparent);
    background: color-mix(in srgb, var(--prio-color, var(--sev-none)) 14%, transparent);
    color: var(--prio-color, var(--sev-none));
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    white-space: nowrap;
}
.vt-priority-label { font-weight: 700; }
.vt-priority-score { opacity: 0.75; font-size: 0.66rem; }
.vt-priority-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--prio-color, var(--sev-none)) 36%, transparent);
    background: color-mix(in srgb, var(--prio-color, var(--sev-none)) 14%, transparent);
    color: var(--prio-color, var(--sev-none));
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
}

/* Secondary context row inside the Vulnerability cell — scanner · CVE · CVSS · EPSS · evidence. */
.vt-vuln-cell { display: flex; flex-direction: column; gap: 2px; }
.vt-vuln-sub { font-size: 0.7rem; opacity: 0.65; display: flex; flex-wrap: wrap; gap: 4px; }
.vt-vuln-sub-item { white-space: nowrap; }
.vt-vuln-sub-sep { opacity: 0.5; }

/* Reasons list inside the Recommended Action panel (detail page + quick-view). */
.vt-prio-reasons {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.vt-prio-reasons li {
    list-style: none;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--sev-none-bg);
    color: var(--sev-none);
    border: 1px solid var(--sev-none-border);
    font-size: 0.72rem;
}

/* =========================================================================
   Gauge ring grid — 4-up at md+, 2-up below 600px. Pairs with <GaugeRing>.
   ========================================================================= */
.vt-gauge-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}
@media (max-width: 599px) {
    .vt-gauge-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* =========================================================================
   Equal-height paired-row utility — MudGrid items default to align-items:
   stretch but Panel (.vt-panel) lacks height:100%, so the shorter panel
   falls short of its sibling. Apply .vt-equal-row to MudGrid wrappers to
   stretch siblings + flex their panels and bodies to equal height.
   ========================================================================= */
.vt-equal-row { align-items: stretch; }
.vt-equal-row > .mud-grid-item { display: flex; }
.vt-equal-row > .mud-grid-item > .vt-panel {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}
.vt-equal-row > .mud-grid-item > .vt-panel > .vt-panel-body { flex: 1 1 auto; }

/* Vornin Insights — markdown remediation block. Lists default to 40px
   padding-inline-start which pushes content past the surrounding text;
   re-align so list bullets sit just inside the panel's pa-4 inset. */
.vt-vornin-insights-md { padding-left: 1.25rem; }
.vt-vornin-insights-md > :first-child { margin-top: 0; }
.vt-vornin-insights-md > :last-child  { margin-bottom: 0; }
.vt-vornin-insights-md ul,
.vt-vornin-insights-md ol {
    padding-inline-start: 1.25rem;
    margin: 0 0 0.75rem 0;
}
.vt-vornin-insights-md li { margin-bottom: 0.25rem; }
.vt-vornin-insights-md p  { margin: 0 0 0.5rem 0; }
.vt-vornin-insights-md code {
    font-family: var(--font-mono);
    font-size: 0.85em;
    padding: 1px 4px;
    border-radius: 3px;
    background: rgba(192,200,212,0.10);
}

/* Truncate text to N lines with an ellipsis. Width is constrained by the
   parent — pair with `max-width: 0` on the host cell when used in tables. */
.vt-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-clamp: 2;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
    line-height: 1.35;
}

/* =========================================================================
   <MudDataGrid> overrides for the vulnerabilities list.
   Stronger zebra striping + clickable-row hover affordance so the slim list
   reads cleanly even at high density.
   ========================================================================= */

.vt-vulns-grid .mud-table-row { cursor: pointer; }

/* Alternating row tint — bumped to be visible against the navy panel.
   Copper at 0.045 vanished on dark mode, so we layer a subtle white wash
   on top so the band is readable in both palettes. */
.vt-vulns-grid tbody .mud-table-row:nth-child(even) > td {
    background: rgba(192, 200, 212, 0.055);
}
[data-mud-theme] .vt-vulns-grid tbody .mud-table-row:hover > td {
    background: rgba(0, 191, 255,0.14);
}

/* Sticky header on the vulnerabilities grid. Default rendering shows the
   underlying rows through the head as you scroll — force a solid surface so
   column titles stay readable. Match the page surface so the header blends
   with the panel chrome rather than fighting it.
   KEEP !important — Mud sets backdrop-filter inline on sticky table headers. */
.vt-vulns-grid .mud-table-head .mud-table-cell,
.vt-vulns-grid thead th {
    background: var(--mud-palette-surface) !important;
    backdrop-filter: none !important;
}

/* =========================================================================
   Vulnerabilities page search field — clamp to 24px to match Size.Small
   chips. Selectors use plain .vt-vuln-search (no [data-mud-theme] prefix)
   because data-mud-theme may not be set at the time these rules cascade,
   which caused the entire selector to not match and left the field at its
   natural content height (~240px).
   ========================================================================= */
.vt-vuln-search,
.vt-vuln-search.mud-input-control-margin-dense {
    min-height: 0 !important;
    height: 24px !important;
    max-height: 24px !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    align-self: center !important;
    overflow: hidden !important;
}
.vt-vuln-search .mud-input-control-input-container,
.vt-vuln-search .mud-input-control,
.vt-vuln-search .mud-input,
.vt-vuln-search .mud-input-outlined,
.vt-vuln-search .mud-input-slot {
    min-height: 0 !important;
    height: 24px !important;
    max-height: 24px !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}
.vt-vuln-search div.mud-input.mud-input-text {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}
.vt-vuln-search .mud-input-outlined-border,
.vt-vuln-search fieldset {
    top: 0 !important;
    height: 24px !important;
    min-height: 24px !important;
    max-height: 24px !important;
}
.vt-vuln-search input {
    height: 22px !important;
    min-height: 22px !important;
    line-height: 22px !important;
    padding: 0 8px !important;
    font-size: 0.78rem !important;
}
.vt-vuln-search .mud-input-adornment {
    height: 22px !important;
    margin-top: 0 !important;
}
.vt-vuln-search .mud-input-adornment .mud-icon-root {
    font-size: 1rem !important;
}

/* =========================================================================
   <Skeleton> — line / card / table-row placeholders.
   Replaces generic spinners during data loads. CSS-only shimmer.
   ========================================================================= */

@keyframes vt-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}
.vt-skeleton {
    display: block;
    background: linear-gradient(
        90deg,
        var(--muted-fill) 0%,
        rgba(192,200,212,0.14) 50%,
        var(--muted-fill) 100%
    );
    background-size: 200% 100%;
    animation: vt-shimmer 1.4s linear infinite;
    border-radius: 4px;
}
.vt-skeleton-line { height: 0.85rem; width: 100%; }
.vt-skeleton-line.short { width: 40%; }
.vt-skeleton-line.medium { width: 65%; }
.vt-skeleton-line.long { width: 90%; }
.vt-skeleton-card {
    height: 96px;
    border-radius: var(--radius-lg);
}
.vt-skeleton-row {
    height: 48px;
    border-radius: 4px;
    margin-bottom: 6px;
}
.vt-skeleton-stack { display: flex; flex-direction: column; gap: 8px; }

@media (prefers-reduced-motion: reduce) {
    .vt-skeleton { animation: none; }
}

/* =========================================================================
   <ActionMenu> — primary button + overflow dots, replaces stacked button clusters.
   Visual: primary action sits flush with a divider, then the overflow trigger.
   ========================================================================= */

.vt-action-menu {
    display: inline-flex; align-items: stretch;
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-1);
}
[data-mud-theme] .vt-action-menu .mud-button-root.vt-action-primary {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
[data-mud-theme] .vt-action-menu .vt-action-overflow {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border-left: 1px solid rgba(13,31,60,0.18);
}

/* =========================================================================
   Attributes grid — labeled key/value pairs for detail-page metadata.
   Used inside <Panel Label="ATTRIBUTES"> on VulnerabilityDetail.
   ========================================================================= */

.vt-attrs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px 24px;
}
.vt-attr-label {
    font-family: var(--font-mono);
    font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 4px;
}
.vt-attr-value {
    font-size: 0.92rem;
    color: var(--mud-palette-text-primary);
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.vt-attr-sub {
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
    font-weight: 400;
}
.vt-attr-state {
    font-family: var(--font-mono);
    font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
    padding: 2px 8px;
    border-radius: 4px;
    border: 1px solid transparent;
    text-transform: uppercase;
}
.vt-attr-state.alert   { background: var(--sev-high-bg);   color: var(--sev-high);   border-color: var(--sev-high-border); }
.vt-attr-state.warn    { background: var(--sev-medium-bg); color: var(--sev-medium); border-color: var(--sev-medium-border); }
.vt-attr-state.success { background: var(--sev-low-bg);    color: var(--sev-low);    border-color: var(--sev-low-border); }

/* =========================================================================
   <SeverityBadge> size variants — sm uses tighter padding, md is default.
   ========================================================================= */

.vt-severity {
    display: inline-flex; align-items: center; gap: 4px;
    border-radius: 4px;
    font-family: var(--font-mono);
    font-weight: 700; letter-spacing: 0.06em;
    border: 1px solid transparent;
    text-transform: uppercase;
}
.vt-severity.sm { padding: 1px 6px; font-size: 0.62rem; }
.vt-severity.md { padding: 3px 10px; font-size: 0.72rem; }
.vt-severity .mud-icon-root { font-size: 0.85rem !important; }
.vt-severity.critical { background: var(--sev-critical-bg); color: var(--sev-critical); border-color: var(--sev-critical-border); }
.vt-severity.high     { background: var(--sev-high-bg);     color: var(--sev-high);     border-color: var(--sev-high-border); }
.vt-severity.medium   { background: var(--sev-medium-bg);   color: var(--sev-medium);   border-color: var(--sev-medium-border); }
.vt-severity.low      { background: var(--sev-low-bg);      color: var(--sev-low);      border-color: var(--sev-low-border); }
.vt-severity.info,
.vt-severity.none     { background: var(--sev-none-bg);     color: var(--sev-none);     border-color: var(--sev-none-border); }

/* ==========================================================================
   Targets page — sector rail, health rings, agent dots, target/group pills,
   action buttons. Hoisted from Targets.razor's inline <style> block and
   rebased onto v3 tokens (--copper / --steel / --muted / --border-dark).
   ========================================================================== */

.vt-shell {
    display: grid; grid-template-columns: 256px minmax(0, 1fr);
    gap: 24px; align-items: start;
}
@media (max-width: 980px) {
    .vt-shell { grid-template-columns: 1fr; gap: 16px; }
    .vt-rail { position: static; top: auto; }
}

.vt-rail {
    position: sticky; top: 24px;
    background: var(--navy);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: 8px;
}
.vt-rail-header {
    padding: 14px 14px 14px;
    border-bottom: 1px solid var(--border-dark);
    margin-bottom: 8px;
}
.vt-rail-header-label {
    font-family: var(--font-mono);
    font-size: 0.64rem; letter-spacing: 0.22em; text-transform: uppercase;
    color: var(--muted);
}
.vt-rail-header-title {
    margin-top: 4px;
    font-size: 0.95rem; font-weight: 600; color: var(--off-white);
}
.vt-rail-item {
    position: relative;
    display: flex; align-items: center; gap: 10px;
    width: 100%; padding: 10px 12px 10px 14px;
    background: transparent;
    border: none; border-left: 2px solid transparent;
    border-radius: 0 6px 6px 0;
    color: var(--steel); font: inherit; font-size: 0.9rem;
    cursor: pointer; text-align: left;
    transition: background var(--dur-quick) var(--ease-out),
                color var(--dur-quick) var(--ease-out),
                border-color var(--dur-quick) var(--ease-out);
}
.vt-rail-item:focus-visible { outline: 2px solid var(--copper); outline-offset: -2px; }
.vt-rail-item:hover { background: rgba(255,255,255,0.04); color: var(--off-white); }
.vt-rail-item.active {
    background: var(--copper-dim);
    border-left-color: var(--copper);
    color: var(--off-white);
}
.vt-rail-swatch { width: 8px; height: 8px; border-radius: 2px; background: var(--muted); flex-shrink: 0; }
.vt-rail-all .vt-rail-swatch { background: transparent; border: 1px solid var(--steel); }
.vt-rail-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-rail-count {
    font-family: var(--font-mono);
    font-size: 0.75rem; color: var(--muted); letter-spacing: 0.02em;
}
.vt-rail-item.active .vt-rail-count { color: var(--copper); }
.vt-rail-delete {
    opacity: 0; padding: 2px; margin-left: 2px;
    background: transparent; border: none; color: var(--muted);
    cursor: pointer; display: flex; border-radius: 4px;
    transition: opacity var(--dur-quick) var(--ease-out),
                color var(--dur-quick) var(--ease-out),
                background var(--dur-quick) var(--ease-out);
}
.vt-rail-item:hover .vt-rail-delete { opacity: 0.7; }
.vt-rail-delete:hover { opacity: 1; color: #DB7884; background: rgba(219,120,132,0.1); }
.vt-rail-add {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 10px 14px;
    background: transparent;
    border: 1px dashed var(--border-dark-2);
    border-radius: 6px; margin-top: 10px;
    color: var(--muted); font: inherit; font-size: 0.85rem;
    cursor: pointer;
    transition: color var(--dur-quick) var(--ease-out),
                border-color var(--dur-quick) var(--ease-out);
}
.vt-rail-add:hover { color: var(--copper); border-color: rgba(0,191,255,0.45); }

.vt-target-name { font-weight: 600; color: var(--off-white); margin-bottom: 2px; letter-spacing: -0.005em; }
.vt-target-host {
    font-family: var(--font-mono);
    font-size: 0.76rem; color: var(--muted); letter-spacing: -0.005em;
}

.vt-group-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px 3px 8px; border-radius: 999px;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.015em;
}
.vt-group-swatch { width: 6px; height: 6px; border-radius: 50%; }

.vt-agent { display: flex; align-items: center; gap: 8px; font-size: 0.88rem; color: var(--steel); }
.vt-agent-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
.vt-agent-dot.online { background: #4CAD7E; box-shadow: 0 0 0 2px rgba(76,173,126,0.18); }
.vt-agent-dot.busy   { background: var(--copper-hover); box-shadow: 0 0 0 2px rgba(0,191,255,0.18); }
.vt-agent.direct { color: var(--muted); font-style: italic; }

/* Health ring — circumference = 2πr ≈ 100 when r=15.915, so dasharray uses score directly */
.vt-health { display: flex; align-items: center; gap: 12px; }
.vt-health-ring { position: relative; width: 40px; height: 40px; flex-shrink: 0; }
.vt-health-ring svg { transform: rotate(-90deg); }
.vt-health-ring-track { stroke: rgba(255,255,255,0.10); }
.vt-health-ring-letter {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 0.9rem;
}
.vt-health-score {
    font-family: var(--font-mono);
    font-size: 0.78rem; color: var(--muted);
}
.vt-health-na {
    font-family: var(--font-mono);
    font-size: 0.76rem; color: var(--muted); letter-spacing: 0.06em;
}

.vt-actions { display: flex; gap: 2px; justify-content: flex-end; }
[data-mud-theme] .vt-actions .mud-icon-button { color: var(--muted); }
[data-mud-theme] .vt-actions .mud-icon-button:hover { background: rgba(255,255,255,0.06); color: var(--off-white); }
[data-mud-theme] .vt-actions .mud-icon-button.vt-action-scan { color: var(--copper); }
[data-mud-theme] .vt-actions .mud-icon-button.vt-action-scan:hover { background: rgba(0,191,255,0.12); color: var(--copper-hover); }
[data-mud-theme] .vt-actions .mud-icon-button.vt-action-delete:hover { background: rgba(219,120,132,0.08); color: #DB7884; }

.vt-csv-hint {
    font-family: var(--font-mono);
    font-size: 0.78rem; color: var(--muted); background: var(--navy-deep);
    padding: 10px 12px; border: 1px solid var(--border-dark);
    border-radius: 6px; margin-bottom: 12px;
}

/* =========================================================================
   Abyssal CTA glow — animated conic-gradient border on primary buttons.
   Applied globally to MudButton[Color=Primary, Variant=Filled] and to .btn-cta.
   Browsers without @property fall back gracefully (no animation, just border).
   ========================================================================= */
@property --vt-glow-angle {
    syntax: '<angle>';
    inherits: false;
    initial-value: 0deg;
}
@keyframes vt-glow-spin {
    to { --vt-glow-angle: 360deg; }
}

/* App Primary Button — solid teal fill + white conic glow ring at reduced peak.
   Per vornin_brand_system.md §3 "App Primary Button":
   - color: #0A0F24, background: #00BFFF
   - ring peak white at 0.65 opacity (vs 0.95 on the website primary)
   - 4s spin (vs 3s website) for in-app calm
   - hover lifts +1px and lightens to #33CCFF
   [data-mud-theme] prefix raises specificity to 0,3,2 — beats Mud's
   .mud-button-filled.mud-button-filled-primary (0,2,0) without !important. */
[data-mud-theme] .mud-button-filled.mud-button-filled-primary,
[data-mud-theme] .btn-cta,
[data-mud-theme] .vt-btn-primary {
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--btn-ink);
    background: var(--btn-bg);
    padding: 9px 20px;
    border-radius: 4px;
    border: none;
    cursor: pointer;
    letter-spacing: 0.3px;
    position: relative;
    transition: transform 0.15s ease, background-color 0.15s ease, filter 0.15s ease;
    overflow: visible;
    text-transform: none;
    box-shadow: none;
}
[data-mud-theme] .mud-button-filled.mud-button-filled-primary:hover,
[data-mud-theme] .btn-cta:hover,
[data-mud-theme] .vt-btn-primary:hover {
    transform: translateY(-1px);
    background: var(--btn-hover);
    color: var(--btn-ink);
    filter: drop-shadow(0 0 8px rgba(0,191,255,0.35));
}

/* ::before — white conic glow ring (4s, reduced peak per app spec).
   Mud doesn't use ::before on filled buttons, so no specificity fight. */
[data-mud-theme] .mud-button-filled.mud-button-filled-primary::before,
[data-mud-theme] .btn-cta::before,
[data-mud-theme] .vt-btn-primary::before {
    content: "";
    position: absolute;
    inset: -1.5px;
    border-radius: 5px;
    z-index: -1;
    padding: 1.5px;
    background: conic-gradient(from var(--vt-glow-angle),
        transparent 70%,
        rgba(255,255,255,0.65) 85%,
        rgba(255,255,255,0.25) 92%,
        transparent 96%);
    -webkit-mask: linear-gradient(#000 0 0) content-box,
                  linear-gradient(#000 0 0);
            mask: linear-gradient(#000 0 0) content-box,
                  linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    animation: vt-glow-spin 4s linear infinite;
    pointer-events: none;
}
[data-mud-theme] .mud-button-filled.mud-button-filled-primary::after,
[data-mud-theme] .btn-cta::after,
[data-mud-theme] .vt-btn-primary::after {
    content: none;
    display: none;
}

/* Keep label above ring */
[data-mud-theme] .mud-button-filled.mud-button-filled-primary .mud-button-label,
[data-mud-theme] .mud-button-filled.mud-button-filled-primary > *,
[data-mud-theme] .btn-cta > *,
[data-mud-theme] .vt-btn-primary > * { position: relative; z-index: 1; }

/* Light mode — flat solid teal, no orbit */
[data-mud-theme="light"] .mud-button-filled.mud-button-filled-primary::before,
.mud-theme-light .mud-button-filled.mud-button-filled-primary::before {
    display: none;
}
[data-mud-theme="light"] .mud-button-filled.mud-button-filled-primary,
.mud-theme-light .mud-button-filled.mud-button-filled-primary {
    background: var(--teal);
}

/* Brand wordmark — "VORNIN." with teal period (per vornin_brand_system.md §8) */
.vt-brand {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    text-transform: uppercase;
    color: var(--off-white);
    user-select: none;
}
.vt-brand .vt-brand-dot { color: var(--teal); }

/* Logo silhouette — invert black artwork onto dark canvas */
.vt-logo-invert { filter: invert(1); }

@media (prefers-reduced-motion: reduce) {
    .mud-button-filled.mud-button-filled-primary::before,
    .btn-cta::before {
        animation: none;
        background: var(--teal);
        opacity: 0.5;
    }
}

/* Coverage-by-category heatmap — used on /admin/compliance/{slug}.
   Each row: category label, stacked pass/fail bar, raw counts. */
.vt-coverage-row {
    display: grid;
    grid-template-columns: 200px 1fr 80px;
    gap: 12px;
    align-items: center;
}
.vt-coverage-label {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.vt-coverage-bar {
    display: flex;
    height: 14px;
    border-radius: 7px;
    overflow: hidden;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--border-dark);
}
.vt-coverage-seg { height: 100%; transition: width var(--dur-base) var(--ease-out); }
.vt-coverage-seg.pass { background: #4CAD7E; }
.vt-coverage-seg.fail { background: #DB7884; }
.vt-coverage-count {
    font-family: var(--font-mono);
    font-size: 0.85rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
    .vt-coverage-row { grid-template-columns: 100px 1fr 60px; gap: 8px; }
    .vt-coverage-label { font-size: 0.7rem; }
}

/* Sticky bulk-action toolbar on the Vulnerabilities list — keeps the action
   menu in view as the user scrolls a long results table. */
.vt-bulk-actions {
    position: sticky;
    top: 64px;
    z-index: 10;
    backdrop-filter: blur(8px);
    background: rgba(33, 43, 69, 0.95); /* --card with high alpha; covers list rows behind */
    border: 1px solid var(--border-dark);
}

/* Live indicator — pulsing teal dot used near scan-progress headers. */
.vt-live-dot {
    display: inline-block; width: 8px; height: 8px;
    border-radius: 50%; background: var(--teal);
    box-shadow: 0 0 0 0 rgba(0,191,255,0.55);
    animation: vt-live-pulse 1.6s ease-out infinite;
}
@keyframes vt-live-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(0,191,255,0.55); }
    70%  { box-shadow: 0 0 0 8px rgba(0,191,255,0); }
    100% { box-shadow: 0 0 0 0 rgba(0,191,255,0); }
}
@media (prefers-reduced-motion: reduce) {
    .vt-live-dot { animation: none; }
}

/* ==========================================================================
   PlanGate — uniform "feature locked" overlay for plan-tier gated UI.
   Used by <PlanGate Feature="..."> when the tenant lacks the feature.
   ========================================================================== */
.vt-plan-gate {
    display: flex; gap: 18px; align-items: flex-start;
    padding: 20px 22px;
    border: 1px dashed rgba(0,191,255,0.35);
    border-radius: var(--radius-lg);
    background: linear-gradient(180deg, rgba(0,191,255,0.04) 0%, rgba(0,191,255,0.01) 100%);
    margin: 8px 0;
}
.vt-plan-gate-icon {
    flex: 0 0 48px; width: 48px; height: 48px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,191,255,0.10);
    color: var(--teal);
}
.vt-plan-gate-body { flex: 1; min-width: 0; }
.vt-plan-gate-title {
    margin: 4px 0 6px;
    font-family: var(--font-display);
    font-size: 1.05rem; font-weight: 600; letter-spacing: -0.01em;
    color: var(--off-white);
}
.vt-plan-gate-sub {
    margin: 0;
    color: rgba(255,255,255,0.72);
    font-size: 0.92rem; line-height: 1.5;
}

/* ==========================================================================
   Severity utility text classes — single source of truth for severity colors
   in inline contexts (KPIs, table cells, banners). Replaces hard-coded
   `style="color: #..."` patterns scattered across razor files.
   ========================================================================== */
.vt-severity-text-critical { color: #B85A66; }
.vt-severity-text-high     { color: #DB7884; }
.vt-severity-text-medium   { color: #C98B3F; }
.vt-severity-text-low      { color: #4CAD7E; }
.vt-severity-text-info     { color: rgba(255,255,255,0.72); }
.vt-severity-text-success  { color: #4CAD7E; }

/* Severity-bar segment (used by Vulnerabilities filter chips). Replaces
   inline-styled <button> elements that bypassed the global focus ring. */
.vt-severity-segment {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 12px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: rgba(255,255,255,0.04);
    color: rgba(255,255,255,0.72);
    font-family: var(--font-mono);
    font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase;
    cursor: pointer;
    transition: background var(--dur-quick) var(--ease-out), border-color var(--dur-quick) var(--ease-out);
}
.vt-severity-segment:hover { background: rgba(255,255,255,0.08); }
.vt-severity-segment.active { border-color: rgba(0,191,255,0.45); background: rgba(0,191,255,0.10); }
.vt-severity-segment:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

/* ==========================================================================
   Mobile breakpoints — adaptive padding so narrow viewports don't feel cramped.
   Tier 5.4 of the 2026-05-02 UX audit.
   ========================================================================== */
@media (max-width: 640px) {
    /* .mud-main-content: !important required because Mud sets padding inline via Class. */
    .mud-main-content { padding-left: 12px !important; padding-right: 12px !important; }
    /* Pure .vt-* rules below — no !important needed. */
    .vt-hero { padding: 16px; }
    .vt-hero-title { font-size: 1.6rem; }
    .vt-kpis { grid-template-columns: 1fr 1fr; gap: 8px; }
    .vt-panel-body.padded { padding: 14px; }
}

/* ==========================================================================
   Mobile UX hardening (2026-05-10) — touch / hover / scrollable-tabs sweep.
   - Touch-action: manipulation removes the 300ms tap-delay on iOS Safari and
     prevents double-tap-to-zoom from swallowing primary taps.
   - hover: none reveals hover-only affordances (e.g. .vt-rail-delete) on
     touch devices that never fire :hover.
   - MudTabs' default toolbar can clip when many tabs render side-by-side; the
     overflow-x rule lets users scroll the tab strip horizontally on narrow
     viewports without breaking MudBlazor's prev/next button layout.
   ========================================================================== */
button, a, [role="button"],
[data-mud-theme] .mud-button-root,
[data-mud-theme] .mud-icon-button-root,
[data-mud-theme] .mud-nav-link,
.vt-rail-item, .vt-severity-segment {
    touch-action: manipulation;
}

@media (hover: none) {
    /* Hover-only affordances must be reachable on touch. */
    .vt-rail-delete { opacity: 0.7; }
    .vt-rail-item:hover .vt-rail-delete { opacity: 0.7; }
}

@media (max-width: 768px) {
    /* MudTabs — let the toolbar scroll horizontally on narrow widths so tabs
       with many panels (ScanDetail per-scanner, Settings sections, Account)
       don't wrap into multiple rows or get clipped. */
    [data-mud-theme] .mud-tabs-toolbar-content {
        overflow-x: auto;
        scrollbar-width: thin;
    }
    [data-mud-theme] .mud-tabs-toolbar-content::-webkit-scrollbar {
        height: 4px;
    }
}

/* Hide brand wordmark + username text + ExpandMore caret on Xs (≤599px) so the
   AppBar fits hamburger + logo + tenant switcher + bell + theme + user-menu on
   a 375px viewport. The user-menu activator collapses to a 36px account icon;
   the StartIcon (AccountCircle) remains so the click target is recognizable. */
@media (max-width: 599.95px) {
    .vt-appbar-brand-text { display: none; }
    .vt-appbar-username { display: none; }
    .vt-appbar-user .mud-button-icon-end { display: none; }
    .vt-appbar-user { min-width: 0; padding-left: 8px; padding-right: 8px; }
}

/* Mobile dialogs go (effectively) full-screen — MaxWidth.Medium / Large
   dialogs (compliance attestation drilldown, vulnerability quick-view, scan
   wizard) waste 32px+ of side margin on a 375px viewport. Push them to edge
   on Xs so the inner content has room to breathe. */
@media (max-width: 599.95px) {
    [data-mud-theme] .mud-dialog-container .mud-dialog {
        max-width: 100%;
        max-height: 100%;
        width: 100%;
        height: 100%;
        margin: 0;
        border-radius: 0;
    }
    [data-mud-theme] .mud-dialog-container .mud-dialog .mud-dialog-content {
        max-height: calc(100dvh - 132px);
    }
}

/* ==========================================================================
   Mobile review fixes (2026-05-10) — second pass after live phone testing.
   ========================================================================== */

/* (#1) Attack Surface — host column was overflowing because the cell stamps
   the discovered host on line 1 + the root target name on line 2. On Xs the
   target line eats the only viewport space we have; truncate the host with
   ellipsis and hide the target line entirely. */
@media (max-width: 599.95px) {
    .vt-as-host { max-width: 60vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .vt-as-target { display: none; }
}

/* (#2) ScanNow — the "1. Select Targets / 2. Choose Scanners / 3. Review &
   Launch" chip strip is wider than 375px and clutters the header. Hide on Xs
   (the in-step "Back / Next" buttons make navigation obvious anyway).
   `!important` is required because MudStack stamps display:flex inline on the
   root <div>; class-level rules can't beat inline declarations otherwise. */
@media (max-width: 599.95px) {
    .vt-scan-step-indicator { display: none !important; }
}

/* (#3 / R2) ScanNow Step 2 — let the "Select scan types" header row stack
   vertically so the title takes its own line and the Recommended/Comprehensive
   buttons drop below it full-width. Same `!important` rationale as (#2). */
@media (max-width: 599.95px) {
    .vt-scan-step-header { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; }
    .vt-scan-step-header > .mud-button-root,
    .vt-scan-step-header .mud-tooltip-root { width: 100%; }
    .vt-scan-step-header .mud-tooltip-root .mud-button-root { width: 100%; }
    /* Category card row also stacks: name+desc on top, count + Advanced below. */
    .vt-scan-cat-row { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; }
    /* Inner scanner option card flips to column too. */
    .vt-scanner-card .mud-stack-row { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* (#6) Targets — sector rail is hidden on Xs entirely; the user can manage
   groups on tablet+. Targets-list still shows the group pill per row. */
@media (max-width: 599.95px) {
    .vt-rail { display: none; }
    .vt-shell { gap: 0; }
}

/* (#9 / R2) VulnerabilityDetail header — on Xs the entire MudStack splits
   into a vertical column: title row on top, action row below. We use
   !important to beat MudStack's inline flex-direction:row, and force each
   inner stack to take a full row of its own. The view-mode toggle (Formatted/
   Table/JSON) still hides on Xs since "Formatted" is the only useful default
   on a phone. */
@media (max-width: 599.95px) {
    .vt-vulndetail-header { flex-direction: column !important; align-items: stretch !important; gap: 12px !important; }
    .vt-vulndetail-header > .mud-stack-row { width: 100%; }
    .vt-vulndetail-title { font-size: 1.25rem !important; line-height: 1.25 !important; word-break: break-word; }
    .vt-vulndetail-toggle { display: none; }
}

/* (#10) Compliance settings — Mud popover sometimes renders behind the
   dialog/panel because its z-index defaults to 1300. Bump select popovers
   above the rest of the surface chrome. */
[data-mud-theme] .mud-popover.mud-popover-open {
    z-index: 1500;
}

/* (#11) Compliance dashboard — `<Actions>` slot has 3 buttons that can blow
   past 375px even with flex-wrap. On Xs stack them full-width. */
@media (max-width: 599.95px) {
    .vt-hero-actions { width: 100%; }
    .vt-hero-actions > * { flex: 1 1 auto; }
    .vt-hero-actions .mud-button-root { width: 100%; }
}

/* (#12 / R4) Compliance control drilldown — earlier rounds tried to morph
   MudTable cells into cards via display:block + nth-of-type pseudo-labels;
   that approach was unreliable across MudBlazor's table renderer (cells
   stayed in their column box on some renders, content kept overflowing
   horizontally). Round 4 ships an explicit parallel card list in markup
   (.vt-drilldown-mobile in the dialog razor) and toggles the table vs the
   cards via display visibility per breakpoint. Tap a card → opens that
   vulnerability detail in a new tab. */
.vt-drilldown-mobile { display: none; }
@media (max-width: 599.95px) {
    .vt-drilldown-table-wrap { display: none; }
    .vt-drilldown-mobile { display: flex; flex-direction: column; gap: 10px; }
}
.vt-drilldown-mobile-card {
    display: block;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--border-dark);
    border-radius: var(--radius);
    background: var(--mud-palette-surface);
    padding: 10px 12px;
    transition: border-color var(--dur-quick) var(--ease-out), background var(--dur-quick) var(--ease-out);
}
.vt-drilldown-mobile-card:hover,
.vt-drilldown-mobile-card:active {
    border-color: rgba(0, 191, 255, 0.45);
    background: rgba(0, 191, 255, 0.04);
}
.vt-drilldown-mobile-card-row {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    padding: 4px 0;
    text-align: left;
}
.vt-drilldown-mobile-card-row + .vt-drilldown-mobile-card-row {
    border-top: 1px solid rgba(192, 200, 212, 0.06);
}
.vt-drilldown-mobile-card-label {
    flex: 0 0 90px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    padding-top: 3px;
}
.vt-drilldown-mobile-card-value {
    flex: 1;
    min-width: 0;
    word-break: break-word;
    overflow-wrap: anywhere;
    text-align: left;
}

/* (#R2 #8 / Compliance framework page) Per-control card row stacks on Xs so
   the failing-count action button drops below the long control title. */
@media (max-width: 599.95px) {
    .vt-control-card .mud-stack-row { flex-direction: column !important; align-items: flex-start !important; gap: 6px !important; }
    .vt-control-card .mud-stack-row .mud-button-root,
    .vt-control-card .mud-stack-row .mud-chip { width: auto; }
}

/* (#R2 #4 / Scan compare) Two scan dropdowns + Compare button stack
   vertically on Xs; each control takes its own line, full-width. */
@media (max-width: 599.95px) {
    .vt-compare-controls { flex-direction: column !important; align-items: stretch !important; gap: 12px !important; }
    .vt-compare-controls > * { width: 100%; }
}

/* (#R2 #5 / Vuln mobile actions) Inline action row at the bottom of every
   mobile vuln card — same actions the desktop overflow menu offers. We
   render them as text-only icon buttons so multiple fit on one row at
   375px. The cluster lives inside the card, click events stop propagating
   so tapping an action doesn't trigger the parent card's navigation. */
.vt-vulns-mobile-card-actions {
    display: flex;
    gap: 4px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(192, 200, 212, 0.06);
    flex-wrap: wrap;
}
.vt-vulns-mobile-card-actions .mud-icon-button-root { width: 36px; height: 36px; }

/* (R3 #1 / Attack Surface toolbar) Filter chip row + bulk-action buttons
   stack vertically on Xs. The filters (chip cluster) get their own line
   that wraps; the action buttons (Add as Target / Ignore) drop below into
   a stretched row so each tap target stays ≥44px tall. */
.vt-as-toolbar-filters { display: inline-flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.vt-as-toolbar-actions { display: inline-flex; flex-wrap: wrap; gap: 8px; align-items: center; }
@media (max-width: 599.95px) {
    .vt-as-toolbar { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; }
    .vt-as-toolbar > * { width: 100%; }
    .vt-as-toolbar-actions { flex-direction: column; }
    .vt-as-toolbar-actions > .mud-button-root { width: 100%; }
}

/* (#13) Schedule rows — bump alternate-row contrast so paused/active scans
   and report schedules are visually distinct. Default Mud striping is too
   subtle on dark surfaces. */
[data-mud-theme] .vt-schedule-grid .mud-table-body .mud-table-row:nth-child(even) > td {
    background: rgba(255, 255, 255, 0.04);
}
.mud-theme-light [data-mud-theme] .vt-schedule-grid .mud-table-body .mud-table-row:nth-child(even) > td,
[data-mud-theme="light"] .vt-schedule-grid .mud-table-body .mud-table-row:nth-child(even) > td {
    background: rgba(15, 23, 42, 0.04);
}

/* (#14 / R2) Reports — the post-generate PDF iframe doesn't render usefully
   on Chrome mobile (the embedded PDF viewer either fails or shows a download
   shim). Hide it entirely on tablets/phones (≤768px) and rely on the
   Download PDF / Other Formats buttons. The pre-generate cover-preview
   placeholder is also hidden on Xs.
   Buttons stack via the wrapper .vt-report-actions; we use !important to
   beat MudStack's inline flex-direction:row, and also stack the inner
   .vt-report-actions-row when there are 2+ actions so they get a 50/50
   split below the title. */
@media (max-width: 768px) {
    .vt-report-iframe { display: none !important; }
}
@media (max-width: 599.95px) {
    .vt-report-preview-wrap { display: none; }
    .vt-report-actions { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; }
    .vt-report-actions > .mud-button-root,
    .vt-report-actions > .mud-menu { width: 100%; }
    .vt-report-actions-row { display: flex; gap: 8px; width: 100%; }
    .vt-report-actions-row > * { flex: 1 1 50%; min-width: 0; }
    .vt-report-actions-row .mud-button-root,
    .vt-report-actions-row .mud-menu { width: 100%; }
}

/* (#15) ApiKeys — the "Usage" curl example block was centred because the
   parent <Panel> applies text-align:center on the heading row. Force the
   inner <pre> to left-align. */
.vt-mono-block, .mud-mono-block {
    text-align: left;
}

/* (#7) Vulnerabilities — on Xs we render a parallel card list (.vt-vulns-mobile)
   instead of trying to stack MudDataGrid cells via CSS. The data-grid gets
   display:none on Xs, the mobile list gets display:block. Each card stamps
   each property as a label/value pair stacked vertically. */
.vt-vulns-mobile { display: none; }
@media (max-width: 599.95px) {
    .vt-vulns-grid-wrap { display: none; }
    .vt-vulns-mobile { display: flex; flex-direction: column; gap: 12px; }
}
.vt-vulns-mobile-card {
    border: 1px solid var(--border-dark);
    border-radius: var(--radius);
    background: var(--mud-palette-surface);
    padding: 12px 14px;
    cursor: pointer;
    transition: border-color var(--dur-quick) var(--ease-out), background var(--dur-quick) var(--ease-out);
}
.vt-vulns-mobile-card:hover,
.vt-vulns-mobile-card:active {
    border-color: rgba(0, 191, 255, 0.45);
    background: rgba(0, 191, 255, 0.04);
}
.vt-vulns-mobile-card-row { display: flex; gap: 8px; align-items: flex-start; padding: 4px 0; }
.vt-vulns-mobile-card-row + .vt-vulns-mobile-card-row { border-top: 1px solid rgba(192, 200, 212, 0.06); }
.vt-vulns-mobile-card-label {
    flex: 0 0 90px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    padding-top: 3px;
}
.vt-vulns-mobile-card-value { flex: 1; min-width: 0; word-break: break-word; }
.vt-vulns-mobile-card-title { font-weight: 600; margin-bottom: 4px; word-break: break-word; }

/* ==========================================================================
   Report cover preview — rendered on /reports before the user generates.
   Embeds the actual PDF cover HTML inside an iframe srcdoc, scaled via a
   container query so what the user sees on screen matches the first page
   of the PDF 1:1. Watermark + disclaimer pill are overlaid in the parent
   DOM (above the iframe) so they don't end up in the rendered cover.
   ========================================================================== */
.vt-report-preview-wrap {
    display: flex;
    justify-content: center;
    padding: 8px 0 24px;
}
.vt-preview-stage {
    container-type: inline-size;
    width: 100%;
    max-width: 720px;
    aspect-ratio: 210 / 297; /* A4 portrait */
    position: relative;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 18px 48px rgba(0,0,0,0.55), 0 2px 6px rgba(0,0,0,0.35);
    user-select: none;
    background: #0A0F24;
}
.vt-preview-frame {
    position: absolute;
    top: 0;
    left: 0;
    width: 794px;   /* A4 width @ 96dpi (210mm) */
    height: 1123px; /* A4 height @ 96dpi (297mm) */
    border: 0;
    background: transparent;
    transform-origin: top left;
    transform: scale(calc(100cqw / 794));
    pointer-events: none;
}
.vt-cover-watermark {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 2;
}
.vt-cover-watermark span {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: clamp(3rem, 9vw, 5.5rem);
    letter-spacing: 0.35em;
    color: rgba(255,255,255,0.10);
    transform: rotate(-22deg);
    text-transform: uppercase;
    white-space: nowrap;
    border: 4px solid rgba(255,255,255,0.10);
    padding: 0.35em 0.7em;
    border-radius: 12px;
}
.vt-cover-disclaimer {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 3;
    background: linear-gradient(0deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0) 100%);
    padding: 3rem 1.5rem 1.5rem;
    text-align: center;
    pointer-events: none;
}
.vt-cover-disclaimer-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: rgba(0,191,255,0.18);
    border: 1px solid rgba(0,191,255,0.45);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.55rem 1rem;
    border-radius: 999px;
    backdrop-filter: blur(4px);
}

/* Attack Surface Overview grid */
.vt-as-overview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
.vt-empty-line { padding: 12px 0; opacity: 0.6; }

/* Cloudflare Turnstile widget is fixed 300x65; scale down when auth card
   narrower than that on mobile so it stops overflowing past the email field.
   Card chrome on /auth/login + /auth/register: ExtraSmall MudContainer (24px)
   + MudPaper pa-10 (80px) = 104px viewport chrome. */
#login-turnstile, #register-turnstile {
    transform-origin: left top;
}
@media (max-width: 420px) {
    #login-turnstile, #register-turnstile {
        transform: scale(calc((100vw - 104px) / 300));
        height: calc(65px * ((100vw - 104px) / 300));
    }
}

/* ─────────────────────────────────────────────────────────────────────
   AuthShell — canonical chrome for /auth/* pages under EmptyLayout.
   Login / Register / TotpVerify / TotpSetup / AcceptUpdatedTerms all
   route through <AuthShell> for shared logo size, padding, border,
   and typography.
   ───────────────────────────────────────────────────────────────────── */
.vt-auth-shell {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    box-sizing: border-box;
}

.vt-auth-card {
    width: 100%;
    max-width: 440px;
    padding: 2.5rem;
    border-radius: 14px;
    background: var(--card);
    border: 1px solid rgba(148, 163, 184, 0.1);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.02) inset, 0 24px 48px -24px rgba(0, 0, 0, 0.5);
}

.vt-auth-shell.wide .vt-auth-card {
    max-width: 640px;
}

.vt-auth-logo {
    display: block;
    margin-bottom: 1.75rem;
    text-decoration: none;
    line-height: 0;
}

.vt-auth-logo img {
    height: 36px;
    width: auto;
    display: block;
}

.vt-auth-eyebrow {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.7rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--teal);
    margin-bottom: 0.5rem;
}

.vt-auth-title {
    font-family: var(--font-display, 'Plus Jakarta Sans', sans-serif);
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.2;
    margin: 0 0 0.4rem 0;
    color: var(--text);
}

.vt-auth-subtitle {
    margin: 0 0 1.5rem 0;
    color: var(--mud-palette-text-secondary, rgba(255, 255, 255, 0.6));
    font-size: 0.92rem;
    line-height: 1.5;
}

.vt-auth-footer {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid rgba(148, 163, 184, 0.1);
    text-align: center;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, rgba(255, 255, 255, 0.6));
}

@media (max-width: 480px) {
    .vt-auth-shell { padding: 1rem 0.75rem; }
    .vt-auth-card { padding: 1.75rem 1.25rem; }
    .vt-auth-logo img { height: 30px; }
    .vt-auth-title { font-size: 1.3rem; }
}

/* Social-login row — moved out of Login.razor inline <style> block. */
.social-login-stack {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
}
.social-login-btn { justify-content: flex-start; }
.social-icon {
    display: inline-flex;
    align-items: center;
    margin-right: 0.75rem;
}
.social-login-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1rem 0;
    color: var(--mud-palette-text-secondary);
}
.social-login-divider::before,
.social-login-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

/* TOTP QR halo — moved out of TotpSetup.razor inline <style> block,
   plus a soft halo so the required white background reads as an
   intentional inset rather than a forgotten dark-mode case. */
.vt-totp-qr {
    display: flex;
    justify-content: center;
    margin-bottom: 1rem;
}
.vt-totp-qr-box {
    width: 220px;
    height: 220px;
    background: #fff;
    padding: 8px;
    border-radius: 8px;
    box-sizing: border-box;
    box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.06);
}
.vt-totp-qr-box svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* ─────────────────────────────────────────────────────────────────────
   EPSS chip — replaces MudBlazor Color.Error/Warning/Default enum.
   Buckets map to severity tokens for visual continuity with the rest
   of the row chrome.
   ───────────────────────────────────────────────────────────────────── */
.vt-epss-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid;
}
.vt-epss-chip--high     { background: var(--sev-high-bg);     color: var(--sev-high);     border-color: var(--sev-high-border); }
.vt-epss-chip--medium   { background: var(--sev-medium-bg);   color: var(--sev-medium);   border-color: var(--sev-medium-border); }
.vt-epss-chip--low      { background: var(--sev-none-bg);     color: var(--sev-none);     border-color: var(--sev-none-border); }

/* VulnTable age cell — replaces inline `style="color: ...; font-weight: 600/400"`
   on VulnTable.razor age column. */
.vt-vuln-age          { font-weight: 400; }
.vt-vuln-age--warning { color: var(--age-warning); font-weight: 400; }
.vt-vuln-age--aged    { color: var(--sev-medium);  font-weight: 600; }
.vt-vuln-age--stale   { color: var(--sev-high);    font-weight: 600; }
