/**
 * VT Stats — Premium Glassmorphic Theme Layer
 *
 * Additive visual layer: Geist typography, glass surfaces, depth shadows,
 * animations, and ambient effects. Loads AFTER layout.css. Uses --kb-*
 * variables for colors (all 44 themes supported), --vt-* for effects.
 *
 * Geist fonts v1.8.0 — vendored from https://github.com/vercel/geist-font
 */

/* ============================================================================
   FONT FACES
   Variable fonts — single file covers weight range 100-900
   ============================================================================ */

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

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

/* ============================================================================
   TYPOGRAPHY
   Global font override + data-oriented refinements
   ============================================================================ */

body {
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    position: relative;
    z-index: 0;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    letter-spacing: -0.01em;
}

.card-header h5 {
    letter-spacing: -0.015em;
    font-weight: 600;
}

.vt-mono {
    font-family: 'Geist Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
}

.stat-value {
    font-family: 'Geist Mono', ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    font-size: 1.5rem;
    font-weight: 700;
}

.table td.text-end,
.table th.text-end {
    font-variant-numeric: tabular-nums;
}

code, pre, .font-monospace {
    font-family: 'Geist Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace;
}

.navbar-brand {
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    letter-spacing: -0.02em;
}

/* ============================================================================
   MIGRATED INLINE STYLES
   Moved from index.html <style> block for modularity
   ============================================================================ */

.chart-container {
    position: relative;
    min-height: 320px;
}

.chart-container-sm {
    position: relative;
    min-height: 200px;
}

/* Distance from Spawn card: stretch the chart container to fill all space the
   card offers (so it visually matches the neighbour All Players Heatmap card
   in the same row). Scoped to this one section so other chart cards keep
   their current 320px fixed-ish behavior. */
#section-distance-timeline .card-body {
    display: flex;
    flex-direction: column;
}

#section-distance-timeline .card-body > .chart-container {
    flex: 1 1 auto;
    min-height: 320px;
}

.heatmap-cell {
    font-size: 0.75rem;
    min-width: 60px;
    padding: 4px !important;
    font-variant-numeric: tabular-nums;
}

.heatmap-header {
    font-size: 0.7rem;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    max-width: 40px;
    padding: 4px !important;
    white-space: nowrap;
}

.heatmap-corner {
    width: 100px;
}

.heatmap-row-header {
    font-size: 0.75rem;
    white-space: nowrap;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rivalry-card {
    background: var(--kb-bg-card);
    border: 1px solid var(--kb-border-subtle);
}

.stat-card {
    text-align: center;
}

.stat-label {
    font-size: 0.75rem;
    color: var(--kb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 500;
}

th[data-sort] {
    cursor: pointer;
    user-select: none;
}

th[data-sort]:hover {
    color: var(--kb-primary);
}

th[data-sort].sort-active {
    color: var(--kb-primary);
}

.badge-f1 {
    background: var(--kb-primary);
    color: var(--kb-primary-fg);
}

.badge-f2 {
    background: var(--kb-accent);
    color: var(--kb-accent-fg);
}

/* Movement Leaderboard rows double as the focus selector for the Distance
   from Spawn chart — clicking a row sets focus mode, clicking the same row
   again clears it. The `vt-row-focused` tint mirrors the card-header toggle
   so it's obvious which row the chart is tracking. */
#movement-leaderboard tr.vt-movement-row {
    cursor: pointer;
}

#movement-leaderboard tr.vt-row-focused {
    background: var(--kb-primary-muted);
    box-shadow: inset 3px 0 0 0 var(--kb-primary);
}

#movement-leaderboard tr.vt-row-focused > td {
    background: transparent;
}

.config-mod {
    font-size: 0.7rem;
    color: var(--kb-text-muted);
}

#all-matches-view {
    display: none;
}

/* ============================================================================
   FULLSCREEN BUTTONS — Borderless icon style
   ============================================================================ */

[data-expand] {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    color: var(--kb-text-muted);
    padding: 0.375rem;
    border-radius: 6px;
    transition: color 0.2s ease, background-color 0.2s ease;
}

[data-expand]:hover {
    color: var(--kb-text-primary);
    background: var(--kb-bg-muted) !important;
}

[data-expand]:focus {
    box-shadow: none !important;
}

/* ============================================================================
   EFFECT CUSTOM PROPERTIES — --vt-* namespace
   Controls visual effects; --kb-* controls colors
   ============================================================================ */

:root {
    /* Glass */
    --vt-glass-blur: 14px;
    --vt-glass-opacity: 87%;
    --vt-glass-border-luminance: 8%;

    /* Depth — multi-layer shadow tokens */
    --vt-shadow-elevation-1:
        0 1px 2px rgba(0, 0, 0, 0.12),
        0 4px 8px rgba(0, 0, 0, 0.08);
    --vt-shadow-elevation-2:
        0 2px 4px rgba(0, 0, 0, 0.12),
        0 8px 24px rgba(0, 0, 0, 0.12);
    --vt-shadow-elevation-3:
        0 4px 8px rgba(0, 0, 0, 0.12),
        0 16px 48px rgba(0, 0, 0, 0.16);

    /* Animation */
    --vt-anim-stagger: 50ms;
    --vt-anim-duration: 0.4s;
    --vt-anim-ease: cubic-bezier(0.16, 1, 0.3, 1);

    /* Chart effects */
    --vt-chart-shadow-blur: 5px;
    --vt-chart-shadow-opacity: 0.12;

    /* Ambient background */
    --vt-ambient-opacity: 0.06;
}

/* Light mode — same effects, reduced intensity */
[data-mode="light"] {
    --vt-glass-blur: 10px;
    --vt-glass-opacity: 92%;
    --vt-glass-border-luminance: 5%;

    --vt-shadow-elevation-1:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 4px 8px rgba(0, 0, 0, 0.04);
    --vt-shadow-elevation-2:
        0 2px 4px rgba(0, 0, 0, 0.06),
        0 8px 24px rgba(0, 0, 0, 0.06);
    --vt-shadow-elevation-3:
        0 4px 8px rgba(0, 0, 0, 0.06),
        0 16px 48px rgba(0, 0, 0, 0.08);

    --vt-ambient-opacity: 0.03;
    --vt-chart-shadow-blur: 3px;
    --vt-chart-shadow-opacity: 0.06;
}

/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    :root {
        --vt-anim-duration: 0s;
        --vt-anim-stagger: 0ms;
    }
}

/* ============================================================================
   AMBIENT BACKGROUND
   Two soft radial gradient washes — adapts to active theme palette
   ============================================================================ */

body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(ellipse 60% 50% at 10% 90%,
            color-mix(in oklab, var(--kb-primary) 6%, transparent),
            transparent 60%),
        radial-gradient(ellipse 50% 60% at 85% 15%,
            color-mix(in oklab, var(--kb-accent) 6%, transparent),
            transparent 60%);
}

[data-mode="light"] body::before {
    background:
        radial-gradient(ellipse 60% 50% at 10% 90%,
            color-mix(in oklab, var(--kb-primary) 3%, transparent),
            transparent 60%),
        radial-gradient(ellipse 50% 60% at 85% 15%,
            color-mix(in oklab, var(--kb-accent) 3%, transparent),
            transparent 60%);
}

/* ============================================================================
   GLASS SURFACES
   Translucent backgrounds with backdrop blur on primary surfaces
   ============================================================================ */

.card {
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent) !important;
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent) !important;
    box-shadow: var(--vt-shadow-elevation-1),
        inset 0 1px 0 color-mix(in oklab, white, transparent 92%) !important;
    transition: transform 0.25s var(--vt-anim-ease), box-shadow 0.25s var(--vt-anim-ease) !important;
}

.card:hover {
    box-shadow: var(--vt-shadow-elevation-2),
        inset 0 1px 0 color-mix(in oklab, white, transparent 88%) !important;
    transform: translateY(-2px);
    border-color: color-mix(in oklab, var(--kb-text-primary) 12%, transparent) !important;
}

.navbar {
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent) !important;
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent) !important;
}

.modal-content {
    background: color-mix(in oklab, var(--kb-bg-card) 92%, transparent) !important;
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    box-shadow: var(--vt-shadow-elevation-3);
}

.dropdown-menu {
    background: color-mix(in oklab, var(--kb-bg-card) 92%, transparent) !important;
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    box-shadow: var(--vt-shadow-elevation-2);
}

/* Light mode: flip inset shadow from light edge to subtle dark edge */
[data-mode="light"] .card {
    box-shadow: var(--vt-shadow-elevation-1),
        inset 0 1px 0 color-mix(in oklab, black, transparent 96%);
}

[data-mode="light"] .card:hover {
    box-shadow: var(--vt-shadow-elevation-2),
        inset 0 1px 0 color-mix(in oklab, black, transparent 94%);
}

/* ============================================================================
   NAV-PILLS — Glass-styled tab navigation
   ============================================================================ */

#match-tabs,
#all-tabs {
    background: color-mix(in oklab, var(--kb-bg-card) 60%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 10px;
    padding: 0.375rem;
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) 5%, transparent);
}

#match-tabs .nav-link,
#all-tabs .nav-link {
    color: var(--kb-text-secondary);
    font-weight: 500;
    font-size: 0.875rem;
    padding: 0.5rem 1rem;
    border-radius: 8px;
    transition: color 0.2s ease, background-color 0.2s ease;
}

#match-tabs .nav-link:hover,
#all-tabs .nav-link:hover {
    color: var(--kb-text-primary);
    background: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
}

#match-tabs .nav-link.active,
#all-tabs .nav-link.active {
    background: var(--kb-primary) !important;
    color: var(--kb-primary-fg) !important;
    box-shadow: 0 2px 8px color-mix(in oklab, var(--kb-primary), transparent 60%);
}

/* ============================================================================
   TABLE ROW HOVER — Subtle left-border indicator + text color fix
   ============================================================================ */

.table {
    --bs-table-hover-color: var(--kb-text-primary);
    --bs-table-hover-bg: var(--kb-bg-muted);
}

.table > tbody > tr {
    position: relative;
    transition: background-color 0.15s ease;
    color: var(--kb-text-primary);
}

.table > tbody > tr:hover {
    color: var(--kb-text-primary) !important;
}

.table > tbody > tr:hover td {
    color: inherit;
}

.table > tbody > tr::after {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--kb-primary);
    opacity: 0;
    transition: opacity 0.2s ease;
}

.table > tbody > tr:hover::after {
    opacity: 0.7;
}

/* ============================================================================
   RIVALRY CARD — Glass treatment
   ============================================================================ */

.rivalry-card {
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent) !important;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent) !important;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.rivalry-card:hover {
    transform: translateY(-1px);
    box-shadow: var(--vt-shadow-elevation-1);
}

/* ============================================================================
   ANIMATION KEYFRAMES
   ============================================================================ */

@keyframes vt-card-enter {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.vt-enter {
    animation: vt-card-enter var(--vt-anim-duration) var(--vt-anim-ease) both;
    animation-delay: var(--vt-delay, 0ms);
}

/* Scroll-triggered reveal (fallback for non-tab content) */
.vt-scroll-reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity var(--vt-anim-duration) var(--vt-anim-ease),
                transform var(--vt-anim-duration) var(--vt-anim-ease);
}

.vt-scroll-reveal.vt-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Tab content fade transition enhancement */
.tab-pane.fade {
    transition: opacity 0.2s ease;
}

/* ============================================================================
   ERROR PANEL — Shown in place of the preloader when a shareable URL
   references a match that no longer exists. Provides a picker to recover.
   ============================================================================ */

.vt-error-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    min-height: 60vh;
    text-align: center;
    padding: 1.5rem;
}

.vt-error-icon {
    font-size: 2.5rem;
    color: var(--kb-warning);
    line-height: 1;
}

.vt-error-title {
    font-family: 'Geist', sans-serif;
    font-weight: 600;
    font-size: 1.15rem;
    color: var(--kb-text-primary);
    letter-spacing: -0.01em;
}

.vt-error-detail {
    font-size: 0.85rem;
    color: var(--kb-text-muted);
}

.vt-error-detail code {
    font-family: 'Geist Mono', ui-monospace, Menlo, Consolas, monospace;
    padding: 0.2em 0.5em;
    border-radius: 4px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 80%, transparent);
    color: var(--kb-primary);
}

.vt-error-action {
    margin-top: 0.5rem;
}

/* ============================================================================
   PRELOADER STYLES
   ============================================================================ */

.vt-preloader {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    gap: 1.25rem;
}

.vt-preloader-ring {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: 3px solid color-mix(in oklab, var(--kb-primary), transparent 75%);
    border-top-color: var(--kb-primary);
    animation: vt-spin 0.8s linear infinite;
}

@keyframes vt-spin {
    to { transform: rotate(360deg); }
}

.vt-preloader-brand {
    font-family: 'Geist', sans-serif;
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: -0.02em;
    color: var(--kb-text-primary);
}

.vt-preloader-status {
    font-size: 0.875rem;
    color: var(--kb-text-muted);
}

/* Preloader fade-out */
.vt-preloader.vt-fade-out {
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
}

/* ============================================================================
   TOPNAV ICON BUTTONS
   Borderless, lone-icon style for lightweight nav controls (Docs, Theme,
   Mode). Muted by default; brighten + subtle backdrop on hover/active.
   Kept separate from Bootstrap's btn system so there's no default padding,
   border, or background-color fight.
   ============================================================================ */

.vt-nav-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    padding: 0.375rem 0.5rem;
    background: transparent;
    border: none;
    border-radius: 6px;
    color: var(--kb-text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.2s ease, background-color 0.2s ease;
}

.vt-nav-icon-btn:hover,
.vt-nav-icon-btn:focus-visible {
    color: var(--kb-text-primary);
    background-color: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
    outline: none;
}

.vt-nav-icon-btn.active,
.vt-nav-icon-btn[aria-current="page"] {
    color: var(--kb-primary);
}

/* Suppress Bootstrap's dropdown-toggle ::after caret when we're using the
   borderless nav-icon treatment (the palette button shows icon only). */
.vt-nav-icon-btn.dropdown-toggle::after,
.dropdown > .vt-nav-icon-btn::after {
    display: none !important;
}

/* Primary-tinted variant of .vt-nav-icon-btn — used for high-emphasis
   actions in the topnav (e.g. #record-stats-btn-desktop / -mobile).
   Mirrors the visual weight of .btn-primary while keeping the topnav's
   sizing and typography. Specificity matches the base .vt-nav-icon-btn
   hover/focus rules above; defined later in source so it wins. */
.vt-nav-icon-btn--primary {
    background: var(--kb-primary);
    color: var(--kb-primary-fg);
    box-shadow: 0 2px 10px var(--kb-primary-muted);
}

.vt-nav-icon-btn--primary:hover,
.vt-nav-icon-btn--primary:focus-visible {
    background: var(--kb-primary-hover);
    color: var(--kb-primary-fg);
    box-shadow: 0 4px 14px var(--kb-primary-muted);
}

.vt-nav-icon-btn--primary:active {
    filter: brightness(0.95);
    box-shadow: 0 1px 6px var(--kb-primary-muted);
}

/* ============================================================================
   TOPNAV URL-SYNC BUTTONS
   Share (one-shot copy) + Live Sync (toggle). Both render as standalone
   .vt-nav-icon-btn buttons (borderless, transparent) so they match the
   rest of the topnav. The base .vt-nav-icon-btn rule above already supplies
   the color/background transitions; these per-id rules only encode the
   stateful color tints (Live Sync .active, Share flash-success/error).
   ============================================================================ */

/* Live Sync "on" state — soft primary tint, painted on top of the
   borderless base button. */
#live-sync-toggle.active {
    color: var(--kb-primary);
    background-color: color-mix(in oklab, var(--kb-primary) 14%, transparent);
}

#share-url-btn.flash-success {
    color: var(--kb-success);
    background-color: color-mix(in oklab, var(--kb-success) 14%, transparent);
}

#share-url-btn.flash-error {
    color: var(--kb-danger);
    background-color: color-mix(in oklab, var(--kb-danger) 14%, transparent);
}

/* ============================================================================
   ACTIVE GAME INDICATOR
   Topnav widget that polls the live BZ2 lobby and surfaces a pulsing LIVE
   pill whenever a session hosted by an allowlisted Steam64 ID is active.
   Markup: #vt-active-game (Bootstrap dropdown wrapper) -> #vt-active-game-pill
   (state-driven trigger) + #vt-active-game-dropdown (multi-match list) +
   #vt-active-game-join (single-match shortcut) + .vt-active-game-gamewatch
   (always-visible external link). State drives via [data-state] on the
   wrapper: "loading" | "no-match" | "match-found-1" | "match-found-n".
   See js/active-game-indicator.js.
   ============================================================================ */

.vt-active-game {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-left: 0.5rem;
}

/* Base pill: borderless nav-icon style with optional success-tinted bg
   when a match is live. Disabled in loading/no-match states. */
.vt-active-game-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.375rem 0.6rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--kb-text-secondary);
    font-size: 0.825rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: color 0.2s ease, background-color 0.2s ease,
                border-color 0.2s ease, transform 0.2s ease;
    font-feature-settings: "tnum" 1;
}

.vt-active-game-pill:hover:not(:disabled),
.vt-active-game-pill:focus-visible:not(:disabled) {
    color: var(--kb-text-primary);
    background-color: color-mix(in oklab, var(--kb-success) 18%, transparent);
    border-color: color-mix(in oklab, var(--kb-success) 36%, transparent);
    outline: none;
}

.vt-active-game-pill:disabled {
    cursor: default;
    opacity: 0.7;
}

.vt-active-game-pill::after {
    display: none !important;
}

/* Pulsing LIVE dot. Sits flush left of the pill text. Animation honors
   prefers-reduced-motion: collapses to a static dot. */
.vt-active-game-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--kb-success);
    box-shadow: 0 0 0 0 color-mix(in oklab, var(--kb-success) 50%, transparent);
    animation: vtActiveGamePulse 2.2s ease-in-out infinite;
}

@keyframes vtActiveGamePulse {
    0%   { box-shadow: 0 0 0 0   color-mix(in oklab, var(--kb-success) 55%, transparent); }
    70%  { box-shadow: 0 0 0 7px color-mix(in oklab, var(--kb-success) 0%,  transparent); }
    100% { box-shadow: 0 0 0 0   color-mix(in oklab, var(--kb-success) 0%,  transparent); }
}

@media (prefers-reduced-motion: reduce) {
    .vt-active-game-dot {
        animation: none;
    }
}

.vt-active-game-pill-label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.vt-active-game-pill-text {
    color: var(--kb-success);
    letter-spacing: 0.04em;
}

.vt-active-game-pill-host {
    color: var(--kb-text-primary);
    font-weight: 600;
    max-width: 18ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-active-game-pill-count {
    color: var(--kb-text-secondary);
    font-weight: 500;
}

/* Loading skeleton: tiny shimmering bar inside the pill. */
.vt-active-game-pill-skeleton {
    display: inline-block;
    width: 12px;
    height: 8px;
    border-radius: 4px;
    background: linear-gradient(90deg,
        color-mix(in oklab, var(--kb-bg-muted) 60%, transparent) 0%,
        color-mix(in oklab, var(--kb-bg-muted) 100%, transparent) 50%,
        color-mix(in oklab, var(--kb-bg-muted) 60%, transparent) 100%);
    background-size: 200% 100%;
    animation: vtActiveGameShimmer 1.6s linear infinite;
}

@keyframes vtActiveGameShimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .vt-active-game-pill-skeleton { animation: none; }
}

/* Multi-match dropdown menu styling. Uses the standard Bootstrap dropdown
   surface but each item is a 4-column flex row. */
.vt-active-game-dropdown {
    min-width: 320px;
    padding: 0.25rem 0;
}

.vt-active-game-dropdown-item {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.3fr) auto auto;
    gap: 0.55rem;
    align-items: center;
    width: 100%;
    padding: 0.5rem 0.85rem;
    font-size: 0.825rem;
    text-align: left;
}

.vt-active-game-dropdown-host {
    color: var(--kb-text-primary);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-active-game-dropdown-map {
    color: var(--kb-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-active-game-dropdown-count {
    color: var(--kb-text-secondary);
    font-weight: 500;
    font-feature-settings: "tnum" 1;
    font-variant-numeric: tabular-nums;
}

/* Join + GameWatch buttons. Borderless, mirror .vt-nav-icon-btn weight.
   Pill-shaped (border-radius 999px) to match the LIVE pill alongside;
   padding + font-size are kept in lockstep with .vt-active-game-pill so
   all three siblings render at the same height. */
.vt-active-game-join,
.vt-active-game-gamewatch {
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 0.6rem;
    border-radius: 999px;
    font-size: 0.825rem;
    font-weight: 600;
    text-decoration: none;
    line-height: 1;
    transition: color 0.2s ease, background-color 0.2s ease;
}

.vt-active-game-join {
    background-color: var(--kb-success);
    color: var(--kb-primary-fg);
    box-shadow: 0 2px 8px color-mix(in oklab, var(--kb-success) 30%, transparent);
}

.vt-active-game-join:hover,
.vt-active-game-join:focus-visible {
    background-color: color-mix(in oklab, var(--kb-success) 88%, white);
    color: var(--kb-primary-fg);
    outline: none;
}

.vt-active-game-join--locked {
    background-color: color-mix(in oklab, var(--kb-bg-muted) 70%, transparent);
    color: var(--kb-text-muted);
    box-shadow: none;
    pointer-events: none;
}

.vt-active-game-gamewatch {
    background: transparent;
    color: var(--kb-text-secondary);
    border: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 35%);
}

.vt-active-game-gamewatch:hover,
.vt-active-game-gamewatch:focus-visible {
    color: var(--kb-text-primary);
    background-color: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
    outline: none;
}

/* State-driven visibility. Done with attribute selectors so the JS only
   has to flip data-state on the wrapper. */
.vt-active-game[data-state="loading"] .vt-active-game-pill {
    opacity: 0.85;
}

.vt-active-game[data-state="no-match"] #vt-active-game-pill,
.vt-active-game[data-state="no-match"] #vt-active-game-join {
    display: none !important;
}

.vt-active-game[data-state="match-found-1"] .vt-active-game-pill,
.vt-active-game[data-state="match-found-n"] .vt-active-game-pill {
    background-color: color-mix(in oklab, var(--kb-success) 12%, transparent);
    border-color: color-mix(in oklab, var(--kb-success) 28%, transparent);
}

/* Hide the topnav GameWatch button whenever a live match is found —
   the GameWatch link stays accessible from the modal footer. The button
   is only relevant in no-match state as a "no live games, browse the
   broader scrapfield catalog" affordance. */
.vt-active-game[data-state="match-found-1"] .vt-active-game-gamewatch,
.vt-active-game[data-state="match-found-n"] .vt-active-game-gamewatch {
    display: none !important;
}

/* Clickability cue: chevron at the tail of the single-match pill +
   subtle lift on hover. Multi-match pill keeps its existing chevron-
   down (dropdown semantic); this chevron-right (drill-in semantic) is
   only emitted from renderMatchFound1(). */
.vt-active-game-pill-chevron {
    color: var(--kb-text-muted);
    font-size: 0.85em;
    margin-left: 0.15rem;
    opacity: 0.7;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.vt-active-game-pill:hover:not(:disabled) {
    transform: translateY(-1px);
}

.vt-active-game-pill:hover:not(:disabled) .vt-active-game-pill-chevron {
    opacity: 1;
    transform: translateX(2px);
}

@media (prefers-reduced-motion: reduce) {
    .vt-active-game-pill,
    .vt-active-game-pill-chevron { transition: none; }
    .vt-active-game-pill:hover:not(:disabled) { transform: none; }
    .vt-active-game-pill:hover:not(:disabled) .vt-active-game-pill-chevron {
        transform: none;
    }
}

/* Compact-mode segments (mobile) — hidden by default on desktop, swapped
   in by the breakpoint below. */
.vt-active-game-pill-loading-compact,
.vt-active-game-pill-multi-compact {
    display: none;
}

/* Mobile compact mode: hide the host name segment + the GameWatch label
   (icon-only chip), and hide the standalone Join button entirely (it
   remains accessible from the modal footer). */
@media (max-width: 767.98px) {
    .vt-active-game {
        margin-left: 0.25rem;
        gap: 0.25rem;
    }
    .vt-active-game-pill-host {
        display: none;
    }
    .vt-active-game-pill-loading-full,
    .vt-active-game-pill-multi-full {
        display: none;
    }
    .vt-active-game-pill-loading-compact,
    .vt-active-game-pill-multi-compact {
        display: inline;
    }
    .vt-active-game-gamewatch-label {
        display: none;
    }
    .vt-active-game[data-state="match-found-1"] #vt-active-game-join,
    .vt-active-game[data-state="match-found-n"] #vt-active-game-join {
        display: none !important;
    }
}

/* ============================================================================
   ACTIVE GAME MODAL
   Click-through detail card mirroring the bz2api demo: header badges
   (state, mode, VSR) -> map thumbnail + map line + host -> player table
   with HOST/CMDR badges + Steam profile + VTstats deep-link chips ->
   session stats grid -> mods row -> footer (Join, GameWatch, Close).
   Body markup is rendered by js/active-game-indicator.js on
   shown.bs.modal so a closed modal carries no per-session DOM cost.
   ============================================================================ */

.vt-active-game-modal-title {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.vt-active-game-modal-title-text {
    font-weight: 600;
}

.vt-active-game-modal-title-badges {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.vt-active-game-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background-color: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
    color: var(--kb-text-secondary);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.2;
}

.vt-active-game-badge--ingame {
    background-color: color-mix(in oklab, var(--kb-success) 16%, transparent);
    color: var(--kb-success);
}

.vt-active-game-badge--pregame {
    background-color: color-mix(in oklab, var(--kb-warning, #d4a017) 18%, transparent);
    color: var(--kb-warning, #d4a017);
}

.vt-active-game-badge--vsr {
    background-color: color-mix(in oklab, var(--kb-primary) 16%, transparent);
    color: var(--kb-primary);
}

.vt-active-game-badge--host {
    background-color: color-mix(in oklab, var(--kb-success) 14%, transparent);
    color: var(--kb-success);
}

.vt-active-game-badge--cmdr {
    background-color: color-mix(in oklab, var(--kb-primary) 14%, transparent);
    color: var(--kb-primary);
}

.vt-active-game-modal-summary {
    display: grid;
    grid-template-columns: minmax(140px, 200px) 1fr;
    gap: 1rem;
    align-items: center;
    margin-bottom: 1rem;
}

@media (max-width: 575.98px) {
    .vt-active-game-modal-summary {
        grid-template-columns: 1fr;
    }
}

.vt-active-game-modal-thumb {
    aspect-ratio: 1 / 1;
    width: 100%;
    border-radius: 8px;
    overflow: hidden;
    background-color: color-mix(in oklab, var(--kb-bg-muted) 80%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
}

.vt-active-game-modal-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.vt-active-game-modal-thumb-missing {
    visibility: hidden;
}

.vt-active-game-modal-thumb-placeholder {
    color: var(--kb-text-muted);
    font-size: 1.6rem;
}

.vt-active-game-modal-summary-meta {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

.vt-active-game-modal-mapline {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--kb-text-primary);
}

.vt-active-game-modal-mapline a {
    color: inherit;
    text-decoration: none;
}

.vt-active-game-modal-mapline a:hover {
    text-decoration: underline;
}

.vt-active-game-modal-host,
.vt-active-game-modal-count {
    color: var(--kb-text-secondary);
    font-size: 0.875rem;
}

/* Host is the single most identifying piece of info on the modal
   (the player you're about to join). The summary line carries the
   weight that the per-row HOST badge previously did, so the host
   name itself gets the primary accent color + a slight size bump. */
.vt-active-game-modal-host strong {
    color: var(--kb-primary);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.01em;
}

.vt-active-game-modal-section {
    margin-top: 1.1rem;
}

.vt-active-game-modal-section-title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--kb-text-muted);
    margin-bottom: 0.5rem;
}

.vt-active-game-modal-players {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

/* Two-column TEAM 1 / TEAM 2 layout for team-based modes (STRAT/MPI/
   Team-DM/etc., gated by session.isTeamGame in js/active-game-indicator.js).
   Falls back to a single column on narrow viewports so player rows stay
   legible. The flat single-list layout is kept for FFA/DM modes. */
.vt-active-game-modal-teams {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
}

@media (max-width: 575.98px) {
    .vt-active-game-modal-teams {
        grid-template-columns: 1fr;
    }
}

.vt-active-game-modal-team-column {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

.vt-active-game-modal-team-header {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--kb-text-muted);
    padding-left: 0.65rem;
    margin-bottom: 0.15rem;
}

.vt-active-game-modal-team-empty {
    color: var(--kb-text-muted);
    font-size: 0.85rem;
    font-style: italic;
    padding: 0.45rem 0.65rem;
}

.vt-active-game-modal-player-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.6rem;
    align-items: center;
    padding: 0.45rem 0.65rem;
    border-radius: 6px;
    background-color: color-mix(in oklab, var(--kb-bg-muted) 28%, transparent);
    border-left: 3px solid transparent;
}

.vt-active-game-modal-player-row--team1,
.vt-active-game-modal-player-row--team2 {
    border-left-color: color-mix(in oklab, var(--kb-primary) 70%, transparent);
}

.vt-active-game-modal-player-badges {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-width: 0;
}

.vt-active-game-modal-player-badges:empty {
    display: none;
}

.vt-active-game-modal-player-name {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-width: 0;
}

.vt-active-game-modal-player-nick {
    font-weight: 600;
    color: var(--kb-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.vt-active-game-modal-player-chips {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}

.vt-active-game-modal-player-stats {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-feature-settings: "tnum" 1;
    font-variant-numeric: tabular-nums;
    color: var(--kb-text-secondary);
    font-size: 0.875rem;
    font-weight: 600;
}

.vt-active-game-modal-player-stat-sep {
    color: var(--kb-text-muted);
}

/* Inline link chip used for the Steam profile link on each player row,
   and the mod-link chips in the Mods row. */
.vt-active-game-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background-color: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
    color: var(--kb-text-secondary);
    font-size: 0.7rem;
    font-weight: 500;
    text-decoration: none;
    line-height: 1.4;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.vt-active-game-chip:hover,
.vt-active-game-chip:focus-visible {
    color: var(--kb-text-primary);
    background-color: color-mix(in oklab, var(--kb-primary) 14%, transparent);
    outline: none;
}

.vt-active-game-chip--static {
    pointer-events: none;
}

.vt-active-game-chip i {
    font-size: 0.75em;
    line-height: 1;
}

/* Icon-only variant: square-ish, no text, used for the per-player-row
   Steam profile link where the bi-steam glyph alone carries the meaning.
   The base .vt-active-game-chip uses 0.7rem font-size to size text + a
   0.75em <i> rule to keep glyphs proportionate; icon-only mode bumps the
   chip up to 1rem and resets the inner glyph to 1em (declared AFTER the
   generic .vt-active-game-chip i rule so it wins on source order, since
   both selectors carry equal specificity). */
.vt-active-game-chip--icon {
    padding: 0.25rem 0.45rem;
    gap: 0;
    font-size: 1rem;
}

.vt-active-game-chip--icon i {
    font-size: 1em;
    line-height: 1;
}

/* Stats grid: two rows of four cells on desktop, collapses to two columns
   on mobile. Mirrors the kb-style stat tile look used elsewhere. */
.vt-active-game-modal-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.5rem;
}

@media (max-width: 575.98px) {
    .vt-active-game-modal-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.vt-active-game-stat {
    padding: 0.5rem 0.7rem;
    background-color: color-mix(in oklab, var(--kb-bg-muted) 30%, transparent);
    border-radius: 6px;
    min-width: 0;
}

.vt-active-game-stat-label {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--kb-text-muted);
    margin-bottom: 0.15rem;
}

.vt-active-game-stat-value {
    color: var(--kb-text-primary);
    font-weight: 600;
    font-size: 0.95rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-active-game-modal-mods {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

/* ============================================================================
   IN-GAME NICK SUBTEXT
   Subtle alias rendered alongside the canonical/known player name when the
   two differ. Pipeline emits `in_game_nick` (null when names match
   case-insensitively); UI checks truthiness and renders one of these two
   variants. Used in: leaderboard rows (block sub), faction roster (inline),
   and kill feed entries (inline).
   ============================================================================ */

.vt-nick-sub,
.vt-nick-inline {
    color: var(--kb-text-muted);
    font-size: 0.72rem;
    font-weight: 400;
    opacity: 0.85;
}

.vt-nick-sub {
    display: block;
    margin-top: -2px;
}

.vt-nick-inline {
    margin-left: 0.35em;
}

/* Kill-feed weapon ODF chip — clickable into the ODF Browser
   (odf/index.html?odf=<basename>). Defined here (not in
   css/odf-browser.css) so the dashboard, which doesn't load the ODF
   browser stylesheet, picks it up. The .vt-odf-link-fallback variant
   covers the rare edge case where the resolver returned a name from
   somewhere but the raw entry.killer_odf / entry.victim_odf is empty
   so we can't build a meaningful URL. */
.vt-odf-link {
    color: var(--kb-text-muted);
    font-size: 0.75rem;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.15s ease, text-decoration-color 0.15s ease;
}

.vt-odf-link:hover {
    color: var(--kb-primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.vt-odf-link-fallback {
    color: var(--kb-text-muted);
    font-size: 0.75rem;
}

/* Used by Phase 3 cards (Snipe Feed, Powerup/Crate Destruction Breakdown) to fully
   hide a card+grid-column when its data is empty, so the surrounding row
   layout collapses cleanly. */
.vt-hide {
    display: none !important;
}

/* ============================================================================
   GLOBAL FILTER BAR
   Player/team filter controls inside the match-info banner
   Positioned as a right-side column, separated from metadata by a vertical rule
   ============================================================================ */

.vt-filter-bar--right {
    border-left: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
    padding-left: 1.25rem;
    margin-left: auto;
    min-width: 260px;
}

.vt-filter-bar-label {
    margin-bottom: 0.4rem;
}

/* Collapse to stacked layout below md so the filter slides beneath metadata */
@media (max-width: 767.98px) {
    .vt-filter-bar--right {
        border-left: none;
        border-top: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
        padding-left: 0;
        padding-top: 0.75rem;
        margin-left: 0;
        width: 100%;
    }
}

#filter-mode .btn {
    font-size: 0.8rem;
    font-weight: 500;
    padding: 0.3rem 0.75rem;
}

#filter-mode .btn.active {
    background: var(--kb-primary) !important;
    border-color: var(--kb-primary) !important;
    color: var(--kb-primary-fg) !important;
}

/* --- Player picker dropdown --- */

.vt-player-picker {
    min-width: 240px;
    max-height: 360px;
    overflow-y: auto;
    padding: 0.5rem;
    background: color-mix(in oklab, var(--kb-bg-card) 96%, transparent);
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent);
    border-radius: 8px;
    box-shadow: var(--vt-shadow-elevation-3);
}

/* Floating variant — appended to <body>, positioned manually so it can
   escape any ancestor with backdrop-filter (which would otherwise trap
   even position: fixed descendants). */
.vt-player-picker--floating {
    position: fixed;
    z-index: 1080;
    display: none;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.vt-player-picker--floating.show {
    display: block;
    opacity: 1;
    transform: translateY(0);
}

.vt-player-picker .vt-player-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.82rem;
    color: var(--kb-text-secondary);
    transition: background-color 0.15s ease, color 0.15s ease;
}

.vt-player-picker .vt-player-option:hover {
    background: color-mix(in oklab, var(--kb-bg-muted) 60%, transparent);
    color: var(--kb-text-primary);
}

.vt-player-picker .vt-player-option input[type="checkbox"] {
    flex-shrink: 0;
}

.vt-player-picker .vt-team-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.vt-player-picker .vt-team-dot--t1 {
    background: var(--kb-primary);
}

.vt-player-picker .vt-team-dot--t2 {
    background: var(--kb-accent);
}

/* --- Player profile card --- */

.vt-profile-panel {
    padding: 1.5rem;
    border-radius: 10px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 80%, transparent);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-left-width: 3px;
    border-left-style: solid;
}

.vt-profile-panel .vt-profile-name {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--kb-text-primary);
}

.vt-profile-panel .stat-value {
    font-size: 1.5rem;
}

.vt-profile-rival {
    padding: 0.75rem;
    border-radius: 8px;
    background: color-mix(in oklab, var(--kb-bg-card) 70%, transparent);
    border: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 50%);
}

.vt-profile-chart-wrap {
    width: 120px;
    height: 120px;
}

/* Player Performance Radar wrapper inside the Overview profile panel.
   Square aspect, a touch larger than the adjacent doughnut so the 7-axis
   shape is readable without crowding the stat cards. */
.vt-profile-radar-wrap {
    width: 220px;
    height: 220px;
    position: relative;
}

.vt-profile-radar-wrap canvas {
    max-width: 100%;
    max-height: 100%;
}

/* Inline info icon overlayed on the Profile Radar. The radar wrap is small
   (220px) and has no header, so the icon sits in the top-right corner with
   a subtle hover lift to flag that hovering shows the axis legend. */
.vt-profile-radar-info {
    position: absolute;
    top: 4px;
    right: 4px;
    z-index: 2;
    cursor: help;
    opacity: 0.65;
    transition: opacity 0.15s ease-in-out;
}

.vt-profile-radar-info:hover {
    opacity: 1;
}

/* ============================================================================
   PLAYER PERFORMANCE RADAR — card-level styling
   Clickable top-rivalry drill-down, Custom... picker, empty-state hints.
   ============================================================================ */

/* Clickable rivalry card (drives the compare-mode Rivalry Radar). */
.vt-rivalry-card--interactive {
    cursor: pointer;
    outline: none;
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.vt-rivalry-card--interactive:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in oklab, var(--kb-primary) 55%, transparent);
}

.vt-rivalry-card--interactive.is-active {
    border-color: var(--kb-primary) !important;
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--kb-primary) 35%, transparent),
                var(--vt-shadow-elevation-1);
}

.vt-rivalry-card--interactive.is-active::after {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--kb-primary);
    margin-left: 0.5rem;
    align-self: center;
}

/* Custom... dropdown block inside the Rivalry / Career Radar cards. */
/* Chip-based two-slot rivalry picker (replaces the old dual-select picker).
   Each slot is a Bootstrap dropdown trigger; menu list is populated
   dynamically by populateRivalryPickerMenu() in js/app.js. */

.vt-radar-picker {
    padding: 0.5rem 0.75rem;
    border-radius: 8px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 65%, transparent);
    border: 1px solid var(--kb-border-subtle);
}

.vt-radar-picker-slots {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.vt-radar-picker-dropdown {
    /* Wrapper for each slot trigger + menu. The Bootstrap .dropdown class
       handles toggle plumbing. */
}

.vt-radar-picker-slot {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    padding: 0.45rem 1.85rem 0.45rem 0.85rem;
    min-width: 180px;
    border: 1px solid var(--kb-border-subtle);
    border-radius: 8px;
    background: color-mix(in oklab, var(--kb-bg-card) 80%, transparent);
    color: var(--kb-text-primary);
    cursor: pointer;
    position: relative;
    text-align: left;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}

.vt-radar-picker-slot:hover,
.vt-radar-picker-slot:focus-visible,
.vt-radar-picker-slot[aria-expanded="true"] {
    border-color: var(--kb-primary);
    outline: none;
    background: color-mix(in oklab, var(--kb-bg-card) 95%, transparent);
}

.vt-radar-picker-slot-label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--kb-text-muted);
    font-weight: 600;
}

.vt-radar-picker-slot-name {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--kb-text-primary);
    line-height: 1.2;
    max-width: 16ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Faction-tinted name color to telegraph which side of the comparison
   each slot represents. */
.vt-radar-picker-slot[data-faction="1"] .vt-radar-picker-slot-name {
    color: var(--kb-primary);
}

.vt-radar-picker-slot[data-faction="2"] .vt-radar-picker-slot-name {
    color: var(--kb-accent);
}

/* Empty slot: muted/italic placeholder so it reads as "click to pick". */
.vt-radar-picker-slot[data-empty="true"] .vt-radar-picker-slot-name {
    color: var(--kb-text-muted);
    font-style: italic;
    font-weight: 400;
}

.vt-radar-picker-slot-caret {
    position: absolute;
    right: 0.65rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.85rem;
    color: var(--kb-text-muted);
}

.vt-radar-picker-vs {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--kb-text-muted);
    text-transform: lowercase;
    letter-spacing: 0.06em;
    padding: 0 0.15rem;
}

.vt-radar-picker-menu {
    max-height: 320px;
    overflow-y: auto;
    min-width: 200px;
}

.vt-radar-picker-menu .dropdown-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.vt-radar-picker-menu .dropdown-item.is-current i {
    color: var(--kb-success);
}

.vt-radar-picker-action {
    /* Inherits btn-outline-secondary; just keep alignment honest. */
    align-self: stretch;
}

/* Toggle button "active" state for Custom... / Compare. */
.vt-radar-custom-toggle.active,
.vt-radar-custom-toggle.active:hover,
.vt-radar-custom-toggle.active:focus {
    background: color-mix(in oklab, var(--kb-primary) 18%, transparent);
    border-color: color-mix(in oklab, var(--kb-primary) 55%, transparent);
    color: var(--kb-text-primary);
}

/* Inline hint paragraph shown below the radar in edge cases (same player
   picked twice, too few players to compare, etc.). */
.vt-radar-hint {
    color: var(--kb-text-muted);
    text-align: center;
}

/* Radar charts are intrinsically square. Centre the canvas within its wide
   chart-container so a 7-axis spiderweb stays readable instead of stretching
   into an ellipse. Fullscreen modals have their own sizing and bypass this. */
#section-rivalry-radar .chart-container,
#section-faction-radar .chart-container,
#section-career-radar .chart-container {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 380px;
}

#section-rivalry-radar .chart-container > canvas,
#section-faction-radar .chart-container > canvas,
#section-career-radar .chart-container > canvas {
    max-width: 480px;
    max-height: 380px;
}

/* ============================================================================
   FACTION SCOREBOARD — Hero Treatment
   First visual in the Overview tab — elevated presentation
   ============================================================================ */

#section-faction .card-body {
    padding: 1.5rem;
}

.vt-faction-panel {
    padding: 1.5rem;
    border-radius: 0;
    background: color-mix(in oklab, var(--kb-bg-subtle) 80%, transparent);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-left-width: 5px;
    border-left-style: solid;
    transition: box-shadow 0.2s ease;
}

.vt-faction-panel:hover {
    box-shadow: var(--vt-shadow-elevation-1);
}

.vt-faction-panel .stat-value {
    font-size: 1.75rem;
    font-weight: 700;
}

.vt-faction-panel .stat-label {
    margin-top: 0.125rem;
}

/* Muted state — team is outside the current filter scope.
   Kept visible for context but clearly deprioritized. */
.vt-faction-panel--muted {
    position: relative;
    opacity: 0.55;
    filter: saturate(0.4);
    transition: opacity 0.2s ease, filter 0.2s ease;
}

.vt-faction-panel--muted::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 0;
    background: color-mix(in oklab, var(--kb-bg-body) 35%, transparent);
    pointer-events: none;
}

.vt-faction-panel--muted:hover {
    opacity: 0.85;
    filter: saturate(0.7);
}

.vt-faction-muted-badge {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
    padding: 0.15rem 0.5rem;
    font-size: 0.68rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--kb-text-muted);
    background: color-mix(in oklab, var(--kb-bg-muted) 70%, transparent);
    border: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 40%);
    border-radius: 999px;
}

/* Faction badge — derived from match.team_factions (schema_version 3+).
   Sits next to the team-leader name in faction scoreboard headers. Color
   is keyed by data-faction-code: i = ISDF, e = Hadean, f = Scion. All
   colors come from existing --kb-* tokens; no hardcoded values. */
.vt-faction-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.55rem;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-radius: 999px;
    border: 1px solid currentColor;
    background: color-mix(in oklab, currentColor 12%, transparent);
}

/* Faction palette aliases — used by both the Commanders tab faction-picks
   chart and the Meta tab donut/bar charts. Defined here so all faction
   visualisations stay in lock-step with the badge colors above. */
:root {
    --kb-faction-i: var(--kb-primary);   /* ISDF — cyan/blue (project primary) */
    --kb-faction-e: var(--kb-warning);   /* Hadean — warm amber/red */
    --kb-faction-f: var(--kb-accent);    /* Scion — accent (typically green) */
}

.vt-faction-badge[data-faction-code="i"] {
    color: var(--kb-faction-i);
}

.vt-faction-badge[data-faction-code="e"] {
    color: var(--kb-faction-e);
}

.vt-faction-badge[data-faction-code="f"] {
    color: var(--kb-faction-f);
}

/* Winner badge — sits next to "Kill Feed" in the Combat-tab card header.
   Three visual states keyed by data-decided-by:
     - clean      : decisive win (recycler + factory of the loser are dead,
                    other team untouched). Success color.
     - contested  : both teams' bases fell; loser fell first. Info color.
     - unclear    : outcome could not be determined (rebuild ambiguity,
                    timeout, host quit, commander self-demo). Muted with
                    cursor:help so users know the tooltip explains why.
   Empty <span> renders nothing (display:none when empty); pre-v3 matches
   simply leave the slot empty. */
.vt-winner-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.18rem 0.6rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-radius: 999px;
    border: 1px solid currentColor;
    background: color-mix(in oklab, currentColor 15%, transparent);
    line-height: 1;
}

.vt-winner-badge:empty {
    display: none;
}

.vt-winner-badge[data-decided-by="clean"] {
    color: var(--kb-success);
}

.vt-winner-badge[data-decided-by="contested"] {
    color: var(--kb-info);
    cursor: help;
}

.vt-winner-badge[data-decided-by="unclear"] {
    color: var(--kb-text-muted);
    cursor: help;
}

/* Winner highlight on the faction scoreboard panel. The .vt-faction-panel
   --winner class is still attached to the winning team's panel so other
   contexts (e.g. fullscreen modal, future per-section selectors) can
   target it, but we deliberately leave its visual treatment to the
   trophy icon alone -- no border / box-shadow accent on the panel
   itself. The team-color border-left and existing hover shadow stay
   exactly as-is so the visual hierarchy is unchanged. */
.vt-faction-winner-icon {
    color: var(--kb-warning);
    font-size: 0.95em;
    filter: drop-shadow(0 0 4px color-mix(in oklab, var(--kb-warning) 40%, transparent));
}

/* In-feed milestone marker — divider row inserted into the Kill Feed at
   the winner's decided_at_tick. Uses --kb-success accent so it visually
   parallels the "clean" winner badge. Filter-safe: the renderer reads
   the tick from currentData.match.winner (passthrough), not from the
   filtered kills.feed. */
.vt-killfeed-milestone {
    margin: 0.4rem 0;
    padding: 0.5rem 0.75rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--kb-success);
    background: color-mix(in oklab, var(--kb-success) 10%, transparent);
    border-top: 1px solid color-mix(in oklab, var(--kb-success) 40%, transparent);
    border-bottom: 1px solid color-mix(in oklab, var(--kb-success) 40%, transparent);
    border-left: 3px solid var(--kb-success);
    border-radius: 0 4px 4px 0;
}

/* ============================================================================
   RIVALRY CARDS — Breathing Room
   Larger doughnut charts, more whitespace
   ============================================================================ */

#rivalries-container .rivalry-card,
#global-rivalries-container .rivalry-card {
    padding: 1.25rem;
    margin-bottom: 1rem;
    border-radius: 10px;
}

#rivalries-container .rivalry-card canvas,
#global-rivalries-container .rivalry-card canvas {
    width: 100px !important;
    height: 100px !important;
}

/* ============================================================================
   VIEW TRANSITION STYLES
   ============================================================================ */

::view-transition-old(root) {
    animation: 250ms ease-out both vt-view-fade-out;
}

::view-transition-new(root) {
    animation: 250ms ease-in both vt-view-fade-in;
}

@keyframes vt-view-fade-out {
    to { opacity: 0; }
}

@keyframes vt-view-fade-in {
    from { opacity: 0; }
}

/* ============================================================================
   DOCUMENTATION PAGE — Layout, TOC, prose, tables, code blocks
   ============================================================================ */

.docs-container {
    max-width: 1200px;
}

/* --- Sticky sidebar TOC (desktop) ---------------------------------------- */

.docs-toc-sticky {
    position: sticky;
    top: 70px;
    max-height: calc(100vh - 90px);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: color-mix(in oklab, var(--kb-text-muted), transparent 60%) transparent;
}

.docs-toc {
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent);
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent);
    border-radius: 10px;
    padding: 1rem;
}

/* --- Scroll progress bar ------------------------------------------------- */

.docs-toc-progress {
    height: 3px;
    border-radius: 3px;
    background: color-mix(in oklab, var(--kb-border-subtle), transparent 50%);
    margin-bottom: 0.75rem;
    overflow: hidden;
}

.docs-toc-progress-bar {
    height: 100%;
    width: 0%;
    border-radius: 3px;
    background: var(--kb-primary);
    box-shadow: 0 0 6px color-mix(in oklab, var(--kb-primary), transparent 50%);
    transition: width 0.1s linear;
}

/* --- TOC title ----------------------------------------------------------- */

.docs-toc-title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--kb-text-muted);
    margin-bottom: 0.75rem;
    padding-left: 0.5rem;
}

/* --- TOC list structure -------------------------------------------------- */

.docs-toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.docs-toc-section {
    margin-bottom: 2px;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 70%);
    padding-bottom: 4px;
}

.docs-toc-section:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

/* H2 row: chevron + link side by side */
.docs-toc-h2-row {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* Chevron toggle button */
.docs-toc-chevron {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    background: none;
    color: var(--kb-text-muted);
    cursor: pointer;
    border-radius: 4px;
    font-size: 0.6rem;
    transition: color 0.15s ease, transform 0.2s ease, background-color 0.15s ease;
}

.docs-toc-chevron:hover {
    color: var(--kb-text-primary);
    background: color-mix(in oklab, var(--kb-bg-muted) 50%, transparent);
}

.docs-toc-chevron i {
    transition: transform 0.2s ease;
    display: block;
}

.docs-toc-section--open > .docs-toc-h2-row > .docs-toc-chevron i {
    transform: rotate(90deg);
}

/* H2 and H3 links */
.docs-toc-link {
    display: block;
    padding: 0.25rem 0.5rem;
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--kb-text-muted);
    text-decoration: none;
    border-left: 2px solid transparent;
    border-radius: 0 4px 4px 0;
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.docs-toc-link--h2 {
    font-weight: 500;
    color: var(--kb-text-secondary);
    flex: 1;
    min-width: 0;
}

.docs-toc-link--h3 {
    font-size: 0.75rem;
    padding: 0.15rem 0.5rem;
}

.docs-toc-link:hover {
    color: var(--kb-text-primary);
    background: color-mix(in oklab, var(--kb-bg-muted) 50%, transparent);
}

.docs-toc-link--active {
    color: var(--kb-primary) !important;
    border-left-color: var(--kb-primary);
    font-weight: 500;
}

/* Active section: H2 gets accent indicator */
.docs-toc-section--active > .docs-toc-h2-row > .docs-toc-link--h2 {
    color: var(--kb-primary);
    border-left-color: var(--kb-primary);
}

/* --- Collapsible H3 sublists --------------------------------------------- */

.docs-toc-sublist {
    list-style: none;
    padding-left: 0.5rem;
    margin: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.25s ease, opacity 0.2s ease, margin 0.25s ease;
    border-left: 1px solid color-mix(in oklab, var(--kb-border-subtle), transparent 40%);
    margin-left: 9px;
}

.docs-toc-section--open > .docs-toc-sublist {
    max-height: 600px;
    opacity: 1;
    margin-top: 2px;
    margin-bottom: 4px;
}

.docs-toc-sublist > li {
    margin-bottom: 1px;
}

/* Sections without children (no chevron) get consistent left padding */
.docs-toc-section:not(:has(.docs-toc-chevron)) > .docs-toc-h2-row {
    padding-left: 22px;
}

/* Mobile TOC variant */
.docs-toc--mobile {
    max-height: 50vh;
    overflow-y: auto;
}

/* --- Heading anchor links ------------------------------------------------ */

.docs-heading-anchor {
    color: var(--kb-text-muted);
    text-decoration: none !important;
    margin-left: 0.4em;
    opacity: 0;
    transition: opacity 0.2s ease, color 0.2s ease;
    font-size: 0.8em;
    vertical-align: middle;
}

h2:hover .docs-heading-anchor,
h3:hover .docs-heading-anchor,
h4:hover .docs-heading-anchor,
.docs-heading-anchor:focus {
    opacity: 0.6;
}

.docs-heading-anchor:hover {
    opacity: 1 !important;
    color: var(--kb-primary);
}

/* --- Back-to-top button -------------------------------------------------- */

.docs-back-to-top {
    position: fixed;
    bottom: 2rem;
    right: 2rem;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent);
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent);
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    color: var(--kb-text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    box-shadow: var(--vt-shadow-elevation-1);
    opacity: 0;
    pointer-events: none;
    transform: translateY(8px);
    transition: opacity 0.25s ease, transform 0.25s ease, color 0.15s ease, box-shadow 0.15s ease;
    z-index: 1020;
}

.docs-back-to-top--visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.docs-back-to-top:hover {
    color: var(--kb-primary);
    box-shadow: var(--vt-shadow-elevation-2);
}

/* --- Prose typography ---------------------------------------------------- */

.docs-prose {
    color: var(--kb-text-primary);
    line-height: 1.7;
}

.docs-prose h1 {
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 1.5rem;
    padding-bottom: 0.75rem;
    border-bottom: 2px solid var(--kb-primary);
}

.docs-prose h2 {
    font-size: 1.5rem;
    font-weight: 650;
    margin-top: 3rem;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--kb-border-subtle);
    scroll-margin-top: 70px;
}

.docs-prose h3 {
    font-size: 1.2rem;
    font-weight: 600;
    margin-top: 2rem;
    margin-bottom: 0.75rem;
    color: var(--kb-text-primary);
    scroll-margin-top: 70px;
}

.docs-prose h4 {
    font-size: 1.05rem;
    font-weight: 600;
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
    color: var(--kb-text-secondary);
    scroll-margin-top: 70px;
}

.docs-prose p {
    margin-bottom: 1rem;
    color: var(--kb-text-secondary);
}

.docs-prose strong {
    color: var(--kb-text-primary);
    font-weight: 600;
}

.docs-prose a:not(.docs-heading-anchor) {
    color: var(--kb-primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.docs-prose a:not(.docs-heading-anchor):hover {
    color: var(--kb-accent);
}

.docs-prose ul,
.docs-prose ol {
    margin-bottom: 1rem;
    padding-left: 1.5rem;
    color: var(--kb-text-secondary);
}

.docs-prose li {
    margin-bottom: 0.35rem;
}

.docs-prose hr {
    border-color: var(--kb-border-subtle);
    margin: 2.5rem 0;
    opacity: 0.5;
}

.docs-prose code {
    font-family: 'Geist Mono', ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
    font-size: 0.85em;
    padding: 0.15em 0.4em;
    border-radius: 4px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 80%, transparent);
    color: var(--kb-primary);
}

.docs-prose pre {
    margin-bottom: 1.25rem;
}

.docs-prose pre > code {
    display: block;
    padding: 0;
    background: none;
    color: var(--kb-text-primary);
    font-size: 0.82rem;
    line-height: 1.6;
}

.docs-prose .docs-code-block {
    background: color-mix(in oklab, var(--kb-bg-card) var(--vt-glass-opacity), transparent);
    backdrop-filter: blur(var(--vt-glass-blur));
    -webkit-backdrop-filter: blur(var(--vt-glass-blur));
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) var(--vt-glass-border-luminance), transparent);
    border-radius: 8px;
    padding: 1rem 1.25rem;
    overflow-x: auto;
}

.docs-prose .table {
    font-size: 0.85rem;
    color: var(--kb-text-primary);
    margin-bottom: 1.25rem;
    --bs-table-striped-bg: color-mix(in oklab, var(--kb-bg-subtle), transparent 50%);
}

.docs-prose .table th {
    font-weight: 600;
    white-space: nowrap;
    color: var(--kb-text-primary);
    border-bottom-color: var(--kb-border-subtle);
    position: sticky;
    top: 0;
    background: var(--kb-bg-card);
    z-index: 1;
}

.docs-prose .table td {
    color: var(--kb-text-secondary);
    border-bottom-color: color-mix(in oklab, var(--kb-border-subtle), transparent 50%);
}

.docs-prose .table td code {
    font-size: 0.82em;
}

.docs-prose blockquote {
    border-left: 3px solid var(--kb-primary);
    padding: 0.5rem 1rem;
    margin: 1rem 0;
    background: color-mix(in oklab, var(--kb-bg-subtle) 50%, transparent);
    border-radius: 0 6px 6px 0;
    color: var(--kb-text-secondary);
}

/* ============================================================
 * Replay Player (Timeline Playback)
 * Transport bar, scrub slider, speed pills, running leaderboard,
 * faction tug-of-war, momentum chip, bucket spotlight.
 * ============================================================ */

.vt-replay-transport {
    padding: 0.75rem;
    border-radius: 10px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 60%, transparent);
    border: 1px solid var(--kb-border-subtle);
}

.vt-replay-transport-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.vt-replay-play.btn-primary {
    min-width: 2.5rem;
}

.vt-replay-time {
    min-width: 7.5rem;
    text-align: center;
    color: var(--kb-text-secondary);
    font-size: 0.85rem;
}

.vt-replay-scrub-wrap {
    flex: 1 1 200px;
    min-width: 160px;
    display: flex;
    align-items: center;
}

.vt-replay-scrub {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 6px;
    border-radius: 3px;
    background: color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
    outline: none;
    cursor: pointer;
}

.vt-replay-scrub::-webkit-slider-runnable-track {
    height: 6px;
    border-radius: 3px;
    background: linear-gradient(to right,
        var(--kb-primary) 0%,
        var(--kb-primary) var(--vt-scrub-progress, 0%),
        color-mix(in oklab, var(--kb-border-subtle), transparent 30%) var(--vt-scrub-progress, 0%));
}

.vt-replay-scrub::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--kb-primary);
    border: 2px solid var(--kb-bg-card);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: grab;
    margin-top: -5px;
}

.vt-replay-scrub::-moz-range-track {
    height: 6px;
    border-radius: 3px;
    background: color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
}

.vt-replay-scrub::-moz-range-progress {
    height: 6px;
    border-radius: 3px;
    background: var(--kb-primary);
}

.vt-replay-scrub::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--kb-primary);
    border: 2px solid var(--kb-bg-card);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: grab;
}

.vt-replay-scrub:active::-webkit-slider-thumb { cursor: grabbing; }
.vt-replay-scrub:active::-moz-range-thumb { cursor: grabbing; }

.vt-replay-speed-pills .btn {
    font-size: 0.75rem;
    padding: 0.25rem 0.5rem;
}

/* Running leaderboard with smooth reorder via CSS flex order */
.vt-replay-leaderboard {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.vt-replay-lb-row {
    display: grid;
    grid-template-columns: 1.75rem 0.75rem minmax(0, 1fr) minmax(60px, 2fr) auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0.5rem;
    border-radius: 6px;
    background: color-mix(in oklab, var(--kb-bg-subtle) 40%, transparent);
    transition: background var(--vt-anim-duration) var(--vt-anim-ease);
    font-size: 0.85rem;
}

.vt-replay-lb-rank {
    color: var(--kb-text-muted);
    font-size: 0.8rem;
    text-align: right;
}

.vt-replay-lb-swatch {
    display: inline-block;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 2px;
    background: var(--kb-primary);
}

.vt-replay-lb-name {
    color: var(--kb-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-replay-lb-bar-wrap {
    height: 6px;
    border-radius: 3px;
    background: color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
    overflow: hidden;
    position: relative;
}

.vt-replay-lb-bar {
    display: block;
    height: 100%;
    width: 0%;
    background: var(--kb-primary);
    border-radius: 3px;
    transition: width var(--vt-anim-duration) var(--vt-anim-ease);
}

.vt-replay-lb-val {
    color: var(--kb-text-secondary);
    font-size: 0.8rem;
    text-align: right;
    min-width: 3rem;
}

/* Faction tug-of-war bar */
.vt-replay-tugbar {
    display: flex;
    width: 100%;
    height: 1.5rem;
    border-radius: 8px;
    overflow: hidden;
    background: color-mix(in oklab, var(--kb-border-subtle), transparent 30%);
}

.vt-replay-tugbar-seg {
    height: 100%;
    transition: width var(--vt-anim-duration) var(--vt-anim-ease);
}

.vt-replay-tugbar-t1 {
    background: var(--kb-primary);
}

.vt-replay-tugbar-t2 {
    background: var(--kb-success);
}

.vt-replay-tugbar-legend {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.5rem;
    font-size: 0.8rem;
    color: var(--kb-text-secondary);
}

.vt-replay-swatch {
    display: inline-block;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 2px;
    margin-right: 0.375rem;
    vertical-align: middle;
}

.vt-replay-swatch-t1 { background: var(--kb-primary); }
.vt-replay-swatch-t2 { background: var(--kb-success); }

/* Momentum chip */
.vt-replay-momentum-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    background: color-mix(in oklab, var(--kb-bg-subtle) 60%, transparent);
    border: 1px solid var(--kb-border-subtle);
    color: var(--kb-text-secondary);
}

.vt-replay-momentum-t1 {
    color: var(--kb-primary);
    border-color: color-mix(in oklab, var(--kb-primary), transparent 60%);
}

.vt-replay-momentum-t2 {
    color: var(--kb-success);
    border-color: color-mix(in oklab, var(--kb-success), transparent 60%);
}

/* Bucket spotlight */
.vt-replay-spotlight {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.vt-replay-spotlight-time {
    font-size: 1.5rem;
    color: var(--kb-primary);
    min-width: 4rem;
}

.vt-replay-spotlight-body {
    color: var(--kb-text-secondary);
    font-size: 0.9rem;
    flex: 1;
}

/* Responsive: stack transport on narrow screens */
@media (max-width: 575.98px) {
    .vt-replay-time {
        min-width: 0;
        flex: 1 0 100%;
        text-align: left;
    }
    .vt-replay-speed-pills {
        flex: 1 0 100%;
    }
    .vt-replay-scrub-wrap {
        flex: 1 0 100%;
    }
}

/* ============================================================================
   MOBILE RESPONSIVENESS
   Topnav hamburger (<md), tab horizontal-scroll strip, match-info grid,
   filter bar compaction, player picker clamp, container spacing.
   ============================================================================ */

/* ---------- Label helpers (hidden on desktop, shown inside collapsed nav) ---------- */

.vt-nav-label {
    display: none;
}

/* Mode label pair: show only the one matching current root mode */
[data-mode="dark"] .vt-nav-label--mode-light,
[data-mode="light"] .vt-nav-label--mode-dark {
    display: none !important;
}

/* ---------- Burger button ---------- */

.vt-navbar-toggler {
    border: none;
    box-shadow: none;
    font-size: 1.25rem;
    padding: 0.375rem 0.5rem;
    line-height: 1;
}

.vt-navbar-toggler:focus,
.vt-navbar-toggler:focus-visible {
    box-shadow: none;
    outline: none;
}

/* ---------- Horizontal-scroll tab strip wrapper ---------- */

.vt-tab-scroll-wrap {
    position: relative;
}

/* ---------- Breakpoint: below md (<768px) ---------- */

@media (max-width: 767.98px) {
    /* -- Navbar collapsed menu -- */
    .navbar-collapse {
        flex-basis: 100%;
        margin-top: 0.5rem;
        padding-top: 0.75rem;
        border-top: 1px solid color-mix(in oklab, var(--kb-text-primary) 8%, transparent);
    }

    /* Inner flex column fills the collapsed row so stacked items align flush */
    .vt-nav-menu {
        width: 100%;
    }

    .vt-nav-menu .vt-nav-icon-btn {
        justify-content: flex-start;
        width: 100%;
        padding: 0.5rem 0.75rem;
    }

    .vt-nav-menu .vt-nav-label {
        display: inline;
    }

    /* Theme dropdown: render its menu inline with the collapsed menu
       so it doesn't float off the viewport edge. */
    .vt-nav-menu .dropdown {
        width: 100%;
    }

    .vt-nav-menu .dropdown-menu {
        position: static !important;
        transform: none !important;
        inset: auto !important;
        width: 100%;
        min-width: 0 !important;
        border: none;
        box-shadow: none;
        background: transparent !important;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        padding-left: 0.5rem;
    }

    /* -- Tab navigation: horizontal scroll strip -- */
    #match-tabs,
    #all-tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x proximity;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    #match-tabs::-webkit-scrollbar,
    #all-tabs::-webkit-scrollbar {
        display: none;
    }

    #match-tabs .nav-item,
    #all-tabs .nav-item {
        flex: 0 0 auto;
        scroll-snap-align: start;
    }

    #match-tabs .nav-link,
    #all-tabs .nav-link {
        white-space: nowrap;
    }

    /* Right-edge fade hint: suggests more tabs are off-screen.
       Only applied to the 6-tab match-tabs wrapper (always overflows on
       mobile); the 2-tab all-tabs fits without scrolling. */
    .vt-tab-scroll-wrap:has(#match-tabs)::after {
        content: "";
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: 2rem;
        pointer-events: none;
        background: linear-gradient(to right, transparent, var(--kb-bg-body) 85%);
        border-top-right-radius: 10px;
        border-bottom-right-radius: 10px;
    }

    /* -- Match-info banner: 2-column grid for stat blocks -- */
    #match-info .card-body {
        gap: 0.75rem !important;
        padding: 1rem;
    }

    #match-info .card-body > .d-flex:first-child {
        display: grid !important;
        grid-template-columns: 1fr 1fr;
        gap: 0.75rem 1.25rem;
        width: 100%;
    }

    #match-info .card-body > .d-flex:first-child > div {
        min-width: 0;
    }

    /* -- Filter mode btn-group: compact so 3 buttons fit one row -- */
    #filter-mode .btn {
        padding: 0.3rem 0.6rem;
        font-size: 0.75rem;
    }
}

/* ---------- Breakpoint: below sm (<576px) ---------- */

@media (max-width: 575.98px) {
    /* Tighter container spacing on phones */
    #dashboard,
    #all-matches-view {
        padding-top: 1rem !important;
        padding-bottom: 1rem !important;
    }

    /* Even tighter filter btn-group */
    #filter-mode .btn {
        padding: 0.25rem 0.5rem;
        font-size: 0.7rem;
    }

    /* Player picker floating dropdown: pin to both sides so it never clips.
       The JS sets `right: Xpx` + `left: auto` to right-anchor against the
       toggle; on phones we override both to stretch full-width with 8px
       margins, keeping it on-screen at 320px. */
    .vt-player-picker--floating {
        left: 0.5rem !important;
        right: 0.5rem !important;
        max-width: none !important;
        min-width: 0 !important;
        max-height: 60vh;
    }
}

/* ============================================================================
   POSITIONING TAB
   Movement Profile: top-down heatmaps, radial small multiples, score bars.
   Honors the same glass + kb-* theme system as the rest of the dashboard.
   ============================================================================ */

/* Movement score cell in main leaderboard + movement leaderboard */
.vt-movement-cell {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 110px;
}

.vt-movement-cell-top {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    justify-content: space-between;
}

.vt-movement-score {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1;
}

.vt-movement-band-label {
    color: var(--kb-text-muted);
    font-size: 0.7rem;
    letter-spacing: 0.02em;
}

.vt-movement-bar {
    height: 4px;
    background: var(--kb-border-subtle);
    border-radius: 2px;
    overflow: hidden;
}

.vt-movement-bar-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 300ms ease;
}

.vt-movement-chip {
    display: inline-block;
    padding: 0 0.4em;
    border-radius: 4px;
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 0.72rem;
    line-height: 1.35;
}

/* Heatmap canvas wrappers */
.vt-heatmap-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    max-height: 520px;
}

.vt-heatmap-wrap canvas {
    width: 100%;
    height: 100%;
    display: block;
    border-radius: 8px;
    border: 1px solid var(--kb-border-subtle);
}

/* Per-player small-multiples grid */
.vt-heatmap-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 0.75rem;
}

.vt-heatmap-grid-cell {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.5rem;
    border-radius: 8px;
    background: var(--kb-bg-subtle);
    border: 1px solid var(--kb-border-subtle);
}

.vt-heatmap-grid-title {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
    font-size: 0.8rem;
}

.vt-heatmap-small {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
}

.vt-heatmap-small canvas {
    width: 100%;
    height: 100%;
    display: block;
    border-radius: 6px;
}

/* Empty-state card */
.vt-empty-icon {
    opacity: 0.45;
}

/* ============================================================================
   POSITIONING POLISH PASS
   Intro banner, info icons on column headers, band pill chip.
   ============================================================================ */

.vt-info-banner {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    background: color-mix(in oklab, var(--kb-info) 10%, var(--kb-bg-card));
    border: 1px solid color-mix(in oklab, var(--kb-info) 30%, transparent);
    color: var(--kb-text-secondary);
    font-size: 0.85rem;
    line-height: 1.5;
}

.vt-info-banner > i.bi {
    color: var(--kb-info);
    font-size: 1.1rem;
    margin-top: 0.15rem;
    flex-shrink: 0;
}

.vt-info-banner strong {
    color: var(--kb-text-primary);
    font-weight: 600;
}

.vt-info-banner em {
    color: var(--kb-text-primary);
    font-style: normal;
    font-weight: 600;
}

/* Info icon on column headers */
.vt-col-info {
    color: var(--kb-text-muted);
    font-size: 0.85em;
    cursor: help;
    transition: color 0.15s ease;
    vertical-align: baseline;
}

.vt-col-info:hover {
    color: var(--kb-info);
}

/* Bootstrap tooltips — dark-theme correction.
   Bootstrap's defaults derive tooltip text color from --bs-body-bg, which this
   project remaps to a dark color, collapsing tooltip text to invisible.
   Remap the tooltip tokens directly to our --kb-* surface/text variables. */
.tooltip {
    --bs-tooltip-color: var(--kb-text-primary);
    --bs-tooltip-bg: var(--kb-bg-card);
    --bs-tooltip-max-width: 260px;
    --bs-tooltip-padding-x: 0.6rem;
    --bs-tooltip-padding-y: 0.45rem;
    --bs-tooltip-font-size: 0.78rem;
    --bs-tooltip-opacity: 1;
}

/* Wider tooltip for the per-axis bar rows in the VTSR-T expand panel.
   The body carries label + formula (in <code>) + description + per-row
   sigma interpretation; 260px wraps the formula awkwardly. */
.tooltip.vt-axis-tooltip {
    --bs-tooltip-max-width: 340px;
}

.tooltip .tooltip-inner {
    border: 1px solid var(--kb-border-default);
    text-align: left;
    line-height: 1.4;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}

/* Arrow color must match the background per placement — Bootstrap hardcodes
   these and does not read --bs-tooltip-bg for the arrow. */
.tooltip.bs-tooltip-top    .tooltip-arrow::before { border-top-color:    var(--kb-bg-card); }
.tooltip.bs-tooltip-bottom .tooltip-arrow::before { border-bottom-color: var(--kb-bg-card); }
.tooltip.bs-tooltip-start  .tooltip-arrow::before { border-left-color:   var(--kb-bg-card); }
.tooltip.bs-tooltip-end    .tooltip-arrow::before { border-right-color:  var(--kb-bg-card); }
.tooltip.bs-tooltip-auto[data-popper-placement^="top"]    .tooltip-arrow::before { border-top-color:    var(--kb-bg-card); }
.tooltip.bs-tooltip-auto[data-popper-placement^="bottom"] .tooltip-arrow::before { border-bottom-color: var(--kb-bg-card); }
.tooltip.bs-tooltip-auto[data-popper-placement^="left"]   .tooltip-arrow::before { border-left-color:   var(--kb-bg-card); }
.tooltip.bs-tooltip-auto[data-popper-placement^="right"]  .tooltip-arrow::before { border-right-color:  var(--kb-bg-card); }

/* Split columns (PvP / PvE breakdowns) — visually secondary vs the combined total */
.vt-col-split,
td.vt-col-split {
    color: var(--kb-text-muted);
    font-size: 0.92em;
}

#leaderboard thead th.vt-col-split,
#career-table thead th.vt-col-split {
    color: var(--kb-text-muted);
    font-weight: 500;
}

/* Career leaderboard: show per-match averages, totals, or both */
#career-table.vt-career-cols-per-match .vt-career-col-total,
#career-table.vt-career-cols-totals .vt-career-col-avg {
    display: none;
}

/* Sticky table headers — keep column labels visible while scrolling the page.
   Anchored to the .kb-header height (64px). Uses --kb-bg-popover to match
   the existing `.table > thead` background in css/main.css (otherwise the
   thead would shift color on themes where -popover and -card diverge). */
.vt-sticky-thead thead th {
    position: sticky;
    top: 64px;
    z-index: 5;
    background: var(--kb-bg-popover);
    box-shadow: inset 0 -1px 0 var(--kb-border-subtle);
}

/* The card-body wrapper uses .table-responsive (overflow-x: auto), which the
   CSS spec promotes into a y-axis scroll container too — that swallows the
   sticky behaviour. At >=992px (where these tables fit horizontally) drop
   the wrapper's overflow constraint so page-level scroll drives sticky.
   Below 992px keep the default behaviour: horizontal table scroll, no sticky. */
@media (min-width: 992px) {
    .vt-sticky-thead-card.table-responsive {
        overflow: visible;
    }
}

/* Inside the Fullscreen modal the cloned table sits in its own scroll
   container (.modal-body), and the page header isn't above it — re-anchor
   sticky to the top of that scroll container. */
#fullscreen-modal .vt-sticky-thead thead th {
    top: 0;
}

/* Movement band pill (replaces the muted band-label text) */
.vt-movement-band-pill {
    padding: 0.1em 0.5em;
    border-radius: 10px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.35;
    white-space: nowrap;
}

.vt-sort-caret {
    color: var(--kb-info);
    font-size: 0.75em;
    margin-left: 0.15em;
    vertical-align: baseline;
}

/* ============================================================================
   HEATMAP LEGEND
   Compact strip rendered above the per-player small-multiples grid.
   Spans the full grid row via grid-column: 1 / -1 so it sits above the cards.
   ============================================================================ */

.vt-heatmap-legend {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    padding: 0.5rem 0.25rem 0.75rem;
    margin-bottom: 0.5rem;
    color: var(--kb-text-muted);
    font-size: 0.75rem;
    border-bottom: 1px solid var(--kb-border-subtle);
}

.vt-heatmap-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.vt-heatmap-legend-diamond {
    width: 8px;
    height: 8px;
    background: var(--kb-info);
    transform: rotate(45deg);
    display: inline-block;
}

.vt-heatmap-legend-gradient {
    display: inline-block;
    width: 80px;
    height: 8px;
    border-radius: 4px;
    background: linear-gradient(
        to right,
        color-mix(in oklab, var(--kb-info) 10%, transparent),
        color-mix(in oklab, var(--kb-info) 85%, transparent)
    );
}

.vt-heatmap-legend-label {
    font-size: 0.7rem;
}

/* =====================================================================
   Rich Match Picker
   ---------------------------------------------------------------------
   Faux-dropdown trigger in both hero contexts (#match-info on the
   per-match dashboard and the .vt-all-hero card on the All Matches
   view) opens #match-picker-modal, which houses a searchable card
   grid. Phase 2 will add a filter toolbar above the grid.
   ===================================================================== */

/* Map thumbnail in the match-info hero. 70x70 top-down image from
 * data/map-registry.json. Hidden (d-none) on matches whose map isn't
 * in the registry. Renders to the left of the match-picker trigger.
 * Wrapped in a `.vt-map-thumb-btn` button that opens #map-info-modal
 * with the full-resolution image + registry metadata. */
.vt-map-thumb {
    width: 70px;
    height: 70px;
    border-radius: 8px;
    border: 1px solid var(--kb-border-subtle);
    background: var(--kb-bg-subtle);
    object-fit: cover;
    flex-shrink: 0;
    display: block;
    transition: border-color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-map-thumb-btn {
    position: relative;
    cursor: pointer;
    line-height: 0;
    border-radius: 8px;
}

.vt-map-thumb-btn:hover .vt-map-thumb,
.vt-map-thumb-btn:focus-visible .vt-map-thumb {
    border-color: var(--kb-primary);
    transform: translateY(-1px);
}

/* Lightbox-style affordance: a small zoom-in badge in the bottom-right
 * corner of the thumbnail signals the image opens the Map Info Modal.
 * Pointer-events disabled so the wrapping button still owns the click. */
.vt-map-thumb-overlay {
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: color-mix(in oklab, var(--kb-bg-surface) 75%, transparent);
    color: var(--kb-primary);
    font-size: 0.85rem;
    line-height: 1;
    pointer-events: none;
    backdrop-filter: blur(2px);
    border: 1px solid var(--kb-border-subtle);
    transition: transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                background var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-map-thumb-btn:hover .vt-map-thumb-overlay,
.vt-map-thumb-btn:focus-visible .vt-map-thumb-overlay {
    transform: scale(1.1);
    background: color-mix(in oklab, var(--kb-primary) 25%, var(--kb-bg-surface));
}

/* Map Info Modal: full-resolution map image + registry / terrain meta.
 * Triggered by the .vt-map-thumb-btn in the match-info banner. */
.vt-map-info-image {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: contain;
    border-radius: 8px;
    border: 1px solid var(--kb-border-subtle);
    background: var(--kb-bg-subtle);
    display: block;
}

.vt-map-info-meta {
    margin: 0;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.45rem 1rem;
    font-size: 0.9rem;
}

.vt-map-info-meta dt {
    color: var(--kb-text-muted);
    font-weight: 500;
    margin: 0;
    white-space: nowrap;
}

.vt-map-info-meta dd {
    color: var(--kb-text-primary);
    margin: 0;
    word-break: break-word;
}

/* Author / community blurb shown beneath the map image in the left
 * column. Multi-line strings (registry `description` is a raw newline-
 * delimited dump from iondriver's API) read better here than crammed
 * into the right-column metadata grid. */
.vt-map-info-description {
    margin-top: 0.75rem;
    color: var(--kb-text-secondary);
    font-style: italic;
    font-size: 0.875rem;
    line-height: 1.5;
    padding: 0.6rem 0.85rem;
    border-left: 2px solid var(--kb-border-subtle);
    background: color-mix(in oklab, var(--kb-bg-subtle) 40%, transparent);
    border-radius: 0 6px 6px 0;
    word-break: break-word;
}

.vt-map-info-meta-empty {
    color: var(--kb-text-muted);
    font-style: italic;
    font-size: 0.9rem;
}

/* vsrmaplist-sourced map tags (e.g. "popular", "played"). Rendered as
 * inline chips in the Map Info Modal's Tags row. Aesthetic mirrors the
 * project's existing pill-shaped badge treatments. */
.vt-map-info-tag {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.55rem;
    margin-right: 0.25rem;
    border-radius: 999px;
    background: var(--kb-bg-subtle);
    color: var(--kb-text-secondary);
    border: 1px solid var(--kb-border-subtle);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.2;
}

.vt-map-info-tag:last-child {
    margin-right: 0;
}

.vt-map-info-meta .vt-map-info-meta-section {
    grid-column: 1 / -1;
    color: var(--kb-text-muted);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-top: 0.5rem;
    padding-top: 0.4rem;
    border-top: 1px solid var(--kb-border-subtle);
}

.vt-map-info-meta .vt-map-info-meta-section:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

/* --- Trigger button (lives in each hero) --- */

.vt-match-picker-trigger {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 0.15rem;
    padding: 0.4rem 0.85rem 0.45rem;
    min-width: 180px;
    max-width: 320px;
    border: 1px solid var(--kb-border-subtle);
    border-radius: 0.5rem;
    background: color-mix(in oklab, var(--kb-bg-subtle) 50%, transparent);
    color: var(--kb-text-primary);
    text-align: left;
    cursor: pointer;
    transition: border-color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                background var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-match-picker-trigger:hover,
.vt-match-picker-trigger:focus-visible {
    border-color: var(--kb-primary);
    transform: translateY(-1px);
    background: color-mix(in oklab, var(--kb-bg-subtle) 75%, transparent);
    outline: none;
}

.vt-match-picker-trigger .stat-label {
    font-size: 0.65rem;
    line-height: 1;
    opacity: 0.9;
}

.vt-match-picker-trigger-primary {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.1;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-match-picker-trigger-primary .bi-chevron-down {
    font-size: 0.75rem;
    color: var(--kb-text-muted);
    transition: transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-match-picker-trigger[aria-expanded="true"] .bi-chevron-down {
    transform: rotate(180deg);
}

.vt-match-picker-trigger-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 220px;
}

.vt-match-picker-trigger-secondary {
    font-size: 0.75rem;
    color: var(--kb-text-muted);
    font-family: 'Geist Mono', ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Modal --- */

.vt-match-picker-modal .modal-content {
    background: var(--kb-bg-card);
    border: 1px solid var(--kb-border-subtle);
}

.vt-match-picker-modal .modal-header {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.75rem;
    align-items: center;
    border-bottom: 1px solid var(--kb-border-subtle);
}

.vt-match-picker-modal .modal-title {
    flex: 0 0 auto;
}

.vt-match-picker-search {
    flex: 1 1 260px;
    max-width: 360px;
    margin-left: auto;
}

.vt-match-picker-modal .modal-body {
    background: transparent;
}

/* --- Grid --- */

.vt-match-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 0.75rem;
}

/* --- Card (rendered as <button>, visually a card) --- */

.vt-match-picker-card {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: 0.75rem;
    padding: 0.75rem 0.9rem;
    border: 1px solid var(--kb-border-subtle);
    border-radius: 0.55rem;
    background: color-mix(in oklab, var(--kb-bg-subtle) 55%, transparent);
    color: var(--kb-text-primary);
    text-align: left;
    font: inherit;
    cursor: pointer;
    transition: border-color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                background var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
    position: relative;
}

.vt-match-picker-card:hover,
.vt-match-picker-card:focus-visible {
    border-color: var(--kb-primary);
    transform: translateY(-1px);
    background: color-mix(in oklab, var(--kb-bg-subtle) 75%, transparent);
    outline: none;
}

.vt-match-picker-card.is-active {
    border-color: var(--kb-primary);
    background: color-mix(in oklab, var(--kb-primary) 10%, var(--kb-bg-subtle));
}

.vt-match-picker-card.is-active::after {
    content: "\F26A"; /* bi-check-lg */
    font-family: "bootstrap-icons";
    position: absolute;
    top: 0.55rem;
    right: 0.6rem;
    color: var(--kb-primary);
    font-size: 1rem;
    line-height: 1;
}

.vt-match-picker-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}

/* Thumbnail on the left of each match-picker card. Top-down map image
 * from data/map-registry.json; when unavailable (map not in registry
 * or registry not fetched yet), renders a neutral placeholder so card
 * heights stay stable. Square to preserve aspect ratio regardless of
 * source image dimensions. */
.vt-match-picker-card-thumb {
    flex: 0 0 auto;
    width: 96px;
    height: 96px;
    border-radius: 0.4rem;
    border: 1px solid var(--kb-border-subtle);
    background: color-mix(in oklab, var(--kb-bg-subtle) 80%, transparent);
    object-fit: cover;
    align-self: center;
}

.vt-match-picker-card-thumb--placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--kb-text-muted);
    font-size: 1.5rem;
}

/* Wrapper around the text side of the card. flex-column so the existing
 * head/meta/submeta/leaders rows still stack vertically inside. */
.vt-match-picker-card-body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1 1 auto;
    min-width: 0;
}

@media (max-width: 480px) {
    /* On narrow viewports the left thumb eats too much of the card width.
     * Fold to a top thumb / bottom text layout at 64px height. */
    .vt-match-picker-card {
        flex-direction: column;
        align-items: stretch;
    }
    .vt-match-picker-card-thumb {
        width: 100%;
        height: 72px;
    }
}

.vt-match-picker-card-name {
    font-weight: 600;
    font-size: 0.95rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}

.vt-match-picker-card-meta {
    font-size: 0.75rem;
    color: var(--kb-text-muted);
    font-family: 'Geist Mono', ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
    white-space: nowrap;
}

.vt-match-picker-card-rawmap {
    font-size: 0.72rem;
    color: var(--kb-text-muted);
    opacity: 0.8;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-match-picker-card-submeta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--kb-text-muted);
}

.vt-match-picker-card-submitter {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.vt-match-picker-card-date {
    font-family: 'Geist Mono', ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.vt-match-picker-card-leaders {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding-top: 0.4rem;
    margin-top: 0.15rem;
    border-top: 1px dashed var(--kb-border-subtle);
    font-size: 0.8rem;
    min-width: 0;
}

.vt-match-picker-card-leader {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 0 1 auto;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.vt-match-picker-card-leader::before {
    content: "";
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    flex: 0 0 auto;
}

.vt-match-picker-card-leader--t1::before {
    background: var(--kb-primary);
}

.vt-match-picker-card-leader--t2::before {
    background: var(--kb-accent);
}

.vt-match-picker-card-leader-vs {
    color: var(--kb-text-muted);
    font-size: 0.75rem;
    font-style: italic;
    flex: 0 0 auto;
}

/* --- "All Matches" pinned card --- */

.vt-match-picker-card--all {
    background: color-mix(in oklab, var(--kb-primary) 6%, var(--kb-bg-subtle));
    border-style: dashed;
}

.vt-match-picker-card--all:hover,
.vt-match-picker-card--all:focus-visible {
    background: color-mix(in oklab, var(--kb-primary) 12%, var(--kb-bg-subtle));
}

/* --- Empty state (search / filters yield zero matches) --- */

.vt-match-picker-empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--kb-text-muted);
    border: 1px dashed var(--kb-border-subtle);
    border-radius: 0.5rem;
    background: color-mix(in oklab, var(--kb-bg-subtle) 30%, transparent);
    margin-top: 0.5rem;
}

/* --- Phase 2: Filter toolbar --- */

.vt-match-picker-filters {
    margin-bottom: 0.85rem;
    border: 1px solid var(--kb-border-subtle);
    border-radius: 0.55rem;
    background: color-mix(in oklab, var(--kb-bg-subtle) 35%, transparent);
    overflow: hidden;
}

.vt-match-picker-filters-body {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.75rem 0.9rem;
}

.vt-match-picker-filter-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    min-height: 1.9rem;
}

.vt-match-picker-filter-row--controls {
    justify-content: space-between;
    padding-bottom: 0.35rem;
    border-bottom: 1px dashed var(--kb-border-subtle);
    margin-bottom: 0.1rem;
}

.vt-match-picker-filter-label {
    flex: 0 0 84px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--kb-text-muted);
}

.vt-match-picker-filter-controls {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.vt-match-picker-filter-summary {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.8rem;
    color: var(--kb-text-muted);
}

.vt-match-picker-sort {
    min-width: 150px;
    max-width: 220px;
}

.vt-match-picker-chipset {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    flex: 1 1 auto;
    min-width: 0;
}

.vt-match-picker-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.55rem;
    border: 1px solid var(--kb-border-subtle);
    border-radius: 999px;
    background: color-mix(in oklab, var(--kb-bg-card) 88%, transparent);
    color: var(--kb-text-primary);
    font-size: 0.78rem;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
    transition: border-color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                background var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-match-picker-chip:hover,
.vt-match-picker-chip:focus-visible {
    border-color: var(--kb-primary);
    outline: none;
}

.vt-match-picker-chip.is-active {
    background: var(--kb-primary);
    color: var(--kb-primary-fg);
    border-color: var(--kb-primary);
}

.vt-match-picker-chip.is-active:hover,
.vt-match-picker-chip.is-active:focus-visible {
    background: color-mix(in oklab, var(--kb-primary) 85%, white);
}

/* --- Players section (chip list with own search + Match-mode toggle +
   Role toggle). Replaced the old Commanders section: the chip list now
   spans the full roster (every name that ever appeared in any match)
   and role membership is derived per-match from `team_leaders`. */

.vt-match-picker-filter-row--players {
    align-items: flex-start;
}

.vt-match-picker-players {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    flex: 1 1 auto;
    min-width: 0;
}

.vt-match-picker-players-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.vt-match-picker-players-search {
    flex: 1 1 200px;
    max-width: 280px;
}

.vt-match-picker-players-mode,
.vt-match-picker-players-role {
    flex: 0 0 auto;
}

.vt-match-picker-chipset--players {
    max-height: 132px;
    overflow-y: auto;
    padding: 0.35rem;
    border: 1px dashed var(--kb-border-subtle);
    border-radius: 0.4rem;
    background: color-mix(in oklab, var(--kb-bg-subtle) 50%, transparent);
    scrollbar-width: thin;
    scrollbar-color: var(--kb-border-subtle) transparent;
}

/* --- Active-filter badge on trigger + inline mobile toggle --- */

.vt-match-picker-trigger-badge,
.vt-match-picker-filters-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 0.35rem;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    border-radius: 999px;
    background: var(--kb-primary);
    color: var(--kb-primary-fg);
}

/* --- Clear-all button spacing --- */

.vt-match-picker-clear {
    white-space: nowrap;
}

/* --- Responsive: mobile Filters disclosure --- */

.vt-match-picker-filters-toggle {
    display: none;
    width: 100%;
    padding: 0.55rem 0.85rem;
    border: none;
    border-bottom: 1px solid var(--kb-border-subtle);
    background: transparent;
    color: var(--kb-text-primary);
    font: inherit;
    font-weight: 600;
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
    align-items: center;
    gap: 0.35rem;
}

.vt-match-picker-filters-toggle:focus-visible {
    outline: 2px solid var(--kb-primary);
    outline-offset: -2px;
}

.vt-match-picker-filters[data-expanded="true"] .vt-match-picker-filters-toggle .bi-chevron-down {
    transform: rotate(180deg);
}

@media (max-width: 768px) {
    .vt-match-picker-filters-toggle {
        display: flex;
    }

    .vt-match-picker-filters-body {
        display: none;
    }

    .vt-match-picker-filters[data-expanded="true"] .vt-match-picker-filters-body {
        display: flex;
    }

    /* Labels stack above chipsets on narrow screens for readability. */
    .vt-match-picker-filter-row {
        flex-direction: column;
        align-items: stretch;
        gap: 0.35rem;
    }

    .vt-match-picker-filter-label {
        flex: 0 0 auto;
    }

    .vt-match-picker-filter-row--controls {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/* --- Responsive --- */

@media (max-width: 768px) {
    .vt-match-picker-trigger {
        min-width: 0;
        max-width: 100%;
        width: 100%;
    }

    .vt-match-picker-trigger-name {
        max-width: 100%;
    }

    .vt-match-picker-modal .modal-dialog {
        margin: 0;
    }

    .vt-match-picker-modal .modal-content {
        min-height: 100vh;
        border-radius: 0;
    }

    .vt-match-picker-modal .modal-header {
        flex-wrap: wrap;
    }

    .vt-match-picker-search {
        order: 3;
        flex: 1 1 100%;
        max-width: 100%;
        margin-left: 0;
    }

    .vt-match-picker-grid {
        grid-template-columns: 1fr;
    }
}

/* ============================================================================
   ALL MATCHES HERO + RECENT MATCHES STRIP
   Markup in index.html (#all-matches-view): .vt-all-hero card + 4-up
   .vt-hero-stats grid + conditional .vt-hero-chips chip strip, plus a
   .vt-recent-matches block that reuses .vt-match-picker-card for each
   recent-match tile. Renderers in js/app.js: renderHeroStats(),
   renderHeroChips(), renderRecentMatches().
   ============================================================================ */

.vt-all-hero-head {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.vt-all-hero-head h4 {
    font-weight: 600;
    letter-spacing: -0.01em;
}

.vt-hero-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
}

@media (max-width: 991.98px) {
    .vt-hero-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 575.98px) {
    .vt-hero-stats {
        grid-template-columns: 1fr;
    }
}

.vt-hero-stat {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1rem 1.1rem;
    background: color-mix(in oklab, var(--kb-bg-card) 60%, transparent);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 0.55rem;
    position: relative;
    overflow: hidden;
}

.vt-hero-stat-icon {
    position: absolute;
    right: 0.75rem;
    top: 0.75rem;
    font-size: 1.25rem;
    color: var(--kb-text-muted);
    opacity: 0.5;
}

.vt-hero-stat-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--kb-text-muted);
    font-weight: 500;
}

.vt-hero-stat-value {
    font-family: 'Geist Mono', ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 1.6rem;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--kb-text-primary);
}

.vt-hero-stat-sub {
    font-size: 0.78rem;
    color: var(--kb-text-muted);
    /* Stop the optional sub-line from shoving the value down on hover or
       wrapping mid-card; truncates with ellipsis on overflow. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.vt-hero-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1rem;
}

.vt-hero-chips:empty {
    display: none;
}

.vt-hero-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    font-size: 0.78rem;
    background: color-mix(in oklab, var(--kb-bg-card) 70%, transparent);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 999px;
    color: var(--kb-text-muted);
}

.vt-hero-chip strong {
    color: var(--kb-text-primary);
    font-weight: 600;
}

.vt-recent-matches-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.75rem;
    padding: 0 0.25rem;
}

.vt-recent-matches-viewall {
    text-decoration: none;
}

.vt-recent-matches-strip {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
}

@media (max-width: 991.98px) {
    .vt-recent-matches-strip {
        display: flex;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 0.25rem;
        scrollbar-width: thin;
        scrollbar-color: var(--kb-border-subtle) transparent;
    }

    .vt-recent-matches-strip > .vt-match-picker-card {
        flex: 0 0 280px;
        scroll-snap-align: start;
    }
}

.vt-recent-matches-empty {
    padding: 1.5rem;
    text-align: center;
    color: var(--kb-text-muted);
    background: color-mix(in oklab, var(--kb-bg-card) 50%, transparent);
    border: 1px dashed var(--kb-border-subtle);
    border-radius: 0.55rem;
    grid-column: 1 / -1;
}

/* ============================================================================
   DOCS SEARCH PALETTE
   Cmd/Ctrl+K modal that fuzzy-searches the rendered DATA_DICTIONARY.md.
   Markup in docs.html (#docs-search-modal); behavior in js/docs-search.js.
   Matches the existing match-picker glass aesthetic.
   ============================================================================ */

/* Algolia-style centered trigger pill in the docs navbar. Absolutely
 * positioned inside the sticky navbar so it stays at viewport-center
 * regardless of brand / collapse-menu widths. Hidden on mobile (d-md-flex
 * on the markup); the burger menu has its own icon-button trigger. */
.vt-docs-nav {
    position: sticky; /* matches existing .sticky-top; absolute children anchor here */
}

.vt-docs-search-pill {
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.7rem 0.4rem 0.85rem;
    min-width: 320px;
    max-width: 480px;
    background: var(--kb-bg-subtle);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 999px;
    color: var(--kb-text-muted);
    font-size: 0.85rem;
    line-height: 1.2;
    cursor: pointer;
    text-align: left;
    transition: background 140ms ease, border-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
}

.vt-docs-search-pill:hover,
.vt-docs-search-pill:focus-visible {
    background: var(--kb-bg-card);
    border-color: var(--kb-primary);
    color: var(--kb-text-primary);
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--kb-primary) 18%, transparent);
}

.vt-docs-search-pill-icon {
    font-size: 1rem;
    color: var(--kb-text-muted);
    flex-shrink: 0;
}

.vt-docs-search-pill:hover .vt-docs-search-pill-icon,
.vt-docs-search-pill:focus-visible .vt-docs-search-pill-icon {
    color: var(--kb-primary);
}

.vt-docs-search-pill-label {
    flex: 1 1 auto;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.vt-docs-search-pill-kbd {
    font-family: 'Geist Mono', ui-monospace, SFMono-Regular, 'SF Mono', Consolas, monospace;
    font-size: 0.7rem;
    padding: 0.15rem 0.4rem;
    background: var(--kb-bg-card);
    color: var(--kb-text-muted);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 4px;
    line-height: 1;
    letter-spacing: 0.05em;
    flex-shrink: 0;
}

@media (min-width: 768px) {
    .vt-docs-search-pill {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        z-index: 1; /* above the right-aligned collapse menu when widths get tight */
    }
}

@media (min-width: 768px) and (max-width: 991.98px) {
    .vt-docs-search-pill {
        min-width: 240px;
    }
}

.vt-docs-search-modal .modal-dialog {
    max-width: 720px;
}

.vt-docs-search-modal .modal-content {
    background: var(--kb-bg-card);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 12px;
    box-shadow: var(--vt-shadow-elevation-3, 0 16px 48px rgba(0, 0, 0, 0.35));
    overflow: hidden;
}

.vt-docs-search-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--kb-border-subtle);
    background: var(--kb-bg-card);
}

.vt-docs-search-icon {
    color: var(--kb-text-muted);
    font-size: 1.1rem;
    flex-shrink: 0;
}

.vt-docs-search-input {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    box-shadow: none;
    color: var(--kb-text-primary);
    font-size: 1rem;
    padding: 0;
    line-height: 1.4;
}

.vt-docs-search-input:focus {
    background: transparent;
    border: none;
    outline: none;
    box-shadow: none;
    color: var(--kb-text-primary);
}

.vt-docs-search-input::placeholder {
    color: var(--kb-text-muted);
    opacity: 0.7;
}

/* Cancel the default search input clear (X) Webkit/Edge button so the layout
 * stays predictable; users have Esc + the modal close button. */
.vt-docs-search-input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.vt-docs-search-count {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.75rem;
    color: var(--kb-text-muted);
    flex-shrink: 0;
    white-space: nowrap;
}

.vt-docs-search-body {
    padding: 0;
    max-height: min(60vh, 520px);
    overflow-y: auto;
}

.vt-docs-search-results {
    list-style: none;
    margin: 0;
    padding: 0.25rem 0;
}

.vt-docs-search-result {
    margin: 0;
    padding: 0;
    border-bottom: 1px solid transparent;
}

.vt-docs-search-result-link {
    display: block;
    padding: 0.65rem 1rem;
    color: var(--kb-text-primary);
    text-decoration: none;
    transition: background 120ms ease;
    border-left: 2px solid transparent;
}

.vt-docs-search-result.is-active .vt-docs-search-result-link,
.vt-docs-search-result-link:hover {
    background: var(--kb-bg-subtle);
    border-left-color: var(--kb-primary);
    text-decoration: none;
    color: var(--kb-text-primary);
}

.vt-docs-search-result-head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.15rem;
}

.vt-docs-search-result-section {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.7rem;
    padding: 0.1rem 0.4rem;
    background: var(--kb-primary);
    color: var(--kb-primary-fg, #fff);
    border-radius: 4px;
    line-height: 1.3;
    letter-spacing: 0.03em;
    flex-shrink: 0;
}

.vt-docs-search-result-heading {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--kb-text-primary);
}

.vt-docs-search-result-breadcrumb {
    font-size: 0.72rem;
    color: var(--kb-text-muted);
    margin-bottom: 0.15rem;
    line-height: 1.4;
}

.vt-docs-search-result-breadcrumb i {
    font-size: 0.6rem;
    margin: 0 0.15rem;
    opacity: 0.6;
}

.vt-docs-search-result-snippet {
    font-size: 0.82rem;
    color: var(--kb-text-secondary);
    line-height: 1.45;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
}

.vt-docs-search-result-snippet mark {
    background: color-mix(in srgb, var(--kb-primary) 25%, transparent);
    color: var(--kb-text-primary);
    padding: 0 0.1rem;
    border-radius: 2px;
}

.vt-docs-search-empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--kb-text-muted);
    font-size: 0.9rem;
    list-style: none;
}

.vt-docs-search-footer {
    padding: 0.5rem 1rem;
    border-top: 1px solid var(--kb-border-subtle);
    background: var(--kb-bg-subtle);
    justify-content: flex-end;
}

.vt-docs-search-legend {
    font-size: 0.72rem;
    color: var(--kb-text-muted);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
}

.vt-docs-search-legend kbd {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.65rem;
    padding: 0.1rem 0.35rem;
    background: var(--kb-bg-card);
    color: var(--kb-text-secondary);
    border: 1px solid var(--kb-border-subtle);
    border-radius: 3px;
    line-height: 1;
    margin-right: 0.15rem;
}

.vt-docs-search-sep {
    opacity: 0.5;
    margin: 0 0.25rem;
}

@media (max-width: 575.98px) {
    .vt-docs-search-modal .modal-dialog {
        margin: 0;
    }

    .vt-docs-search-modal .modal-content {
        min-height: 100vh;
        border-radius: 0;
    }

    .vt-docs-search-body {
        max-height: none;
        flex: 1 1 auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .vt-docs-search-result-link {
        transition: none;
    }
}

/* ============================================================================
   Match Highlights — fixed-slate award catalog (12 cards, always-on).
   Tile is the unit; the section card uses the standard glass surface from
   `.card`. Layout uses Bootstrap row-cols utilities; tile styling lives here.
   xl breakpoint (>=1200px): 6 tiles wide, flavor copy collapses to a tooltip
   to keep tiles compact. md/lg/sm/xs: flavor copy renders inline below the
   value.
   ============================================================================ */

.vt-highlights-card .card-header h5 {
    color: var(--kb-text-primary);
}

.vt-highlight-tile {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.85rem 0.9rem;
    border-radius: 0.6rem;
    background: color-mix(in oklab, var(--kb-bg-card) 92%, transparent);
    border: 1px solid color-mix(in oklab, var(--kb-text-primary) 8%, transparent);
    box-shadow: var(--vt-shadow-elevation-1, 0 1px 2px rgba(0, 0, 0, 0.18));
    transition: border-color var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                box-shadow var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease),
                transform var(--vt-anim-duration, 150ms) var(--vt-anim-ease, ease);
}

.vt-highlight-tile:hover {
    border-color: color-mix(in oklab, var(--kb-text-primary) 16%, transparent);
    transform: translateY(-1px);
}

.vt-highlight-tile--dominant {
    border-color: color-mix(in oklab, var(--kb-primary) 45%, transparent);
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--kb-primary) 22%, transparent),
                var(--vt-shadow-elevation-1, 0 1px 2px rgba(0, 0, 0, 0.18));
}

.vt-highlight-tile--dominant:hover {
    border-color: color-mix(in oklab, var(--kb-primary) 65%, transparent);
}

.vt-highlight-tile-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--kb-text-secondary);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.vt-highlight-tile-icon {
    font-size: 0.95rem;
    color: var(--kb-primary);
}

.vt-highlight-tile--dominant .vt-highlight-tile-icon {
    color: var(--kb-primary);
    filter: drop-shadow(0 0 4px color-mix(in oklab, var(--kb-primary) 45%, transparent));
}

.vt-highlight-tile-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-highlight-tile-winner {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--kb-text-primary);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Keep pair winners ("A vs B") on one row when possible; clamp at two. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.vt-highlight-tile-vs {
    color: var(--kb-text-muted);
    font-weight: 500;
    margin: 0 0.3rem;
}

.vt-highlight-tile-value {
    font-family: var(--vt-font-mono, "Geist Mono", ui-monospace, monospace);
    font-size: 1.45rem;
    font-weight: 600;
    color: var(--kb-text-primary);
    line-height: 1.05;
    letter-spacing: -0.01em;
}

.vt-highlight-tile--dominant .vt-highlight-tile-value {
    color: var(--kb-primary);
}

/* Unit suffix on the headline value. Smaller, regular weight, system font
   (Geist Sans renders short word units cleaner than mono); muted color so
   the big number remains the visual anchor. Slight vertical lift makes the
   unit read as a label rather than competing with the value baseline. */
.vt-highlight-tile-value-unit {
    font-family: var(--vt-font-system, "Geist", system-ui, sans-serif);
    font-size: 0.55em;
    font-weight: 500;
    color: var(--kb-text-muted);
    letter-spacing: 0;
    margin-left: 0.2em;
    vertical-align: 0.2em;
}

/* Schema-v2 breakdown line: pre-computed context that gives the headline value
   meaning ("4.00" -> "12K / 3D (4.00)"). Sits between the big value and the
   runner-up line; visible at every breakpoint (unlike `vt-highlight-tile-copy`
   which xl hides). Names are inline-bold; numerics use the mono stack so digits
   align across cards. */
.vt-highlight-tile-breakdown {
    font-size: 0.78rem;
    line-height: 1.35;
    color: var(--kb-text-secondary);
    font-variant-numeric: tabular-nums;
}

.vt-highlight-tile-copy {
    font-size: 0.78rem;
    line-height: 1.35;
    color: var(--kb-text-secondary);
    /* Wraps gracefully on small/medium tiles; xl hides this and uses a tooltip. */
}

.vt-highlight-tile-runner {
    font-size: 0.74rem;
    color: var(--kb-text-muted);
    margin-top: auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vt-highlight-tile-runner-val {
    color: var(--kb-text-secondary);
    font-family: var(--vt-font-mono, "Geist Mono", ui-monospace, monospace);
    margin-left: 0.25rem;
}

.vt-highlight-tile-runner--solo {
    font-style: italic;
}

/* Compact xl layout: 6 tiles wide, drop the flavor copy and lean on the
   tooltip (rendered via the `title` attr by renderHighlights). */
@media (min-width: 1200px) {
    .vt-highlight-tile {
        padding: 0.75rem 0.8rem;
        gap: 0.3rem;
    }

    .vt-highlight-tile-copy {
        display: none;
    }

    /* Keep the breakdown visible on xl, but force a single-line ellipsis to
       protect tile width. The tooltip (carrying the flavor copy) provides
       any overflow narrative. */
    .vt-highlight-tile-breakdown {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: 0.74rem;
    }

    .vt-highlight-tile-value {
        font-size: 1.3rem;
    }

    .vt-highlight-tile-winner {
        font-size: 0.9rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .vt-highlight-tile {
        transition: none;
    }

    .vt-highlight-tile:hover {
        transform: none;
    }
}

/* ============================================================================
   VTSR-T LEADERBOARD + 5-TIER LADDER
   Render-layer presentation for the All Matches → Overview tab.
   Tier color tokens lean on the existing --kb-* palette where possible
   (Tier 3 picks up project blue so the anchor band matches the brand).
   ============================================================================ */

:root {
    --vt-tier-1: #f5c518;                     /* Tier 1 — gold */
    --vt-tier-2: #84d6e6;                     /* Tier 2 — silver-cyan */
    --vt-tier-3: var(--kb-primary);           /* Tier 3 — anchor band, brand */
    --vt-tier-4: #f0a93b;                     /* Tier 4 — warm amber */
    --vt-tier-5: var(--kb-text-muted);        /* Tier 5 — muted slate (wide band) */
}

.vt-tier-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.1rem;
    padding: 0.1rem 0.45rem;
    border-radius: 0.4rem;
    font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-weight: 600;
    font-size: 0.78rem;
    line-height: 1.2;
    color: var(--kb-bg-primary);
    background: var(--kb-text-muted);  /* default for unknown tier */
    cursor: default;
    user-select: none;
}

.vt-tier-badge.vt-tier-1 { background: var(--vt-tier-1); color: #1a1306; }
.vt-tier-badge.vt-tier-2 { background: var(--vt-tier-2); color: #061520; }
.vt-tier-badge.vt-tier-3 { background: var(--vt-tier-3); color: var(--kb-bg-primary); }
.vt-tier-badge.vt-tier-4 { background: var(--vt-tier-4); color: #1a1006; }
.vt-tier-badge.vt-tier-5 {
    background: color-mix(in oklab, var(--vt-tier-5) 60%, transparent);
    color: var(--kb-text-primary);
}

.vt-vtsr-provisional {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.1rem;
    padding: 0.1rem 0.45rem;
    border-radius: 0.4rem;
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-weight: 600;
    font-size: 0.78rem;
    line-height: 1.2;
    color: var(--kb-text-muted);
    background: color-mix(in oklab, var(--kb-text-muted) 22%, transparent);
    border: 1px dashed color-mix(in oklab, var(--kb-text-muted) 38%, transparent);
    cursor: default;
    user-select: none;
}

.vt-vtsr-delta-positive { color: var(--kb-success); }
.vt-vtsr-delta-negative { color: var(--kb-danger); }

.vt-vtsr-rating {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-weight: 600;
    font-size: 0.92rem;
    color: var(--kb-text-primary);
    letter-spacing: -0.01em;
}

#vtsr-table tbody tr {
    cursor: pointer;
}

/* "How It's Calculated" button next to the VTSR-T fullscreen icon. Borderless,
   muted, with the same hover treatment as the surrounding card-header icon
   buttons so the pair reads as a single control cluster. */
.vt-vtsr-info-btn {
    border: 0;
    background: transparent;
    color: var(--kb-text-muted);
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.25rem 0.55rem;
}

.vt-vtsr-info-btn:hover,
.vt-vtsr-info-btn:focus-visible {
    color: var(--kb-text-primary);
    background: color-mix(in oklab, var(--kb-text-muted) 12%, transparent);
}

/* ============================================================================
   KATEX TOOLTIP
   Override Bootstrap tooltip width + KaTeX glyph color so equations pick
   up the theme foreground in both light and dark modes.

   The shared .vt-katex-tooltip class is reused on the modal body that
   opens from the VTSR-T Leaderboard's "How It's Calculated" button so it
   inherits the same equation-spacing rules below. The width cap is
   scoped to tooltip context only — applying max-width: 600px to a modal
   body would visually shrink the dialog content even though the dialog
   itself is .modal-lg, so we exclude that context here.
   ============================================================================ */

.vt-katex-tooltip:not(.modal-body) {
    --bs-tooltip-max-width: 600px;
    max-width: 600px;
}

.vt-katex-tooltip .tooltip-inner {
    text-align: left;
    padding: 0.85rem 1rem;
    font-size: 0.85rem;
    line-height: 1.55;
    background: var(--kb-bg-secondary);
    color: var(--kb-text-primary);
    border: 1px solid color-mix(in oklab, var(--kb-text-muted) 25%, transparent);
}

.vt-katex-tooltip .tooltip-arrow::before { display: none; }

.vt-katex-tooltip .vt-katex-tooltip-body { line-height: 1.55; }

.vt-katex-tooltip .katex-display {
    margin: 0.95em 0 0.8em;
    line-height: 1.4;
}

.vt-katex-tooltip .katex {
    font-size: 1.0em;
    line-height: 1.4 !important;
}

.vt-katex-tooltip .vt-katex-tooltip-body strong {
    display: inline-block;
    margin-top: 0.45em;
}

.vt-katex-tooltip table {
    width: 100%;
    margin: 0.55rem 0;
    font-size: 0.78rem;
}

.vt-katex-tooltip table th,
.vt-katex-tooltip table td {
    padding: 0.18rem 0.4rem;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-muted) 18%, transparent);
}

.vt-katex-tooltip table th {
    color: var(--kb-text-muted);
    font-weight: 600;
    text-align: left;
}

.vt-katex-tooltip .vt-katex-caveat {
    color: var(--kb-text-muted);
    font-size: 0.78rem;
    margin: 0.45em 0;
}

.vt-katex-tooltip a { color: var(--kb-primary); }

/* Modal variant — the VTSR-T methodology button opens #vtsr-methodology-modal
   whose body carries .vt-katex-tooltip so the equation-spacing rules above
   apply inside the modal too. The modal body has much more room than a
   tooltip, so restore a comfortable reading size for the prose. */
.modal-body.vt-katex-tooltip {
    font-size: 0.95rem;
    line-height: 1.55;
}

.modal-body.vt-katex-tooltip .vt-katex-tooltip-body { line-height: 1.55; }

/* VTSR-T methodology modal — v2 (Phase 12) structured-reference layout.
   The body is divided into six titled <section class="vt-vtsr-doc-section">
   blocks (golden equation / expected curve / composite / K & hope / tiers /
   worked example). Each section is separated by a subtle bottom border so
   the reference reads like a doc page rather than a long blob. */
.modal-body.vt-katex-tooltip .vt-vtsr-doc-section {
    padding: 1.1rem 0;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-muted) 18%, transparent);
}
.modal-body.vt-katex-tooltip .vt-vtsr-doc-section:first-of-type { padding-top: 0; }
.modal-body.vt-katex-tooltip .vt-vtsr-doc-section:last-of-type {
    padding-bottom: 0.5rem;
    border-bottom: 0;
}
.modal-body.vt-katex-tooltip .vt-vtsr-doc-section h6 {
    color: var(--kb-text-muted);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin: 0 0 0.85rem 0;
}

/* Symbol legend grid — 2 columns under the hero equation. Each cell pairs
   a <code> symbol with a brief description. */
.modal-body.vt-katex-tooltip .vt-vtsr-doc-symbols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem 1.2rem;
    margin: 0.75rem 0;
    font-size: 0.86rem;
}
.modal-body.vt-katex-tooltip .vt-vtsr-doc-symbols code {
    color: var(--kb-primary);
    margin-right: 0.4rem;
}

/* Compact 2/3-column tables used by the expected-curve, K-decay, and tier
   sections. Slightly tighter than the legacy .vt-katex-tiers / .vt-katex-weights
   tables so the dense data reads at a glance. */
.modal-body.vt-katex-tooltip .vt-vtsr-doc-curve-table {
    width: auto;
    min-width: 50%;
    margin: 0.65rem 0;
    font-size: 0.86rem;
}
.modal-body.vt-katex-tooltip .vt-vtsr-doc-curve-table th,
.modal-body.vt-katex-tooltip .vt-vtsr-doc-curve-table td {
    padding: 0.3rem 1rem 0.3rem 0;
}
.modal-body.vt-katex-tooltip .vt-vtsr-doc-curve-table th {
    color: var(--kb-text-muted);
    font-weight: 500;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-muted) 25%, transparent);
}

/* KaTeX ships hard-coded color: #000 on .katex; force it to follow the
   theme so equations stay legible in dark mode. */
.katex { color: inherit; }

/* ===== VTSR-T v2.3 — Loadout Profile + Per-Class Combat + chips ===== */

/* Compact PvP/PvE chip rendered next to the kills/deaths total in the
   Player Leaderboard + Career Leaderboard tables. The total stays as
   the primary number; the chip is a small, muted parenthetical so the
   row reads as TOTAL (PvP/PvE). Tooltip surfaces the full split. */
.vt-kd-split {
    color: var(--kb-text-muted);
    font-size: 0.85em;
    font-variant-numeric: tabular-nums;
    margin-left: 0.15em;
}

/* Loadout Profile card. Stacked horizontal bar + per-class list,
   shown inside renderPlayerProfile and the All Matches Career card.
   Uses the same chart-palette tokens as the Combat Timeline so a
   "wingman" segment renders the same color across the whole UI. */
.vt-loadout-card {
    border: 1px solid var(--kb-border-subtle);
    border-radius: var(--kb-radius-md, 6px);
    padding: 0.75rem 0.9rem;
    background: color-mix(in srgb, var(--kb-bg-card) 60%, transparent);
}
.vt-loadout-bar {
    display: flex;
    height: 14px;
    width: 100%;
    border-radius: 999px;
    overflow: hidden;
    background: color-mix(in srgb, var(--kb-text-muted) 10%, transparent);
    margin-bottom: 0.6rem;
}
.vt-loadout-bar-seg {
    height: 100%;
    transition: opacity 120ms ease;
    cursor: default;
}
.vt-loadout-bar-seg:hover {
    opacity: 0.85;
}
.vt-loadout-classlist {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 0.25rem 1rem;
    font-size: 0.85rem;
}
.vt-loadout-classlist li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--kb-text-secondary);
}
.vt-loadout-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex-shrink: 0;
}
.vt-loadout-ship {
    color: var(--kb-text-primary);
    font-weight: 500;
}
.vt-loadout-share {
    color: var(--kb-text-secondary);
    font-variant-numeric: tabular-nums;
}
.vt-loadout-time {
    color: var(--kb-text-muted);
    font-size: 0.92em;
    font-variant-numeric: tabular-nums;
    margin-left: auto;
}

/* Per-Class Combat table. Shown immediately below the Loadout bar.
   Compact rows — one per ship class with time>0. PvE K column is
   muted (not zeroed) to keep PvP K visually primary. */
.vt-pcc-card {
    margin-top: 0.75rem;
}
.vt-pcc-table th {
    color: var(--kb-text-muted);
    font-weight: 500;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-muted) 25%, transparent);
    padding: 0.35rem 0.5rem;
}
.vt-pcc-table td {
    padding: 0.35rem 0.5rem;
    font-size: 0.86rem;
    color: var(--kb-text-secondary);
    border-top: 1px solid color-mix(in oklab, var(--kb-text-muted) 12%, transparent);
}
.vt-pcc-table tbody tr:first-child td {
    border-top: 0;
}

/* Player weapon-breakdown table (with v2.3 PvP Hits + PvP Acc cols).
   Same compact aesthetic as the per-class combat table. */
.vt-wb-card {
    margin-top: 0.75rem;
}
.vt-wb-table th {
    color: var(--kb-text-muted);
    font-weight: 500;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid color-mix(in oklab, var(--kb-text-muted) 25%, transparent);
    padding: 0.35rem 0.5rem;
}
.vt-wb-table td {
    padding: 0.35rem 0.5rem;
    font-size: 0.86rem;
    color: var(--kb-text-secondary);
    border-top: 1px solid color-mix(in oklab, var(--kb-text-muted) 12%, transparent);
}
.vt-wb-table tbody tr:first-child td {
    border-top: 0;
}

/* VTSR-T leaderboard expandable rows + detail panel (v2.3 polish).
   Replaces the prior popover/tooltip pattern with always-discoverable
   inline drill-down. Each visible row pairs with a sibling
   `<tr class="collapse vt-vtsr-detail">` that hosts a 5-section panel
   in a 2-column responsive grid. Sort + filter re-renders preserve
   expand state via the module-local `expandedVtsrRows` Set. */
.vt-vtsr-expand-col { width: 32px; padding-left: 0; padding-right: 0; }
.vt-row-expand {
    background: transparent;
    border: 0;
    padding: 0.15rem 0.35rem;
    color: var(--kb-text-muted);
    cursor: pointer;
    transition: transform 150ms ease, color 120ms ease;
    line-height: 1;
}
.vt-row-expand:hover { color: var(--kb-primary); }
.vt-row-expand[aria-expanded="true"] {
    transform: rotate(90deg);
    color: var(--kb-text-primary);
}
.vt-row-expand:focus-visible {
    outline: 2px solid var(--kb-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

.vt-vtsr-detail > td {
    padding: 0;
    background: color-mix(in srgb, var(--kb-bg-card) 70%, transparent);
    border-top: 1px solid var(--kb-border-subtle);
}
.vt-vtsr-detail-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
    padding: 1rem 1.25rem;
}
@media (max-width: 1199.98px) {
    .vt-vtsr-detail-grid { grid-template-columns: 1fr; }
}
.vt-vtsr-detail-col {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.vt-vtsr-detail-section {
    border: 1px solid var(--kb-border-subtle);
    border-radius: var(--kb-radius-md, 6px);
    padding: 0.75rem 0.9rem;
    background: var(--kb-bg-card);
}
.vt-vtsr-detail-section h6 {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--kb-text-muted);
    margin-bottom: 0.55rem;
}
.vt-vtsr-detail-section .vt-vtsr-detail-sub {
    font-size: 0.7rem;
    text-transform: none;
    letter-spacing: normal;
    margin-left: 0.3rem;
}

/* Section A: combat split stats grid */
.vt-vtsr-detail-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem 1rem;
}
.vt-vtsr-detail-stats > div { display: flex; flex-direction: column; }
.vt-vtsr-detail-stats .vt-stat-label {
    color: var(--kb-text-muted);
    font-size: 0.74rem;
    line-height: 1;
    margin-bottom: 0.15rem;
}
.vt-vtsr-detail-stats .vt-stat-value {
    color: var(--kb-text-primary);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* Sections B+C: 8-axis horizontal bar grid (per-axis z-score with
   weighted contribution sub-text). Each row has an axis name | bar
   centered on 0 (extends right for positive, left for negative) |
   z value (color-coded) + optional w*z weighted contribution. */
.vt-axis-bar-grid {
    display: flex;
    flex-direction: column;
    gap: 0.18rem;
}
.vt-axis-bar-row {
    display: grid;
    grid-template-columns: minmax(110px, 1fr) minmax(120px, 2fr) minmax(140px, auto);
    gap: 0.6rem;
    align-items: center;
    font-variant-numeric: tabular-nums;
}
.vt-axis-bar-name {
    color: var(--kb-text-secondary);
    font-size: 0.78rem;
}
.vt-axis-bar-track {
    position: relative;
    display: block;
    height: 8px;
    background: color-mix(in srgb, var(--kb-text-muted) 10%, transparent);
    border-radius: 4px;
}
.vt-axis-bar-center {
    position: absolute;
    left: 50%;
    top: -2px;
    bottom: -2px;
    width: 1px;
    background: color-mix(in srgb, var(--kb-text-muted) 50%, transparent);
}
.vt-axis-bar-fill {
    position: absolute;
    top: 0;
    height: 100%;
    border-radius: 4px;
}
.vt-axis-bar-row.is-positive .vt-axis-bar-fill {
    background: var(--kb-success);
}
.vt-axis-bar-row.is-negative .vt-axis-bar-fill {
    background: var(--kb-danger);
}
.vt-axis-bar-z {
    text-align: right;
    color: var(--kb-text-secondary);
    font-size: 0.78rem;
}
.vt-axis-bar-row.is-positive .vt-axis-bar-z { color: var(--kb-success); }
.vt-axis-bar-row.is-negative .vt-axis-bar-z { color: var(--kb-danger); }
.vt-axis-bar-weighted {
    color: var(--kb-text-muted);
    font-size: 0.7rem;
    margin-left: 0.4rem;
}

.vt-vtsr-detail-formula {
    color: var(--kb-text-secondary);
    font-size: 0.78rem;
    font-family: var(--bs-font-monospace);
    margin-bottom: 0.6rem;
}

/* Section D: ship loadout mini-rows (top 5 by time). */
.vt-vtsr-detail-loadout-row {
    display: grid;
    grid-template-columns: minmax(120px, 1.5fr) minmax(80px, 2fr) 60px 60px 70px;
    gap: 0.5rem;
    align-items: center;
    padding: 0.18rem 0;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}
.vt-vtsr-detail-loadout-name {
    color: var(--kb-text-primary);
    font-weight: 500;
}
.vt-vtsr-detail-loadout-bar {
    position: relative;
    display: block;
    height: 6px;
    background: color-mix(in srgb, var(--kb-text-muted) 10%, transparent);
    border-radius: 3px;
}
.vt-vtsr-detail-loadout-bar-fill {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    background: var(--kb-primary);
    border-radius: 3px;
}
.vt-vtsr-detail-loadout-share,
.vt-vtsr-detail-loadout-time,
.vt-vtsr-detail-loadout-kd {
    color: var(--kb-text-secondary);
    text-align: right;
}
.vt-vtsr-detail-loadout-more {
    margin-top: 0.3rem;
    font-size: 0.74rem;
}

/* Section E: peak rating callout. */
.vt-vtsr-detail-peak {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    font-variant-numeric: tabular-nums;
}
.vt-vtsr-detail-peak-value {
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--kb-text-primary);
}
.vt-vtsr-detail-peak-label {
    font-size: 0.78rem;
}

/* Primary ship chip on the VTSR-T leaderboard. Small badge sized
   to align with the existing Tier badge column. (Token name kept as
   `vt-vtsr-primary-class` for backwards-CSS-token-stability; renders
   ship names like "Tank", "Scout" in v2.3+.) */
.vt-vtsr-primary-class {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.72rem;
    background: color-mix(in srgb, var(--kb-text-muted) 15%, transparent);
    color: var(--kb-text-secondary);
    border: 1px solid var(--kb-border-subtle);
    text-transform: lowercase;
    letter-spacing: 0.02em;
}

