/* iA Writer Quattro S — the editorial workhorse. Becomes the default
   body font (replacing Funnel Display). Loaded from jsDelivr's
   mirror of the iA-Fonts repo (SIL OFL). Funnel Display is kept as
   fallback for legacy callers and as a stylistic option, 7-Segment
   stays for digital LCD-style numerics (chrono, lap counter, etc.). */
@font-face {
    font-family: 'iA Writer Quattro';
    src: url('https://cdn.jsdelivr.net/gh/iaolo/iA-Fonts@master/iA%20Writer%20Quattro/Static/iAWriterQuattroS-Regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'iA Writer Quattro';
    src: url('https://cdn.jsdelivr.net/gh/iaolo/iA-Fonts@master/iA%20Writer%20Quattro/Static/iAWriterQuattroS-Italic.ttf') format('truetype');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: 'iA Writer Quattro';
    src: url('https://cdn.jsdelivr.net/gh/iaolo/iA-Fonts@master/iA%20Writer%20Quattro/Static/iAWriterQuattroS-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'iA Writer Quattro';
    src: url('https://cdn.jsdelivr.net/gh/iaolo/iA-Fonts@master/iA%20Writer%20Quattro/Static/iAWriterQuattroS-BoldItalic.ttf') format('truetype');
    font-weight: 700;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Funnel Display';
    src: url('../assets/Tipografia/Funnel_Display/FunnelDisplay-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 900;
    font-style: normal;
}

@font-face {
    font-family: '7-Segment';
    src: url('../assets/Tipografia/7segment.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
}

:root {
    /* ============== Colors ============== */
    --White: #FFF;
    --White-8:  rgba(255, 255, 255, 0.08);
    --White-20: rgba(255, 255, 255, 0.20);
    --White-24: rgba(255, 255, 255, 0.24);
    --White-40: rgba(255, 255, 255, 0.40);
    --White-56: rgba(255, 255, 255, 0.56);
    --White-Stroke: rgba(255, 255, 255, 0.6);
    --Black: #000;
    --Black-Linear: linear-gradient(180deg, #2A2A2A 0%, #1A1A1A 100%);
    --Red: #e30613;
    --Red-Glow: rgba(227, 6, 19, 0.5);
    --Amber: #BE990A;
    --Green: #0BA805;
    --Purple-FL: #B450FF;

    /* ============== Border-radius scale ============== */
    --r-xs:   4px;
    --r-sm:   8px;
    --r-md:  12px;
    --r-lg:  16px;
    --r-xl:  24px;
    --r-pill: 999px;

    /* ============== Spacing scale (base 4) ============== */
    --s-1:  4px;
    --s-2:  8px;
    --s-3: 12px;
    --s-4: 16px;
    --s-5: 20px;
    --s-6: 24px;
    --s-8: 32px;

    /* ============== Glow tokens — UN solo lenguaje para "active" ============== */
    --glow-active-short: 0 0 7px rgba(255, 255, 255, 0.70);
    --glow-active-long:  0 0 24px rgba(255, 255, 255, 0.35);
    --glow-active: var(--glow-active-short), var(--glow-active-long);
    --glow-red: 0 0 12px rgba(227, 6, 19, 0.55);

    /* HDR "screen-luminance" tokens for white UI elements that should
       read like real emissive displays (timer LCDs, active menu
       labels, pilot principal text, white pill chrome). Layered
       multi-radius text-shadows simulate the way a backlit pixel
       blooms slightly on a monitor. */
    --glow-hdr-soft:   0 0 4px  rgba(255, 255, 255, 0.55),
                       0 0 10px rgba(255, 255, 255, 0.22);
    --glow-hdr-strong: 0 0 6px  rgba(255, 255, 255, 0.85),
                       0 0 14px rgba(255, 255, 255, 0.45),
                       0 0 28px rgba(255, 255, 255, 0.20);

    /* ============== Focus rings ============== */
    --ring-focus: 0 0 0 2px var(--White-56);
    --ring-active: 0 0 0 2px var(--White);

    /* ============== Easing + durations ============== */
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in: cubic-bezier(0.55, 0, 0.78, 0.3);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
    --ease-snap: cubic-bezier(0.5, 1.8, 0.4, 1);
    --dur-fast: 120ms;
    --dur-base: 220ms;
    --dur-slow: 480ms;
    --dur-x: 800ms;

    /* ============== Glass surfaces ==============
       Liquid-glass language for floating panels (NOT the timer
       marker, which keeps its heavier solid treatment). The bg is
       intentionally translucent so the backdrop-filter blur can
       pick up colour from what's behind. The 1px inset white +
       1px inset dark together read as the "overlay" rim the user
       asked for.
       --glass-bg-tint is a placeholder colour each surface can
       override to inject pilot/team tint into the glass. */
    --glass-bg-tint: rgba(20, 20, 24, 0.42);
    --glass-bg: linear-gradient(180deg, rgba(36, 36, 40, 0.55) 0%, rgba(16, 16, 20, 0.55) 100%);
    --glass-border: 1px solid rgba(0, 0, 0, 0.55);
    --glass-overlay:
        0 1px 0 0 rgba(255, 255, 255, 0.12) inset,
        0 -1px 0 0 rgba(0, 0, 0, 0.40) inset;
    --glass-shadow: 0 10px 28px -10px rgba(0, 0, 0, 0.55);
    --glass-blur: 18px;
    --glass-saturate: 1.4;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

*:focus { outline: none; }
*:focus-visible {
    outline: none;
    box-shadow: var(--ring-focus);
    border-radius: var(--r-xs);
}

body {
    /* iA Writer Quattro becomes the project default — editorial,
       slightly heavier than Funnel Display at the same px size, with
       cleaner numerals and a more confident voice. Funnel Display
       lives as a fallback (and is still used by a handful of legacy
       opt-in callers). Base size bumped 14 → 15px to give the new
       font room to breathe; line-height nudged for the same reason. */
    font-family: 'iA Writer Quattro', 'Funnel Display', system-ui, sans-serif;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.45;
    letter-spacing: 0.005em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background-color: #1a1a1a;
    color: #ffffff;
    min-height: 100vh;
    position: relative;
    opacity: 0;
    transition: opacity var(--dur-x) var(--ease-out);
}

body.is-ready { opacity: 1; }

/* ============================================================
   Entry choreography — Ferrari-grade cascade.
   Order: red stripe → menu items ONE BY ONE → timer marker →
   empezar → pilot list → [1s pause] → canvas + blurs.
   The UI assembles itself first (so the user understands the
   instrument cluster); only then does the track scenery wash
   in behind it.
   ============================================================ */
.top-bar,
.menu-item,
.timer-section,
.submenu,
.cinema-veil,
.progressive-blur,
.zoom-control {
    transition:
        opacity 380ms var(--ease-out),
        transform 520ms var(--ease-out),
        filter 480ms var(--ease-out);
}
/* Canvas reveal is a longer, gentler fade — it's the background
   washing in, not a foreground element. */
#game-canvas {
    transition:
        opacity 900ms var(--ease-out),
        transform 900ms var(--ease-out);
}
/* .pilot-list deliberately omitted from the shared block — it has
   its own richer multi-prop transition above so the seamless full
   ⇄ sidebar morph animates padding/width/etc. */

/* Initial cloaked state (body has no .is-ready yet). Note: no CSS
   filter on #game-canvas — even one-shot blur on a fullscreen WebGL
   canvas hitches the GPU compositor on weaker setups, so we reveal
   with opacity + scale only. */
body:not(.is-ready) .top-bar          { transform: scaleX(0.6); opacity: 0; transform-origin: center; }
body:not(.is-ready) #game-canvas      { opacity: 0; transform: scale(1.015); transform-origin: 50% 60%; }
body:not(.is-ready) .menu-item        { opacity: 0; transform: translateY(-4px); }
body:not(.is-ready) .timer-section    { opacity: 0; transform: translateX(-50%) translateY(-12px) scale(0.96); }
body:not(.is-ready) .submenu          { opacity: 0; transform: translateX(-50%) translateY(8px); }
body:not(.is-ready) .pilot-list       { opacity: 0; transform: translateY(16px); }
body:not(.is-ready) .cinema-veil      { opacity: 0; }
body:not(.is-ready) .progressive-blur { opacity: 0; }
body:not(.is-ready) .zoom-control     { opacity: 0; transform: translateY(8px); }

/* Choreography — UI assembles first, track washes in 1s later.
   Stripe (0ms) → menu items 1..N one by one (200–700ms) → timer
   (820ms) → empezar (940ms) → pilot list (1060ms) → [1s breath]
   → canvas + cinema layers (1750ms+). */
body.is-ready .top-bar       { transition-delay:    0ms; }
/* Per-menu-item stagger: each .menu-item exposes --enter-delay (set
   by main.js based on its index) so they fan in one by one
   regardless of how many dividers sit between them in the DOM. */
body.is-ready .menu-item     { transition-delay: var(--enter-delay, 200ms); }
body.is-ready .timer-section { transition-delay:  820ms; }
body.is-ready .submenu       { transition-delay:  940ms; }
body.is-ready .pilot-list    { transition-delay: 1060ms; }
/* 1-second breath between the UI settling and the track washing in */
body.is-ready #game-canvas   { transition-delay: 1750ms; }
body.is-ready.cinema-on .progressive-blur { transition-delay: 2050ms; }
body.is-ready.cinema-on .cinema-veil      { transition-delay: 2150ms; }
body.is-ready .zoom-control  { transition-delay: 2250ms; }

body::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-image: url('../assets/texture.png');
    background-repeat: repeat;
    background-size: auto;
    opacity: 0.18;
    pointer-events: none;
    z-index: -1;
}

#game-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    display: block;
    z-index: 0;
    background: #06070b;
    transition: opacity var(--dur-slow) var(--ease-out);
}

/* "vista 3D off" — hide the canvas AND the cinema veil. The render
   loop also skips composer.render in this state (see startLoop). Race
   state, HUD, audio all keep running so it's a perf escape hatch with
   zero progress loss. */
body.no-3d #game-canvas,
body.no-3d .cinema-veil { opacity: 0; pointer-events: none; }
body.no-3d {
    /* When 3D is hidden we promote the page background to something
       that reads like a "spectator mode" — a tasteful deep gradient
       behind the HUD so it doesn't look like the canvas just crashed. */
    background:
        radial-gradient(ellipse 80% 50% at 50% -10%, rgba(227, 6, 19, 0.10) 0%, rgba(0, 0, 0, 0) 60%),
        linear-gradient(180deg, #14171c 0%, #0a0c10 100%);
}

/* ============================================================
   Progressive blur — a frosted gradient that sits over the canvas
   from the very top of the viewport down to roughly mid-screen,
   easing from heavily-blurred-and-slightly-darkened at the very
   top to fully transparent at the midpoint. Reads as "natural
   light falling from above onto the diorama", soft-focuses the
   distant background, and gives the HUD breathing room above the
   focal action zone.

   Gated by body.cinema-on because backdrop-filter over 50vh of
   fullscreen canvas is the second-most expensive operation here
   after raw WebGL — users who turned cinema off get a clean,
   unblurred view by design.

   Only ONE blur layer (not the stacked-multi-blur Apple uses) to
   keep cost bounded on weaker GPUs.
   ============================================================ */
.progressive-blur {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Height is the measured BOTTOM Y of the deepest HUD chrome
       element (submenu/EMPEZAR) + a small feather. Set from JS
       via --hud-bottom on :root so the blur sits EXACTLY where the
       UI lives — never wasting GPU on empty canvas below. Fallback
       to a sensible default if the JS hasn't measured yet. */
    height: calc(var(--hud-bottom, 240px) + 40px);
    pointer-events: none;
    /* z-index 1 — above canvas (z:0), below all HUD chrome
       (z ≥ 5 top-bar, ≥ 9 pilot-list, 10 timer, 11 submenu). */
    z-index: 1;
    opacity: 0;
    transform: translateZ(0);
    will-change: opacity;
    background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0.62) 0%,
        rgba(0, 0, 0, 0.42) 45%,
        rgba(0, 0, 0, 0.18) 78%,
        rgba(0, 0, 0, 0)    100%
    );
    backdrop-filter: blur(10px) saturate(1.05);
    -webkit-backdrop-filter: blur(10px) saturate(1.05);
    /* Mask aligned to height — last 40px of the layer feathers to
       transparent so the cut from blurred → sharp track is invisible. */
    -webkit-mask-image: linear-gradient(
        to bottom,
        black 0%,
        rgba(0,0,0,0.92) 60%,
        rgba(0,0,0,0.55) 82%,
        transparent 100%
    );
    mask-image: linear-gradient(
        to bottom,
        black 0%,
        rgba(0,0,0,0.92) 60%,
        rgba(0,0,0,0.55) 82%,
        transparent 100%
    );
    transition: opacity 380ms var(--ease-out),
                height 280ms var(--ease-out);
}

body.cinema-on .progressive-blur { opacity: 1; }
/* When the 3D view is hidden there's nothing meaningful to blur, so
   we also collapse the layer. */
body.no-3d .progressive-blur { opacity: 0; }

/* ============================================================
   Cinema mode — opt-in vignette overlay on top of the canvas.
   Toggleable via key 'C'. Persisted to localStorage. Default = on.
   Sits above canvas (z=1) but below .app HUD (z=10+) so the HUD
   stays crisp. We avoid CSS `filter` and `mix-blend-mode` on the
   WebGL canvas — both trigger a compositor readback that kills
   FPS. A plain alpha radial gradient, promoted to its own GPU
   layer, composites cheaply.
   ============================================================ */
.cinema-veil {
    position: fixed;
    inset: 0;
    pointer-events: none;
    /* z-index = 0 (matching #game-canvas at z:0) — the veil sits
       directly on top of the canvas in DOM order (canvas is line
       30, veil is line 32) so it darkens the 3D scene, but EVERY
       HUD element (.app z:1, .top-bar z:5, .timer-section z:10,
       .submenu z:11, .pilot-list inside .app) paints OVER it.
       User explicitly asked: "no debe ni sobre franja roja ni
       cronómetro ni empezar, solo sobre el circuito". */
    z-index: 0;
    opacity: 0;
    transform: translateZ(0);
    will-change: opacity;
    transition: opacity 320ms var(--ease-out);
    /* Stronger gradient (was 0/45/80/100, 0/0/0.30/0.62) — user
       reported the vignette read clearly during the entry choreo
       but vanished once the bright race canvas filled the centre.
       The inner clear region is smaller and the outer darken
       deeper so the cinema edges hold up against the racing
       brightness + bloom. */
    background: radial-gradient(
        ellipse 78% 68% at 50% 52%,
        rgba(0,0,0,0) 0%,
        rgba(0,0,0,0) 35%,
        rgba(0,0,0,0.22) 60%,
        rgba(0,0,0,0.55) 85%,
        rgba(0,0,0,0.85) 100%
    );
    mix-blend-mode: multiply;
}

/* Cinema strength — driven by the ··· popover slider. Multiplies the
   veil + progressive-blur opacity so the user can dial cinema from
   off (0) to max (1). Default 1 ensures cinema-on starts at full
   intensity. */
body { --cinema-strength: 1; }
body.cinema-on .cinema-veil { opacity: var(--cinema-strength); }
body.cinema-on .progressive-blur { opacity: var(--cinema-strength); }

/* ============================================================
   Camera dock — bottom-right cluster of three glass pills:
     [zoom -, %, +]    [mute]    [···]
   Plus a popover that fans out above the ··· button with extra
   knobs (pitch, lights, cinema, center). Pointer-events stay
   on the pills only so the canvas underneath can be dragged.
   ============================================================ */
.camera-dock {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 12;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    pointer-events: none; /* re-enabled on the pills themselves */
}
.camera-dock > * { pointer-events: auto; }

.zoom-control {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    border-radius: 999px;
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    color: var(--White-56);
    transition: opacity 280ms var(--ease-out), transform 280ms var(--ease-out);
}
.zoom-btn {
    appearance: none;
    background: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    height: 28px;
    padding: 0 8px;
    border-radius: 999px;
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.32px;
    transition: color var(--dur-fast) var(--ease-out),
                background-color var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out);
}
.zoom-btn:hover {
    color: var(--White);
    background-color: rgba(255, 255, 255, 0.08);
}
.zoom-btn:active { transform: scale(0.94); }
.zoom-btn:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.zoom-level { font-variant-numeric: tabular-nums; }

/* Hide the zoom pill when the 3D view is off — nothing to zoom. */
body.no-3d .zoom-control { opacity: 0; pointer-events: none; transform: translateY(8px); }

/* Single-icon dock pills (mute, ···) share the same glass treatment
   as .zoom-control but as a simple circle button. */
.dock-btn {
    appearance: none;
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    color: var(--White-56);
    width: 36px;
    height: 36px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: color var(--dur-fast) var(--ease-out),
                background-color var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out);
}
.dock-btn:hover { color: var(--White); }
.dock-btn:active { transform: scale(0.94); }
.dock-btn:focus-visible { outline: none; box-shadow: var(--glass-overlay), var(--ring-focus); }

/* Mute icon swap — ico-off only shows when audio is muted */
.dock-mute .ico-off { display: none; }
.dock-mute[aria-pressed="true"] .ico-on  { display: none; }
.dock-mute[aria-pressed="true"] .ico-off { display: inline; color: var(--Red); }

/* "···" popover above the dock — fans up on click. Glass panel with
   pitch / lights / cinema sliders + a "center track" reset action. */
.dock-popover {
    position: absolute;
    right: 0;
    bottom: 100%;
    margin-bottom: 8px;
    min-width: 232px;
    padding: 12px;
    border-radius: var(--r-md);
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    opacity: 0;
    transform: translateY(6px) scale(0.97);
    transform-origin: 100% 100%;
    pointer-events: none;
    transition: opacity 220ms var(--ease-out), transform 220ms var(--ease-out);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.dock-popover.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.dock-row {
    display: grid;
    grid-template-columns: 78px 1fr 48px;
    align-items: center;
    gap: 10px;
    color: var(--White-56);
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 11px;
    letter-spacing: 0.4px;
    text-transform: uppercase;
}
.dock-row .dock-value { color: var(--White); text-align: right; font-variant-numeric: tabular-nums; }
/* Hairline separator inside the popover — splits camera knobs from
   audio-mix knobs visually without adding a label. Same subtle
   opacity as other internal dividers in the HUD. */
.dock-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.10);
    margin: 4px 2px;
    border-radius: 1px;
}
.dock-slider {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    height: 14px;
    background: transparent;
}
.dock-slider::-webkit-slider-runnable-track {
    height: 3px;
    border-radius: 3px;
    background: linear-gradient(to right, rgba(255,255,255,0.42), rgba(255,255,255,0.12));
}
.dock-slider::-moz-range-track {
    height: 3px;
    border-radius: 3px;
    background: linear-gradient(to right, rgba(255,255,255,0.42), rgba(255,255,255,0.12));
}
.dock-slider::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    margin-top: -5px;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--White);
    border: 1px solid rgba(0,0,0,0.55);
    box-shadow: 0 1px 0 rgba(0,0,0,0.4), 0 0 6px rgba(255,255,255,0.4);
    cursor: pointer;
}
.dock-slider::-moz-range-thumb {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--White);
    border: 1px solid rgba(0,0,0,0.55);
    box-shadow: 0 1px 0 rgba(0,0,0,0.4);
}
.dock-action {
    appearance: none;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.12);
    color: var(--White);
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    padding: 8px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out);
}
.dock-action:hover { background: rgba(255,255,255,0.16); }

body.no-3d .dock-popover,
body.no-3d .dock-more { opacity: 0; pointer-events: none; }

.app {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 1194px;
    margin: 0 auto;
    /* padding-top:1px breaks the margin-collapse between .app and
       its first flow child (.menu, which has margin-top:65). Without
       this, .menu's margin "escaped" through .app and pushed the
       entire .app box down by 61px — making timer-section's
       absolute `top` reference a wrong origin. */
    padding-top: 1px;
}

/* Top brand bar — proper SCALEXTRIC strip with the logo on the left
   and the action cluster (PADDOCK PASS / CLUB SCX / cart / BT /
   account) on the right. Spec follows the Framer mock the user
   shared: 916px-ish inner container, 61.4px tall, brand red
   background, 0.76px white stroke as overlay. Centered with the
   rest of .app's max-width budget. */
.top-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    width: 100vw;
    height: 65px;
    /* Pure brand red — NO gradient. User feedback: "le sobra
       degradado a la barra roja del menu". */
    background-color: #E30512;
    background-image: none;
    z-index: 5;
    /* Soft black shadow under the bar — separates from the canvas
       below the (now overlay-blend) bottom border. */
    box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
    display: flex;
    justify-content: center;
    align-items: stretch;
}
/* Bottom-only white overlay border, 80% opacity, mix-blend overlay.
   The full perimeter outline was retired — user only wants the
   inferior edge highlighted to separate the brand strip from the
   menu region. */
.top-bar::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    pointer-events: none;
    background: rgba(255, 255, 255, 0.80);
    mix-blend-mode: overlay;
    z-index: 1;
}
.top-bar-inner {
    /* The brand strip itself is full viewport width (the red colour
       extends edge-to-edge via .top-bar above), but the CONTENT
       inside the strip is clamped to the same vertical container
       as the menu below (1194px max-width) so the SCALEXTRIC logo
       sits flush with JUGADORES, and the pills sit flush with
       HISTORIAL. flex:1 + max-width because .top-bar is a flex
       parent — margin:auto wouldn't centre a flex item, but
       align-self via the parent's justify-content:center does. */
    flex: 1 1 auto;
    max-width: 1194px;
    padding: 0 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}
.top-logo {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    color: var(--White);
    line-height: 1;
    height: 100%;
}
.top-logo-svg {
    /* Exact brand SVG provided by the user — 153 × 19 viewBox.
       Scale to ~22px tall at desktop so it reads as the canonical
       SCALEXTRIC wordmark + ® emblem combined. */
    width: auto;
    height: 22px;
    display: block;
    /* HDR-white emission — same luminance language as the timer
       LCD digits + active menu items + numeric leaderboard. The
       logo isn't just "white text on red", it reads as a real
       lit panel on the brand strip. Drop-shadow is the SVG
       equivalent of text-shadow; we stack a tight bright halo
       on top of a wider soft bloom for the HDR feel. */
    filter:
        drop-shadow(0 0 1px rgba(255, 255, 255, 0.95))
        drop-shadow(0 0 6px rgba(255, 255, 255, 0.55))
        drop-shadow(0 0 16px rgba(255, 255, 255, 0.22));
}
@media (max-width: 1023px) {
    .top-logo-svg { height: 18px; }
}

.top-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.top-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 34px;
    padding: 0 20px;
    border-radius: 6px;
    /* Slanted SCALEXTRIC chrome — pill is skewed -8° so it matches
       the brand's italic geometry; text content is COUNTER-skewed
       so the letters stay upright. Border is painted on the ::after
       layer with mix-blend-mode: overlay (Figma spec) so the red
       brand colour shows through and the stroke reads as a true
       overlay-blend hairline. The label itself stays as a regular
       HDR-white emissive — overlay blend would eat pure white on
       this red. */
    transform: skewX(-8deg);
    background: transparent;
    border: 0;
    color: var(--White);
    /* Synced with EMPEZAR + menu typography: iA Writer Quattro is
       the system family, Funnel Display is only the fallback.
       Earlier order swap (Funnel first) made the pills read in a
       different font and look "desincronizadas" from the rest. */
    font-family: 'iA Writer Quattro', 'Funnel Display', system-ui, sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1.2px;
    text-decoration: none;
    text-transform: uppercase;
    transition: transform var(--dur-fast) var(--ease-out);
}
.top-pill::after {
    /* Overlay-blend border layer. position:absolute matches the
       parent's slanted rect; border-radius matches the parent so
       the stroke clips cleanly at the corners. */
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow:
        inset 0 0 0 1px rgba(255, 255, 255, 0.72),
        inset 0 0 0 1.6px rgba(255, 255, 255, 0.14);
    mix-blend-mode: overlay;
    pointer-events: none;
    transition: box-shadow var(--dur-fast) var(--ease-out);
}
.top-pill > * {
    /* Counter-skew the label so letters stand upright. HDR-white
       glow language matches the timer LCD + menu actives. */
    position: relative;
    z-index: 1;
    transform: skewX(8deg);
    text-shadow: var(--glow-hdr-soft);
}
.top-pill:hover::after {
    box-shadow:
        inset 0 0 0 1px rgba(255, 255, 255, 0.95),
        inset 0 0 0 1.6px rgba(255, 255, 255, 0.28),
        inset 0 0 12px 0 rgba(255, 255, 255, 0.18);
}
.top-pill:active { transform: skewX(-8deg) scale(0.97); }

.top-icon {
    appearance: none;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 0;
    background: transparent;
    color: var(--White);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
    transition: background-color var(--dur-fast) var(--ease-out);
}
/* Overlay-blend border on the ··· prefs icon — same chrome
   language as the .top-pill above so the icon reads as a real
   button on the red strip, not a stranded glyph. */
.top-icon::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    box-shadow:
        inset 0 0 0 1px rgba(255, 255, 255, 0.72),
        inset 0 0 0 1.6px rgba(255, 255, 255, 0.14);
    mix-blend-mode: overlay;
    transition: box-shadow var(--dur-fast) var(--ease-out);
}
.top-icon:hover { background-color: rgba(255, 255, 255, 0.12); }
.top-icon:hover::after {
    box-shadow:
        inset 0 0 0 1px rgba(255, 255, 255, 0.95),
        inset 0 0 0 1.6px rgba(255, 255, 255, 0.28),
        inset 0 0 12px 0 rgba(255, 255, 255, 0.18);
}
.top-icon:focus-visible { outline: none; box-shadow: var(--ring-focus); }

/* Bluetooth "connected" indicator — small white-bordered green disc
   with a check tick centred inside, sitting on the top-right corner
   of the BT icon. Matches the screenshot's "connected" cue. */
.top-bt-dot {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #1fbf4d;
    border: 1.5px solid #E30512;
    box-shadow: 0 0 0 0.5px rgba(255,255,255,0.6);
}
.top-bt-dot::after {
    content: '';
    position: absolute;
    inset: 0;
    /* white check mark — two-segment polyline drawn via background */
    background:
        linear-gradient(45deg, transparent 0 47%, #fff 47% 53%, transparent 53% 100%) no-repeat 35% 65% / 5px 2px,
        linear-gradient(-45deg, transparent 0 47%, #fff 47% 53%, transparent 53% 100%) no-repeat 60% 50% / 7px 2px;
}

/* Push everything that used to live at top:0 down by the new bar
   height so the marker + menu don't collide with the brand bar.
   These reset the earlier 12px / 12px / 122px values with the
   updated offsets. !important here only because the earlier
   declarations share the same specificity. */
/* Top-bar 65px tall, timer top 47 → ~18px of overlap with the
   red strip (y=47..65). Just the very top edge of the chrome
   pokes up into the brand bar, not the entire label row.
   User: "no solapes tanto hasta la barra roja solo unos 16-20px". */
.menu              { margin-top: 65px !important; }
.timer-section     { top: 47px !important; }
.submenu           { top: 157px !important; }

/* Narrow viewports: collapse the right-side actions / smaller logo */
@media (max-width: 1023px) {
    .top-logo-mark { font-size: 18px; }
    .top-pill { display: none; }
    .top-icon { width: 30px; height: 30px; }
}

/* Navigation Menu — pushed down 12px to clear the (now fixed) top bar.
   Reverted to the original "clean" look: icon + label per item, slim
   1px vertical .divider strokes between items, single hairline at the
   menu's bottom edge that rhymes with the top-bar border without
   wrapping any item in a box. Earlier attempts to wrap each item or
   each cluster (.menu-left / .menu-right) in an overlay-blend rect
   looked cluttered and unbalanced — the user explicitly wanted
   "separadores, no cajas". */
.menu {
    position: relative;
    display: flex;
    justify-content: space-between;
    width: 100%;
    max-width: 1194px;
    padding: 24px 16px;
    margin-top: 12px;
    /* No explicit column-gap — let space-between push the clusters
       to the container edges (where the SCALEXTRIC logo and the
       PADDOCK/CLUB pills above land). With the top-bar-inner now
       sharing this max-width, every column lines up vertically:
         logo                |  …  | pills
         JUGADORES + GARAJE  |  …  | MONTMELÓ + HISTORIAL
       The floating timer occupies the central gap (positioned
       absolutely, centered at viewport mid). */
}

.menu-left,
.menu-right {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* Tighter cluster: items + divider were spaced 16px which
       left ~32px of air around the hairline divider — user
       feedback: "puedes juntar algo entre las 2 accesos de cada
       lado del menu". 6px hugs the divider so each pair reads
       as one unit. */
    gap: 6px;
    color: var(--White-56, rgba(255, 255, 255, 0.56));
    flex: 0 0 auto;
    min-width: 0;
}

.menu-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    cursor: pointer;
    /* Cell width tightened from clamp(108..148) → clamp(88..120)
       so the label hugs its icon and the cluster gets compact.
       The active item's bolder span still doesn't widen the cell
       because the width is locked. */
    width: clamp(88px, 9vw, 120px);
    min-height: 64px;
    padding: 0;
    position: relative;
    color: var(--White-56);
    /* Subtle residual halo even when inactive — reads as a dim
       backlit indicator rather than flat text. Picks up at hover/
       active via the existing rules below. */
    text-shadow:
        0 0 2px rgba(255, 255, 255, 0.10),
        0 0 8px rgba(255, 255, 255, 0.05);
    transition: color var(--dur-fast) var(--ease-out),
                text-shadow var(--dur-base) var(--ease-out),
                transform var(--dur-fast) var(--ease-out);
}
.menu-item svg {
    flex: 0 0 24px;
    width: 24px;
    height: 24px;
    display: block;
}
.menu-item span {
    line-height: 1;
    height: 1em;
    text-align: center;
    width: 100%;
}

.menu-item svg {
    transition: filter var(--dur-base) var(--ease-out);
}
.menu-item svg path {
    transition: fill-opacity var(--dur-fast) var(--ease-out);
}

/* Hover: a medio camino — texto más blanco y un brillo sutil */
.menu-item:hover {
    color: var(--White);
    transform: translateY(-1px);
    text-shadow: 0 0 6px rgba(255, 255, 255, 0.35);
}
.menu-item:hover svg path { fill-opacity: 1; }
.menu-item:hover svg {
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.5));
}

/* Activo: encendido pleno con HDR luminance (same family as the
   timer LCD). Active menu items also get a slightly heavier
   weight to read as "this section is selected" without yelling. */
.menu-item.is-active {
    color: var(--White, #FFF);
    text-shadow: var(--glow-hdr-strong);
}
.menu-item.is-active span {
    font-weight: 700;
    letter-spacing: 0.32px;
}
.menu-item.is-active svg path { fill-opacity: 1; }
.menu-item.is-active svg {
    filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.75))
            drop-shadow(0 0 16px rgba(255, 255, 255, 0.25));
}

/* Half: estado intermedio (sidebar mode) — luz a medio gas */
.menu-item.is-half {
    color: var(--White, #FFF);
    text-shadow: 0 0 5px rgba(255, 255, 255, 0.45),
                 0 0 14px rgba(255, 255, 255, 0.18);
}
.menu-item.is-half svg path { fill-opacity: 0.88; }
.menu-item.is-half svg {
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.5));
}
/* The legacy ::after no-op (used to host a "red underline" indicator,
   now replaced by the overlay-blend gradient stroke defined above)
   is removed — the new ::after IS the indicator. */

.menu-item .icon {
    width: 24px;
    height: 24px;
    color: #ffffff;
}

.menu-item span {
    /* Text-button typography — same family/case/weight language as
       EMPEZAR's .btn-label so the menu reads as a row of inline text
       buttons rather than a "labels under icons" navigation. The
       letter-spacing matches EMPEZAR's hover state (0.6px) so the
       row has the same emissive cadence as the CTA. */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-style: normal;
    font-weight: 600;
    line-height: 140%;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}

.divider {
    width: 1px;
    height: 45px;
    background: var(--White-8, rgba(255, 255, 255, 0.08));
}

/* Single bottom hairline under the menu — picks up the same overlay
   gradient language as the top bar's bottom border so they read as
   layered chrome lines rather than disconnected elements. NO full
   box around the menu (user found that cluttered), just a thin line
   spanning the full width with a left→centre→right opacity fade so
   it doesn't look harsh at the edges. */
.menu::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    pointer-events: none;
    /* Background and mask BOTH use a left→right gradient that
       fades to zero in the centre — this MASKS OUT the section
       of the hairline that sits behind the timer chrome, so even
       though the line spans the full menu, it visually disappears
       under the floating timer (which is otherwise too translucent
       to fully hide it). The mask centre stays clear for ~520px
       (max timer width 760 → ~70% of width). */
    /* Two soft arcs (0 → peak → 0) of light on each side of the
       timer, fading to nothing at the screen edges AND at the
       timer's footprint in the middle. Mask is no longer needed —
       the gradient itself shapes the visible line.
       User: "el gradient está mal debe ir de 0 a 100 a 0" +
       "brilla mucho" → peak alpha dropped 0.55 → 0.22. */
    background: linear-gradient(90deg,
        rgba(255, 255, 255, 0.00)  0%,
        rgba(255, 255, 255, 0.22) 15%,
        rgba(255, 255, 255, 0.00) 28%,
        rgba(255, 255, 255, 0.00) 72%,
        rgba(255, 255, 255, 0.22) 85%,
        rgba(255, 255, 255, 0.00) 100%);
    mix-blend-mode: overlay;
    opacity: 0.90;
    z-index: 0;
}

/* Timer Section — the most elevated glass surface in the whole UI.
   Shares the liquid-glass language of the pilot rows (translucent
   gradient + backdrop-filter blur + overlay rim) so they read as
   the same physical material, just at different elevations. What
   sets the marker apart:
     - brighter top inset highlight (0.22 vs the rows' 0.12) so it
       reads as raised
     - heavier drop shadow with a longer falloff, so it casts onto
       the canvas below
     - tighter backdrop saturation lift (1.55) so the LCD numerals
       feel more "lit from inside"
   Width clamped so it can never push past the column-gap budget. */
.timer-section {
    display: flex;
    width: fit-content;
    max-width: min(calc(100vw - 32px), 760px);
    /* More breathing room around the LCD + labels.
       (was 20px all sides, 20px gap) */
    padding: 22px 32px 24px;
    justify-content: center;
    gap: 28px;
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    border-radius: var(--r-xl);
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(20px) saturate(1.55);
    -webkit-backdrop-filter: blur(20px) saturate(1.55);
    box-shadow:
        0 2px 0 0 rgba(255, 255, 255, 0.22) inset,
        0 -1px 0 0 rgba(0, 0, 0, 0.55) inset,
        0 6px 12px -4px rgba(0, 0, 0, 0.42),
        0 18px 38px -14px rgba(0, 0, 0, 0.50);
}

.timer-block {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    /* justify-content: space-between → label sticks to top, value
       sticks to bottom. Combined with timer-section's parent
       align-items: stretch (default), all three blocks become the
       same height and their LCD values bottom-align at the same y.
       User reported "el contador está desajustado en altura" —
       cronómetro's label-row (with 1×/2×/3× pills inline) is
       ~6px taller than the bare VUELTAS label, which used to push
       its value down relative to VUELTAS. */
    justify-content: space-between;
    gap: 8px;
}

.timer-block.weather {
    align-items: center;
    /* Icon block has no LCD — keep it center-stacked. */
    justify-content: center;
    gap: 10px;
}

/* Speed switch — 3 círculos outlined (1×/2×/3×) inline junto al label de
   cronómetro. Inactivos: borde gris sutil. Activo: borde blanco + halo
   interno como una luz del dashboard. */
.timer-label-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
}
.speed-switch {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.speed-pill {
    appearance: none;
    /* Inactive pills are now GREY-FILLED discs (matches the .light off
       state language). User: "los 1x 2x 3x inactivos no deben ser
       outline sino gris filled al estilo del 40 etc". */
    background: rgba(255, 255, 255, 0.14);
    padding: 0;
    cursor: pointer;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;

    /* Tipografía pequeña y consistente con el resto del HUD */
    color: var(--White-56, rgba(255, 255, 255, 0.56));
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 10px;
    font-style: normal;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.2px;
    font-feature-settings: 'liga' off, 'clig' off, 'tnum' on;

    transition: color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
}
.speed-pill:hover {
    background: rgba(255, 255, 255, 0.22);
    color: var(--White, rgba(255, 255, 255, 0.92));
}
.speed-pill.is-active {
    /* Encendido: filled white. !important defends against an
       earlier `background` shorthand on .speed-pill that was
       winning the cascade even though the .is-active selector
       has higher specificity (Chrome quirk reproducible). */
    background-color: #ffffff !important;
    color: rgba(0, 0, 0, 0.85);
    box-shadow: var(--glow-active),
                0 0 0 1px rgba(255, 255, 255, 0.6);
    animation: pillClick 320ms var(--ease-spring) 1;
}
@keyframes pillClick {
    0%   { transform: scale(1); }
    55%  { transform: scale(1.12); }
    100% { transform: scale(1); }
}
.speed-pill:focus-visible {
    outline: none;
    box-shadow: var(--ring-focus);
}

.timer-label {
    color: var(--White-56, rgba(255, 255, 255, 0.56));
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;

    /* 14 l UC */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-style: normal;
    font-weight: 450;
    line-height: 140%; /* 19.6px */
    letter-spacing: 0.28px;
    text-transform: uppercase;
}

.timer-value {
    display: flex;
    align-items: baseline;
    gap: 4px;
}

.timer-number {
    color: var(--White, #FFF);
    font-feature-settings: 'liga' off, 'clig' off;

    /* Number Light — HDR luminance + drop shadow. Layered glows
       simulate a backlit LCD blooming under camera exposure. */
    text-shadow: 0 4px 4px rgba(0, 0, 0, 0.25),
                 var(--glow-hdr-strong),
                 0 0 100px rgba(255, 255, 255, 0.32);

    /* 64 */
    font-family: "7-Segment", monospace;
    font-size: 64px;
    font-style: normal;
    font-weight: 400;
    line-height: 100%; /* 64px */
    letter-spacing: 1.28px;
    white-space: nowrap;
}

.timer-suffix {
    color: var(--White-20, rgba(255, 255, 255, 0.20));
    font-feature-settings: 'liga' off, 'clig' off;

    /* 64 */
    -webkit-text-stroke-width: 1px;
    -webkit-text-stroke-color: rgba(0, 0, 0, 0.50);
    font-family: "7-Segment", monospace;
    font-size: 64px;
    font-style: normal;
    font-weight: 400;
    line-height: 100%; /* 64px */
    letter-spacing: 1.28px;
    white-space: nowrap;
}

.timer-ms {
    color: var(--White-20, rgba(255, 255, 255, 0.20));
    font-feature-settings: 'liga' off, 'clig' off;
    -webkit-text-stroke-width: 1px;
    -webkit-text-stroke-color: rgba(0, 0, 0, 0.50);
    font-family: "7-Segment", monospace;
    font-size: 64px;
    font-style: normal;
    font-weight: 400;
    line-height: 100%;
    letter-spacing: 1.28px;
    white-space: nowrap;
}

.timer-divider {
    width: 1px;
    flex-shrink: 0;
    align-self: stretch;
    background: var(--White-8, rgba(255, 255, 255, 0.08));
}

/* 7-segment ghost — "8" detrás de cada dígito activo, como un LCD real */
.timer-number .seg,
.timer-number .colon,
.timer-number .punc,
.timer-suffix .seg,
.timer-suffix .punc,
.timer-ms .seg {
    position: relative;
    display: inline-block;
    font-variant-numeric: tabular-nums;
    isolation: isolate; /* nuevo stacking-context para que el ::before(z-index:-1) quede detrás del texto sin escapar a la barra */
}
.timer-number .seg::before {
    content: "8";
    position: absolute;
    inset: 0;
    z-index: -1; /* detrás del dígito visible */
    /* Stronger ghost so the "off" segments read as a real backlit
       LCD rather than a flat 10% wash. Bumped to 18% + a soft
       blur halo at the same colour so the inactive segments have
       residual luminescence — feels like a real instrument
       cluster's off pixels still glow faintly. */
    color: rgba(255, 255, 255, 0.18);
    text-shadow:
        0 0 4px rgba(255, 255, 255, 0.10),
        0 0 10px rgba(255, 255, 255, 0.06);
    -webkit-text-stroke-width: 0;
    pointer-events: none;
    letter-spacing: inherit;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
}
/* En suffix y ms los dígitos ya son tenues — fantasma más suave aún */
.timer-suffix .seg::before,
.timer-ms .seg::before {
    content: "8";
    position: absolute;
    inset: 0;
    z-index: -1;
    color: rgba(255, 255, 255, 0.10);
    text-shadow:
        0 0 3px rgba(255, 255, 255, 0.06),
        0 0 8px rgba(255, 255, 255, 0.04);
    -webkit-text-stroke-width: 0;
    pointer-events: none;
    letter-spacing: inherit;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
}

.weather-icon {
    width: 40px;
    height: 40px;
    color: #ffffff;
    margin-top: 8px;
}

/* Submenu */
.submenu {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin-top: 16px;
}

.submenu-tab {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 16px 24px;
    background-color: #1a1a1a;
    border-radius: 8px;
    cursor: pointer;
    transform: skewX(-10deg);
    transition: background-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
}

.submenu-tab:hover {
    background-color: rgba(255,255,255,0.05);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.15) inset,
                0 0 24px -8px rgba(255,255,255,0.35);
}

.submenu-tab svg {
    transition: transform var(--dur-base) var(--ease-out),
                filter var(--dur-base) var(--ease-out);
}
.submenu-tab:hover svg {
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.5));
}

.submenu-tab.is-open {
    box-shadow: 0 0 0 1px rgba(255,255,255,0.22) inset,
                0 0 28px -6px rgba(255,255,255,0.45);
}
.submenu-tab.is-open svg {
    transform: rotate(180deg);
    filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.7));
}

.submenu-tab::after {
    content: '';
    position: absolute;
    left: 24px;
    right: 24px;
    bottom: 10px;
    height: 1px;
    background: var(--White);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--dur-base) var(--ease-out);
    opacity: 0;
}

.submenu-tab.active::after { transform: scaleX(1); opacity: 0.4; }

.submenu-tab span {
    color: var(--White, #FFF);
    text-align: center;
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;

    /* 16 sb UC */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 16px;
    font-style: normal;
    font-weight: 600;
    line-height: 140%; /* 22.4px */
    text-transform: uppercase;
     transform: skewX(10deg);
}

.submenu-icon {
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The submenu wraps the empezar button just below the timer-section,
   overlapping the timer's bottom edge by ~10px so the button "sits
   on" the marcador with a confident bite (was 4px, user wanted
   more). z-index 11 keeps it above the timer (z:10). */
.submenu {
    position: absolute;
    top: 122px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 11;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: opacity var(--dur-base) var(--ease-out),
                transform var(--dur-base) var(--ease-out);
}
body.race-running .submenu {
    opacity: 0;
    pointer-events: none;
    transform: translateX(-50%) translateY(8px);
}

/* F1 start light tree — 5 dots inside the button.
   Hidden by default; visible when .btn-start.is-counting is set. */
.f1-lights {
    display: none;
    gap: 8px;
    align-items: center;
    justify-content: center;
    height: 22px;
}
.f1-light {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.42);
    border: 1px solid rgba(0, 0, 0, 0.55);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4),
                inset 0 -1px 1px rgba(255, 255, 255, 0.05);
    transition: background-color 80ms var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
}
.btn-start.is-counting .f1-lights {
    display: inline-flex;
    /* Counter-skew lights so the dots row stays upright on the
       tilted parallelogram. */
    transform: skewX(8deg);
}
.btn-start.is-counting .btn-label { display: none; }
/* During counting, suppress the hover sheen — wrong vibe.
   Preserve the base skew so the button doesn't snap upright. */
.btn-start.is-counting::after { display: none; }
.btn-start.is-counting:hover { transform: skewX(-8deg); }

/* Countdown mode — the button flips from "painted metal red" to the
   same liquid-glass language as the pilot rows. The f1-lights inside
   stay in their colours (red while counting, green on GO) so they
   read as actual signal lamps mounted on a transparent housing.
   Transition timed to match the first light coming on. */
.btn-start.is-counting {
    background-color: transparent;
    background-image: none;
    border: var(--glass-border);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    transition:
        background-color 200ms var(--ease-out),
        background-image 0ms 0ms,
        border-color 200ms var(--ease-out),
        box-shadow 200ms var(--ease-out),
        backdrop-filter 200ms var(--ease-out);
}

/* Active reds — one per stage of the sequence */
.btn-start.is-counting.lights-1 .f1-light:nth-child(-n + 1),
.btn-start.is-counting.lights-2 .f1-light:nth-child(-n + 2),
.btn-start.is-counting.lights-3 .f1-light:nth-child(-n + 3),
.btn-start.is-counting.lights-4 .f1-light:nth-child(-n + 4),
.btn-start.is-counting.lights-5 .f1-light:nth-child(-n + 5) {
    background: #ff1726;
    border-color: #ff1726;
    box-shadow: 0 0 8px 1px rgba(255, 23, 38, 0.85),
                inset 0 1px 1px rgba(255, 255, 255, 0.25);
}

/* GO state: button stays GLASS (no metallic flash back to red), but
   all 5 lights snap GREEN simultaneously and pulse — the way real
   F1 lights communicate the start. The btnGoFlash keyframe is kept
   for the lift / glow timing. */
.btn-start.is-counting.lights-go {
    background-color: transparent;
    background-image: none;
    box-shadow:
        var(--glass-overlay),
        var(--glass-shadow),
        0 0 24px -4px rgba(0, 255, 122, 0.55);
    animation: btnGoFlash 320ms var(--ease-out) 1;
}
.btn-start.is-counting.lights-go .f1-light,
.btn-start.is-counting.lights-go .f1-light:nth-child(-n + 5) {
    background: #00ff7a;
    border-color: #00ff7a;
    box-shadow:
        0 0 10px 2px rgba(0, 255, 122, 0.85),
        0 0 22px 4px rgba(0, 255, 122, 0.45);
}
@keyframes btnGoFlash {
    0%   { filter: brightness(2.2) saturate(1.6); transform: scale(1.08); }
    100% { filter: brightness(1) saturate(1);     transform: scale(1); }
}

.btn-start {
    position: relative;
    overflow: hidden;
    /* Pintura roja con sutil degradado vertical para look "metálico esmaltado" */
    background-color: var(--Red);
    background-image: linear-gradient(180deg, #ec1c2a 0%, var(--Red) 48%, #b8050f 100%);
    color: #ffffff;
    border: none;
    padding: 16px 32px;
    color: var(--White, #FFF);
    text-align: center;
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;

    /* 16 sb UC */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 16px;
    font-style: normal;
    font-weight: 600;
    line-height: 140%; /* 22.4px */
    text-transform: uppercase;
    border-radius: 8px;
    cursor: pointer;
    /* Tilted parallelogram — only the SHAPE is skewed, mirroring the
       SCALEXTRIC brand-strip pills above. The red paint, sheen and
       HDR label all stay; the inner label gets a counter-skew so
       letters stand upright. The hover/active transforms below
       compose on top of this base skew. */
    transform: skewX(-8deg);
    box-shadow: 0 2px 0 0 rgba(0,0,0,0.25),
                0 1px 0 0 rgba(255,255,255,0.18) inset,
                0 -1px 0 0 rgba(0,0,0,0.25) inset;
    transition: background-color var(--dur-fast) var(--ease-out),
                background-position var(--dur-slow) var(--ease-out),
                transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                opacity var(--dur-base) var(--ease-out),
                filter var(--dur-base) var(--ease-out);
    min-width: 130px;
}

/* Capa de "press flash" (manchazo blanco al click) */
.btn-start::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(255,255,255,0.25);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-out);
    z-index: 1;
}

/* Sheen diagonal — brillo de metal pulido que cruza de izquierda a derecha en hover */
.btn-start::after {
    content: '';
    position: absolute;
    top: 0;
    left: -120%;
    width: 80%;
    height: 100%;
    background: linear-gradient(
        100deg,
        transparent 20%,
        rgba(255, 255, 255, 0.22) 48%,
        rgba(255, 255, 255, 0.42) 50%,
        rgba(255, 255, 255, 0.22) 52%,
        transparent 80%
    );
    transform: skewX(-18deg);
    pointer-events: none;
    transition: none; /* al salir del hover, vuelve sin barrido inverso */
    z-index: 2;
}
.btn-start:hover::after {
    left: 130%;
    transition: left 760ms var(--ease-out);
}

.btn-start:hover {
    /* Preserve the -8° base skew while lifting on hover */
    transform: skewX(-8deg) translateY(-1px);
    filter: brightness(1.06) saturate(1.05);
    box-shadow: 0 10px 28px -8px var(--Red-Glow),
                0 0 22px -4px rgba(227, 6, 19, 0.55),
                0 2px 0 0 rgba(0,0,0,0.25),
                0 1px 0 0 rgba(255,255,255,0.32) inset,
                0 -1px 0 0 rgba(0,0,0,0.25) inset;
}
.btn-start:active {
    transform: skewX(-8deg) translateY(0) scale(0.98);
}

/* Label del botón siempre por encima del sheen — counter-skew so
   the letters stand upright on the tilted parallelogram. */
.btn-start .btn-label {
    position: relative;
    z-index: 3;
    display: inline-block;
    transform: skewX(8deg);
    transition: letter-spacing var(--dur-base) var(--ease-out);
}
.btn-start:hover .btn-label { letter-spacing: 0.6px; }
.btn-start.is-counting .btn-label,
.btn-start.is-go .btn-label {
    font-family: "7-Segment", monospace;
    font-size: 22px;
    letter-spacing: 2px;
    text-shadow: 0 0 6px rgba(255,255,255,0.6);
}
.btn-start.is-go .btn-label {
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 16px;
    letter-spacing: 4px;
    text-shadow: 0 0 8px rgba(255,255,255,0.8);
}
/* Pulso del botón con cada tick del countdown */
@keyframes btnCountTick {
    0%   { box-shadow: 0 2px 0 0 rgba(0,0,0,0.25),
                       0 1px 0 0 rgba(255,255,255,0.18) inset,
                       0 -1px 0 0 rgba(0,0,0,0.25) inset; }
    20%  { box-shadow: 0 0 36px 4px var(--Red-Glow),
                       0 0 64px 8px rgba(227,6,19,0.45),
                       0 2px 0 0 rgba(0,0,0,0.25),
                       0 1px 0 0 rgba(255,255,255,0.32) inset,
                       0 -1px 0 0 rgba(0,0,0,0.25) inset; }
    100% { box-shadow: 0 2px 0 0 rgba(0,0,0,0.25),
                       0 1px 0 0 rgba(255,255,255,0.18) inset,
                       0 -1px 0 0 rgba(0,0,0,0.25) inset; }
}
.btn-start.is-counting { animation: btnCountTick 720ms var(--ease-out); }
.btn-start.is-go {
    animation: btnGoFlash 480ms var(--ease-out);
    background-image: linear-gradient(180deg, #ff3742 0%, #ff1726 48%, #d80a18 100%);
}
@keyframes btnGoFlash {
    0%   { filter: brightness(1.7) saturate(1.4); transform: scale(1.06); }
    100% { filter: brightness(1) saturate(1); transform: scale(1); }
}

/* Podio integrado en la fila del piloto — medallas + glow sutil */
.pilot-row.is-finalist { transition: background-color var(--dur-slow) var(--ease-out), box-shadow var(--dur-slow) var(--ease-out); }
.pilot-row.is-p1 .pilot-number,
.pilot-row.is-p2 .pilot-number,
.pilot-row.is-p3 .pilot-number {
    position: relative;
}
.pilot-row.is-p1 .pilot-number::after,
.pilot-row.is-p2 .pilot-number::after,
.pilot-row.is-p3 .pilot-number::after {
    content: '';
    position: absolute;
    top: -4px; right: -4px;
    width: 14px; height: 14px;
    border-radius: 999px;
    box-shadow: 0 0 8px 1px currentColor;
}
.pilot-row.is-p1 .pilot-number::after { background: #FFD040; color: rgba(255,208,64,0.7); }
.pilot-row.is-p2 .pilot-number::after { background: #C8C8D0; color: rgba(200,200,208,0.6); }
.pilot-row.is-p3 .pilot-number::after { background: #CD7F32; color: rgba(205,127,50,0.6); }

/* Podium colours (gold/silver/bronze) only after the race FINISHES.
   Gating to body.race-running.is-finished prevents the colours from
   bleeding into the pre-race lobby (where the rows should read as
   neutral). The is-finalist state is applied by hud-bridge once a
   pilot crosses the line, paired with body.race-finished by main. */
body.race-finished .pilot-row.is-p1 {
    background: linear-gradient(90deg, rgba(255,208,64,0.10) 0%, rgba(0,0,0,0) 60%);
    box-shadow:
        var(--glass-overlay),
        0 0 0 1px rgba(255,208,64,0.32) inset,
        0 0 24px -6px rgba(255,208,64,0.4);
}
body.race-finished .pilot-row.is-p2 {
    background: linear-gradient(90deg, rgba(200,200,208,0.08) 0%, rgba(0,0,0,0) 60%);
    box-shadow:
        var(--glass-overlay),
        0 0 0 1px rgba(200,200,208,0.22) inset,
        0 0 18px -8px rgba(200,200,208,0.3);
}
body.race-finished .pilot-row.is-p3 {
    background: linear-gradient(90deg, rgba(205,127,50,0.08) 0%, rgba(0,0,0,0) 60%);
    box-shadow:
        var(--glass-overlay),
        0 0 0 1px rgba(205,127,50,0.22) inset,
        0 0 18px -8px rgba(205,127,50,0.3);
}

.btn-start:active {
    transform: translateY(1px) scale(0.98);
    transition-duration: 60ms;
}

.btn-start:active::before { opacity: 1; transition-duration: 0ms; }

.btn-start:disabled,
.btn-start[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
    transform: none;
    box-shadow: 0 2px 0 0 rgba(0,0,0,0.25) inset;
}

.btn-start.is-loading {
    pointer-events: none;
    color: transparent;
}

.btn-start.is-loading::after {
    content: '';
    position: absolute;
    inset: 0;
    top: 0;
    left: 0;
    margin: auto;
    width: 36px;
    height: 6px;
    transform: none; /* anula el skew del sheen */
    transition: none;
    background:
        radial-gradient(circle 3px at 6px 50%, #fff 100%, transparent 0) 0 0/14px 100% no-repeat,
        radial-gradient(circle 3px at 6px 50%, #fff 100%, transparent 0) 14px 0/14px 100% no-repeat,
        radial-gradient(circle 3px at 6px 50%, #fff 100%, transparent 0) 28px 0/14px 100% no-repeat;
    animation: btnDots 1.2s var(--ease-in-out) infinite;
}

/* Pilot List */
.pilot-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    /* Container query target — each pilot-row queries the LIST's own
       inline-size to decide what to hide. This replaces the old
       discrete `body.lobby-sidebar` mode: now the same row layout
       reads "we're narrow" the moment the panel shrinks and folds
       indicators / time progressively. Same elements in the DOM,
       just CSS hides what doesn't fit. */
    container-type: inline-size;
    container-name: pilots;
    /* top padding leaves room for the absolutely-positioned submenu
       + EMPEZAR button (which sits at top:128 of .app, ~44px tall =
       bottom edge ~172). We want ≥ 32px breathing room below the
       button before the first pilot row, so 172 - flow_position + 32
       ≈ 130px of padding-top. */
    padding: 130px 48px 24px;
    /* Seamless mode switch — the SAME element resizes between full
       and sidebar layouts. Animating padding/border-radius/background
       /max-width keeps it visually one component morphing in place,
       not two cards crossfading. Position (absolute → fixed) still
       snaps because CSS can't transition that, but the surrounding
       animation hides the jump. */
    transition:
        transform 420ms var(--ease-out),
        opacity 260ms var(--ease-out),
        padding 420ms var(--ease-out),
        max-width 420ms var(--ease-out),
        width 420ms var(--ease-out),
        max-height 420ms var(--ease-out),
        border-radius 420ms var(--ease-out),
        background 380ms var(--ease-out),
        box-shadow 380ms var(--ease-out),
        backdrop-filter 380ms var(--ease-out),
        -webkit-backdrop-filter 380ms var(--ease-out);
    transform-origin: bottom center;
}

/* ---- Container queries: progressive slip compaction ----
   The pilot row carries the same DOM regardless of the lobby panel
   width. Each tier below hides one more peripheral cluster as the
   container shrinks, so a 280px sidebar shows number+name+laps and
   nothing else, while a full-width lobby keeps the gas/tyre/badge.
   The thresholds are tuned against the slip's content width, not
   the viewport — that's the point of container queries here. */
@container pilots (max-width: 640px) {
    .pilot-row .tire-indicator { display: none; }
}
@container pilots (max-width: 480px) {
    .pilot-row .indicator-group { display: none; }
    .pilot-row .pilot-col-right { display: none; }
    /* Slip can also breathe shorter once we've dropped both clusters */
    .pilot-row { min-height: 48px; }
}
@container pilots (max-width: 360px) {
    .pilot-row .pilot-time { display: none; }
}
@container pilots (max-width: 280px) {
    .pilot-row .pilot-laps { display: none; }
    .pilot-row .pilot-name-row .pilot-id,
    .pilot-row .pilot-name-row .pilot-dot { display: none; }
}

/* Sidebar / lobby — el botón "jugadores" cicla 3 estados:
   1) full  (default): vista completa con todos los indicadores
   2) sidebar: comprimido lateral derecho, pista y jugadores visibles a la vez
   3) hidden: oculto, canvas limpio
*/

/* HIDDEN */
body.lobby-hidden .pilot-list,
body.lobby-hidden .submenu {
    transform: translateY(24px);
    opacity: 0;
    pointer-events: none;
}
body.lobby-hidden .submenu {
    transform: translateY(-12px);
}

/* SIDEBAR — pilot-list a la IZQUIERDA. Cada fila es una sola línea
   horizontal: avatar pequeño · nombre · #id · vueltas · tiempo. Mismo
   lenguaje visual que la timer-section, sólo plegado. Estados de
   acelerando/frenando se reflejan en el borde lateral del color del
   piloto y el tiempo flash rojo en frenada. */
body.lobby-sidebar .pilot-list {
    position: fixed;
    top: 200px;
    left: 16px;
    width: min(280px, calc(100vw - 32px));
    max-height: calc(100vh - 220px);
    overflow-y: auto;
    padding: var(--s-2);
    /* No "panel box" — user feedback was that the sidebar still felt
       like a separate component (border + background + box-shadow
       wrapped the whole list as a card). Now the only chrome lives
       on the individual rows; the list itself is transparent so it
       reads as the same lobby slips just shifted to the side and
       compacted, not as a new container. */
    border: 0;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    z-index: 9;
    transform: none;
    scrollbar-width: thin;
    scrollbar-color: var(--White-24) transparent;
}

/* Fila de UNA SOLA LÍNEA — todo inline */
body.lobby-sidebar .pilot-row {
    height: 36px;
    min-height: 36px;
    max-width: none;
    padding: 0 var(--s-2) 0 0;
    gap: var(--s-2);
    border-radius: var(--r-sm);
    overflow: hidden;
}
/* Rows transition height/padding/gap as well so the full→sidebar
   collapse feels like one element folding, not a snap-replace.
   `opacity` deliberately NOT in the list — the FLIP reorder during
   the race tweaks transform per frame and nothing should ever fade
   the row in/out. Earlier the cascade picked up an unintended
   opacity transition on body class flips (race-running, lobby-
   sidebar) and made it look like the row was blinking through
   each overtake. */
.pilot-row {
    transition:
        transform var(--dur-base) var(--ease-out),
        box-shadow var(--dur-base) var(--ease-out),
        filter var(--dur-base) var(--ease-out),
        background 280ms var(--ease-out),
        height 380ms var(--ease-out),
        padding 380ms var(--ease-out),
        gap 380ms var(--ease-out),
        border-radius 380ms var(--ease-out);
}
body.lobby-sidebar .pilot-row + .pilot-row { margin-top: 2px; }
body.lobby-sidebar .pilot-row:hover {
    transform: translateY(-1px);
    box-shadow:
        0 1px 1px 1px rgba(255, 255, 255, 0.40) inset,
        0 -1px 1px 0 rgba(255, 255, 255, 0.12),
        0 6px 12px 0 rgba(0, 0, 0, 0.32);
}

/* Avatar 36px cuadrado, conserva identidad */
body.lobby-sidebar .pilot-avatar {
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
    border-radius: var(--r-sm) 0 0 var(--r-sm);
}
body.lobby-sidebar .pilot-number {
    /* Sidebar slot is 36×36 — number scales DOWN but stays italic.
       Letter-spacing is loosened slightly for 2-digit numbers like
       44 / 33 / 12 so they don't crowd. */
    font-size: 14px;
    letter-spacing: -0.5px;
    transform: translate(calc(-50% - 3px), -50%);
}
body.lobby-sidebar .pilot-line {
    width: 4px;
    height: 36px;
    transform: rotate(10deg);
}
body.lobby-sidebar .pilot-shape svg {
    width: 36px;
    height: 34px;
}
body.lobby-sidebar .pilot-row:hover .pilot-shape svg { transform: translateX(1px); }
body.lobby-sidebar .pilot-row:hover .pilot-avatar { transform: none; }
body.lobby-sidebar .pilot-row:hover .pilot-info   { transform: none; }
body.lobby-sidebar .pilot-row.is-human .pilot-number::before {
    bottom: -4px; width: 3px; height: 3px;
}

/* Info: todo en una sola fila — nombre + id flexibles, laps/time fijos */
body.lobby-sidebar .pilot-info {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--s-2);
    flex: 1;
    min-width: 0;
}
/* Las "columnas" del modo full pasan a ser inline en sidebar */
body.lobby-sidebar .pilot-col-left {
    display: contents;
}
body.lobby-sidebar .pilot-col-right {
    display: contents;
}
body.lobby-sidebar .pilot-name-row {
    display: flex;
    align-items: baseline;
    gap: 4px;
    min-width: 0;
    flex: 1;
    overflow: hidden;
    margin: 0;
    padding: 0;
}
body.lobby-sidebar .pilot-name {
    /* F1-style 3-letter driver code (SEN, SCH, HAM…). The full name
       is kept in the DOM (so click-to-edit still works in full mode);
       in sidebar we just CSS-clip the visible width to roughly three
       characters and disable contenteditable so it doesn't widen
       on focus. JS in lobby.js applies title-attr with the full name
       for accessibility / hover tooltip. */
    font-size: 14px;
    font-style: italic;
    font-weight: 700;
    letter-spacing: 0.4px;
    overflow: hidden;
    text-overflow: clip;
    white-space: nowrap;
    color: var(--White);
    max-width: 3.6ch;
}
body.lobby-sidebar .pilot-dot { font-size: 10px; opacity: 0.55; }
body.lobby-sidebar .pilot-id {
    font-size: 10px;
    /* Principal element — number/id reads at full white, not dimmed */
    opacity: 1;
    color: var(--White);
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
}
body.lobby-sidebar .pilot-laps {
    font-size: 11px;
    font-weight: 500;
    color: var(--White);
    font-variant-numeric: tabular-nums;
    font-family: "7-Segment", monospace;
    flex: 0 0 auto;
    min-width: 22px;
    text-align: right;
}
body.lobby-sidebar .pilot-time {
    font-size: 10px;
    color: var(--White-40);
    font-variant-numeric: tabular-nums;
    font-family: "7-Segment", monospace;
    flex: 0 0 auto;
    min-width: 64px;
    text-align: right;
}

/* Esconder los indicators "ricos" (gas/tyre/tire) — espacio insuficiente */
/* Sidebar transition — fade + collapse the per-row chrome that
   doesn't fit instead of display:none-ing it (which snaps).
   IMPORTANT: NO overflow:hidden on the base — the gas/tyre light
   dots cast colored box-shadow halos that need to render outside
   the group's box. The earlier overflow:hidden was eating those
   halos and making the lights look like masked semicircles
   (user's screenshot of a dim yellow + green dots with a bite
   missing). max-width transition still works without clipping. */
.indicator-group,
.tire-indicator {
    transition:
        opacity 280ms var(--ease-out),
        max-width 380ms var(--ease-out),
        margin 380ms var(--ease-out),
        padding 380ms var(--ease-out);
    max-width: 240px;
}
body.lobby-sidebar .indicator-group,
body.lobby-sidebar .tire-indicator {
    opacity: 0;
    max-width: 0;
    margin: 0;
    padding: 0;
    pointer-events: none;
}

/* Sidebar acceleration glow — soft halo using the pilot colour, no
   extra bar. Identical philosophy to the full-mode treatment. */
body.lobby-sidebar .pilot-row.is-accelerating {
    box-shadow:
        var(--glass-overlay),
        0 4px 14px -4px rgba(0, 0, 0, 0.40),
        0 0 16px -6px var(--pilot-color, rgba(255, 255, 255, 0.35));
}
body.lobby-sidebar .pilot-row.is-braking .pilot-time {
    color: #ff4757;
    text-shadow: 0 0 4px rgba(255, 71, 87, 0.55);
}
body.lobby-sidebar .pilot-row.is-leader::before {
    content: '';
    position: absolute;
    top: 50%; left: -3px;
    width: 3px; height: 16px;
    transform: translateY(-50%);
    background: var(--Red);
    border-radius: 2px;
    box-shadow: 0 0 8px var(--Red);
}

/* Garage panel — sólo visible cuando body.garage-open */
.garage-panel {
    position: fixed;
    top: 96px;
    right: 24px;
    width: 320px;
    max-height: calc(100vh - 130px);
    overflow-y: auto;
    z-index: 12;
    padding: 20px;
    border-radius: 16px;
    border: var(--glass-border);
    background: var(--glass-bg);
    /* Liquid glass — same language as pilot-list sidebar. */
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    transform: translateX(calc(100% + 40px));
    opacity: 0;
    pointer-events: none;
    transition: transform 360ms var(--ease-out),
                opacity 260ms var(--ease-out);
}
body.garage-open .garage-panel {
    transform: translateX(0);
    opacity: 1;
    pointer-events: auto;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

.garage-title {
    color: var(--White-56, rgba(255,255,255,0.56));
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-weight: 450;
    letter-spacing: 0.28px;
    text-transform: uppercase;
    margin-bottom: 12px;
}

/* Quality toggle — same outlined-pill language as the speed switch */
.garage-quality {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
}
.garage-quality-label {
    color: var(--White-56);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 10px;
    font-weight: 450;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    min-width: 60px;
}
.quality-pill {
    appearance: none;
    background: transparent;
    padding: 4px 10px;
    cursor: pointer;
    border: 1px solid var(--White-24);
    border-radius: var(--r-pill);
    color: var(--White-40);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    transition: color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
}
.quality-pill:hover { color: var(--White-56); border-color: var(--White-40); }
.quality-pill.is-active {
    color: var(--White);
    border-color: var(--White);
    box-shadow: var(--glow-active);
}

.garage-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    border-radius: 10px;
    border: 1px solid var(--White-8, rgba(255,255,255,0.08));
    background: rgba(0,0,0,0.32);
}
.garage-card + .garage-card { margin-top: 8px; }

.garage-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
}
.garage-dot {
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--pilot-color, #888);
    box-shadow: 0 0 6px 0 var(--pilot-color, #888);
    flex: 0 0 auto;
}
body.lobby-hidden .garage-dot { /* keep visible */ }
.garage-pilot-name {
    flex: 1;
    color: var(--White, #FFF);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.2px;
    text-transform: uppercase;
}
.garage-pilot-num {
    color: var(--White-56);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.4px;
}
.garage-stat {
    display: grid;
    grid-template-columns: 60px 1fr;
    align-items: center;
    gap: var(--s-3);
}
.garage-stat-label {
    color: var(--White-56);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 10px;
    font-weight: 450;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}
/* Garage lights — variante compacta de .indicator-lights del HUD para
   que el lenguaje sea idéntico al de gas/tyre del dashboard */
.garage-lights {
    display: flex;
    align-items: center;
    gap: 3px;
    justify-content: flex-end;
}
.garage-lights .light {
    width: 9px;
    height: 9px;
}

.pilot-row {
    position: relative;
    width: 100%;
    max-width: 1000px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    overflow: hidden;
    gap: clamp(12px, 1.8vw, 20px);
    padding-right: clamp(12px, 1.8vw, 24px);
    border-radius: var(--r-sm);
    height: 64px;
    border: var(--glass-border);
    /* Row body stays neutral dark glass — the pilot/team colour lives
       ONLY in the angled trapezoid slip inside .pilot-shape (the SVG
       behind the number). No extra vertical bar here. */
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    cursor: pointer;
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                opacity var(--dur-base) var(--ease-out),
                filter var(--dur-base) var(--ease-out),
                background var(--dur-base) var(--ease-out);
}

/* Below 900px hide the second indicator group entirely (tyre).
   The grid auto-tracks adapt naturally without breakpoints needed
   thanks to the `auto` columns. */
@media (max-width: 899px) {
    .pilot-info {
        grid-template-columns:
            minmax(100px, 1fr)
            minmax(24px, max-content)
            minmax(64px, max-content)
            auto
            auto;
        column-gap: 12px;
    }
    .indicator-group:nth-of-type(2) { display: none; }
}

.pilot-row + .pilot-row { margin-top: 8px; }

/* ===========================================================
   9-PLAYER LOBBY — dynamic visibility
   ===========================================================
   The lobby exposes 9 pilot rows in the DOM but only shows N at
   a time. body.has-pilots-N (set by lobby.js, default 6) reveals
   rows 1..N and hides the rest. A separate .pilot-add-slot
   appears after the last visible row, letting the user expand
   the active set up to MAX_PILOTS (9). Hover on the A/M badge
   reveals an X (remove this pilot) — see .tire-indicator below. */

/* By default we show 6 rows (matches DEFAULT_ACTIVE_PILOTS). */
body:not([class*="has-pilots-"]) .pilot-row[data-pilot="7"],
body:not([class*="has-pilots-"]) .pilot-row[data-pilot="8"],
body:not([class*="has-pilots-"]) .pilot-row[data-pilot="9"] {
    display: none;
}
/* For each pilot count N, hide rows numbered (N+1) … 9. We list
   only the cases that DIFFER from default (which is already 6). */
body.has-pilots-1 .pilot-row[data-pilot="2"],
body.has-pilots-1 .pilot-row[data-pilot="3"],
body.has-pilots-1 .pilot-row[data-pilot="4"],
body.has-pilots-1 .pilot-row[data-pilot="5"],
body.has-pilots-1 .pilot-row[data-pilot="6"],
body.has-pilots-1 .pilot-row[data-pilot="7"],
body.has-pilots-1 .pilot-row[data-pilot="8"],
body.has-pilots-1 .pilot-row[data-pilot="9"],
body.has-pilots-2 .pilot-row[data-pilot="3"],
body.has-pilots-2 .pilot-row[data-pilot="4"],
body.has-pilots-2 .pilot-row[data-pilot="5"],
body.has-pilots-2 .pilot-row[data-pilot="6"],
body.has-pilots-2 .pilot-row[data-pilot="7"],
body.has-pilots-2 .pilot-row[data-pilot="8"],
body.has-pilots-2 .pilot-row[data-pilot="9"],
body.has-pilots-3 .pilot-row[data-pilot="4"],
body.has-pilots-3 .pilot-row[data-pilot="5"],
body.has-pilots-3 .pilot-row[data-pilot="6"],
body.has-pilots-3 .pilot-row[data-pilot="7"],
body.has-pilots-3 .pilot-row[data-pilot="8"],
body.has-pilots-3 .pilot-row[data-pilot="9"],
body.has-pilots-4 .pilot-row[data-pilot="5"],
body.has-pilots-4 .pilot-row[data-pilot="6"],
body.has-pilots-4 .pilot-row[data-pilot="7"],
body.has-pilots-4 .pilot-row[data-pilot="8"],
body.has-pilots-4 .pilot-row[data-pilot="9"],
body.has-pilots-5 .pilot-row[data-pilot="6"],
body.has-pilots-5 .pilot-row[data-pilot="7"],
body.has-pilots-5 .pilot-row[data-pilot="8"],
body.has-pilots-5 .pilot-row[data-pilot="9"],
body.has-pilots-6 .pilot-row[data-pilot="7"],
body.has-pilots-6 .pilot-row[data-pilot="8"],
body.has-pilots-6 .pilot-row[data-pilot="9"],
body.has-pilots-7 .pilot-row[data-pilot="8"],
body.has-pilots-7 .pilot-row[data-pilot="9"],
body.has-pilots-8 .pilot-row[data-pilot="9"] {
    display: none;
}
/* When at MAX_PILOTS (9), hide the add slot. */
body.has-pilots-9 .pilot-add-slot { display: none; }

/* Add-pilot slot — mirrors the .pilot-row layout (same width,
   height, glass, avatar + name area) but with a tilted "+" where
   the number sits and "piloto" as the name, and the oblique
   stripe is white-translucent (no driver colour). No laps / time /
   indicators / A-M badge — markup omits those.

   We keep the slot OUTSIDE the .pilot-row class so the lobby JS
   (which iterates real rows to bind handlers / paint numbers /
   etc.) doesn't touch it. Styling is duplicated here from the
   pilot-row block. */
.pilot-add-slot {
    appearance: none;
    position: relative;
    /* Match the .pilot-row dimensions EXACTLY — same width clamp,
       max-width, margin auto, gap, padding, height, border-radius,
       glass treatment. Earlier the slot had a different effective
       width than the rows because it was missing max-width + auto
       margin (the rows use both to centre within .pilot-list). */
    display: flex;
    width: 100%;
    max-width: 1000px;
    margin: 8px auto 0;
    align-items: center;
    overflow: hidden;
    gap: clamp(12px, 1.8vw, 20px);
    padding-right: clamp(12px, 1.8vw, 24px);
    border-radius: var(--r-sm);
    height: 64px;
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    cursor: pointer;
    box-shadow: var(--glass-overlay), var(--glass-shadow);
    color: var(--White);
    text-align: left;
    /* Inherit the row's typography (button defaults to Arial 13px
       which made the "+" look out of family with the helmet
       numbers above). Pull font from the same stack as the row. */
    font-family: 'iA Writer Quattro', 'Funnel Display', system-ui, sans-serif;
    font-size: 15px;
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                background var(--dur-base) var(--ease-out);
}
.pilot-add-slot:hover {
    transform: translateY(-2px);
    box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.55) inset,
                0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 14px 0 rgba(0, 0, 0, 0.32),
                0 10px 28px 0 rgba(0, 0, 0, 0.35);
}
/* Override the per-pilot stripe colour: white at low opacity */
.pilot-add-slot .pilot-line {
    background-color: rgba(255, 255, 255, 0.32) !important;
    box-shadow: none !important;
}
/* Trapezoid SVG inside the avatar — already painted at 6% white
   via the inline fill on the path; nothing to override here. */

/* "+" placeholder in the number slot. Inherits the italic Quattro
   from .pilot-number above (size, weight, italic) so it sits
   exactly where a digit would. */
.pilot-add-slot .pilot-number {
    color: var(--White-56);
    text-shadow: none;
    filter: none;
    transition: color var(--dur-fast) var(--ease-out);
}
.pilot-add-slot .pilot-name {
    color: var(--White-40);
    text-transform: uppercase;
    font-style: italic;
    font-weight: 700;
    letter-spacing: 0.4px;
    transition: color var(--dur-fast) var(--ease-out);
}
.pilot-add-slot:hover .pilot-number,
.pilot-add-slot:hover .pilot-name {
    color: var(--White);
}
.pilot-add-slot:hover .pilot-line {
    background-color: rgba(255, 255, 255, 0.62) !important;
}

/* ============================================================
   SETTINGS PANEL — inline container that takes over the lobby
   area when body.settings-open. Same DOM neighbourhood as
   .pilot-list. Replaces the old floating dock-popover modal.
   ============================================================ */
.settings-panel {
    display: none;
    flex-direction: column;
    gap: 16px;
    width: 100%;
    max-width: 1000px;
    margin: 0 auto;
    padding: 130px 48px 24px;
}
body.settings-open .settings-panel { display: flex; }
body.settings-open .pilot-list { display: none; }

.settings-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 18px 22px 20px;
    border-radius: var(--r-sm);
    border: var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-overlay), var(--glass-shadow);
}
.settings-section-label {
    color: var(--White-56);
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-bottom: 8px;
}
.settings-row {
    display: grid;
    grid-template-columns: 96px 1fr 56px;
    align-items: center;
    gap: 16px;
    padding: 8px 0;
}
.settings-label {
    color: var(--White-56);
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 12px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}
.settings-value {
    color: var(--White);
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 12px;
}
.settings-actions {
    display: flex;
    gap: 10px;
    margin-top: 6px;
}
.settings-action {
    flex: 1;
    appearance: none;
    background: rgba(255, 255, 255, 0.04);
    color: var(--White);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--r-sm);
    padding: 10px 14px;
    cursor: pointer;
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    transition: background var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
}
.settings-action:hover {
    background: rgba(255, 255, 255, 0.10);
    border-color: rgba(255, 255, 255, 0.32);
}

/* Hover-X over the A/M badge: when you mouse over a .tire-indicator
   (the A/M lamp) the existing icon dims and a × glyph fades in on
   top, signalling "click to remove this pilot". lobby.js binds the
   click to drop the row. Skips the active human row by checking
   `body.race-running` (no removals mid-race). */
.tire-indicator { position: relative; }
.tire-indicator::after {
    content: '×';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--White);
    font-family: 'iA Writer Quattro', system-ui, sans-serif;
    font-size: 22px;
    font-weight: 700;
    line-height: 1;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-out);
    text-shadow: 0 0 8px rgba(255, 80, 80, 0.55);
}
body:not(.race-running) .pilot-row:hover .tire-indicator:hover::after {
    opacity: 1;
}
body:not(.race-running) .pilot-row:hover .tire-indicator:hover > svg {
    opacity: 0.20;
    transition: opacity var(--dur-fast) var(--ease-out);
}

.pilot-row:hover {
    transform: translateY(-2px);
    box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.55) inset,
                0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 14px 0 rgba(0, 0, 0, 0.32),
                0 10px 28px 0 rgba(0, 0, 0, 0.35);
}

.pilot-row .pilot-shape svg {
    transition: transform var(--dur-base) var(--ease-out);
}
.pilot-row .pilot-info {
    transition: transform var(--dur-base) var(--ease-out);
}
.pilot-row .pilot-avatar {
    transition: transform var(--dur-base) var(--ease-out),
                filter var(--dur-base) var(--ease-out),
                opacity var(--dur-base) var(--ease-out);
}

/* Parallax leve: el shape se desliza, el avatar gana un micro-lift y la
   info empuja en sentido contrario — efecto "card picking up". */
.pilot-row:hover .pilot-shape svg { transform: translateX(4px); }
.pilot-row:hover .pilot-avatar    { transform: translateY(-1px) scale(1.02); }
.pilot-row:hover .pilot-info      { transform: translateX(2px); }

/* Cursor-tracked specular highlight — same idea as the EMPEZAR
   button's polished-metal sheen, but anchored to the pointer
   position so it reads as a real reflection sliding across the
   glass surface as you move. JS (ui/lobby.js installCursorSheen)
   keeps the --mx / --my custom properties up to date on mousemove.
   --sheen-strength bumps with is-accelerating so the highlight
   reads "more lit, more reactive" without changing the row's box. */
.pilot-row::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 1;
    background: radial-gradient(
        180px circle at var(--mx, 50%) var(--my, 50%),
        rgba(255, 255, 255, var(--sheen-strength, 0)) 0%,
        rgba(255, 255, 255, calc(var(--sheen-strength, 0) * 0.45)) 30%,
        transparent 70%
    );
    opacity: 0;
    transition: opacity 280ms var(--ease-out);
    mix-blend-mode: screen;
}
.pilot-row:hover::before { opacity: 1; }
.pilot-row.is-accelerating::before { opacity: 1; }
/* keep all .pilot-row children above the sheen */
.pilot-row > * { position: relative; z-index: 2; }

/* Estado "acelerando": instead of casting a new shadow below the
   row, we animate WHAT'S ALREADY THERE — the glass itself reads as
   slightly whiter / freshly polished (a touch more inset-light, a
   touch less darkness on the bottom), the slip's halo brightens
   (handled in the .pilot-row.is-human / .is-ai filter rules), and
   the cursor-tracked highlight below picks up extra opacity. The
   row doesn't move, just gets "alive". */
.pilot-row.is-accelerating {
    box-shadow:
        0 2px 0 0 rgba(255, 255, 255, 0.16) inset,
        0 -1px 0 0 rgba(0, 0, 0, 0.28) inset,
        0 6px 18px -8px rgba(0, 0, 0, 0.30);
    --sheen-strength: 0.22;
}
.pilot-row.is-braking .pilot-time {
    color: #ff4757;
    text-shadow: 0 0 6px rgba(255, 71, 87, 0.55);
}

/* States */
/* is-leader only matters DURING the race — applying the red halo
   pre-race made the lobby look noisy (whoever was first in the grid
   got tagged before anyone had raced). Gate to body.race-running. */
body.race-running .pilot-row.is-leader {
    box-shadow:
        var(--glass-overlay),
        0 5px 16px -4px rgba(0, 0, 0, 0.32),
        inset 0 0 0 1px rgba(255, 255, 255, 0.18),
        0 0 22px -8px rgba(255, 255, 255, 0.28);
}

.pilot-row.is-fastest {
    animation: fastestPulse 2s var(--ease-out) 1;
}

.pilot-row.is-dnf {
    filter: saturate(0.2) brightness(0.6);
    cursor: default;
}
.pilot-row.is-dnf:hover { transform: none; }

.pilot-row.is-pit {
    filter: brightness(0.85);
}

.pilot-row.is-pit::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--Red);
    box-shadow: 0 0 8px var(--Red), 0 0 16px var(--Red-Glow);
    animation: pitStripeIn var(--dur-base) var(--ease-out) both;
}

.pilot-row.is-overtaking-up {
    box-shadow: 0 -8px 24px -8px rgba(255, 255, 255, 0.7),
                0 1px 1px 1px rgba(255, 255, 255, 0.55) inset,
                0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 14px 0 rgba(0, 0, 0, 0.32);
}

.pilot-row.is-overtaking-down {
    box-shadow: 0 8px 24px -8px rgba(227, 6, 19, 0.55),
                0 1px 1px 1px rgba(255, 255, 255, 0.4) inset,
                0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 14px 0 rgba(0, 0, 0, 0.32);
}

.pilot-row.just-lapped .pilot-laps {
    animation: lapFlash var(--dur-slow) var(--ease-out) 1;
}

/* ============================================
   LOBBY: humano vs AI
   - Por defecto todas las filas son AI (gris, opacas).
   - Click en el avatar → la fila pasa a is-human (full color).
   - Cuando empieza la carrera (body.race-running) el lobby se bloquea.
   ============================================ */
.pilot-avatar {
    cursor: pointer;
}
/* Pilot slip identity — split between two shapes:
     .pilot-shape svg  → the big angled TRAPEZOID behind the number
     .pilot-line       → the thin oblique STROKE on the right edge
   Both always 100% opacity, but:
     AI (default)  → ONLY the oblique stroke is lit. The trapezoid
                     reads muted/grayed so the row says "this seat
                     is on autopilot".
     HUMAN         → the WHOLE slip lights up — trapezoid in full
                     colour with a halo, stroke even brighter — so
                     a promoted seat reads as "real driver here". */
.pilot-row .pilot-shape svg,
.pilot-row .pilot-line {
    opacity: 1;
    transition: filter var(--dur-base) var(--ease-out);
}

/* AI: the trapezoid LOSES its colour entirely — its inline SVG
   fill is overridden to a subtle dark wash so the slip just reads
   as "muted background". The oblique stroke (.pilot-line) keeps
   the pilot colour, lit with an HDR halo — it's the only spot of
   colour identity on a bot row. */
.pilot-row.is-ai .pilot-shape svg path {
    fill: rgba(0, 0, 0, 0.20);
    transition: fill var(--dur-base) var(--ease-out);
}
.pilot-row.is-ai .pilot-shape svg { filter: none; }
.pilot-row.is-ai .pilot-line {
    filter: drop-shadow(0 0 6px var(--pilot-color, rgba(255,255,255,0.30)))
            drop-shadow(0 0 14px var(--pilot-color, rgba(255,255,255,0.16)))
            saturate(1.05);
}
.pilot-row.is-ai:hover .pilot-shape svg path { fill: rgba(0, 0, 0, 0.12); }
.pilot-row.is-ai:hover .pilot-line {
    filter: drop-shadow(0 0 9px var(--pilot-color, rgba(255,255,255,0.40)))
            drop-shadow(0 0 22px var(--pilot-color, rgba(255,255,255,0.22)))
            saturate(1.1);
}

/* Human: trapezoid lights up fully in the pilot's colour (overriding
   any AI dim) and gains an HDR halo. The whole slip reads as "this
   seat is occupied by a real driver". */
.pilot-row.is-human .pilot-shape svg path {
    fill: var(--pilot-color, #888);
    transition: fill var(--dur-base) var(--ease-out);
}
.pilot-row.is-human .pilot-shape svg {
    filter: drop-shadow(0 0 10px var(--pilot-color, rgba(255,255,255,0.50)))
            drop-shadow(0 0 22px var(--pilot-color, rgba(255,255,255,0.28)))
            saturate(1.05);
}
.pilot-row.is-human .pilot-line {
    filter: drop-shadow(0 0 10px var(--pilot-color, rgba(255,255,255,0.65)))
            drop-shadow(0 0 22px var(--pilot-color, rgba(255,255,255,0.32)))
            saturate(1.1);
}
/* Removed: the .pilot-row.is-ai::before vertical bar was duplicating
   the angled .pilot-shape slip as a second indicator. The angled
   slip itself (inline SVG, coloured per pilot) is now the only
   identifier in AI mode. */
/* Hover overlay clipped to the SAME trapezoid as the .pilot-shape
   SVG (path "M 0 0 L 0 68 L 60 68 L 72 0 Z"). Previous version was
   a plain rounded rectangle that didn't follow the slant — user
   feedback: "no tiene como la inclinación". clip-path: polygon
   uses the SVG path's normalised corners (72 wide / 68 tall =
   roughly 100% / 100% with the right side ramping in by 12/72
   ≈ 17%). */
.pilot-row.is-ai .pilot-avatar::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 0;
    clip-path: polygon(0% 0%, 100% 0%, 83% 100%, 0% 100%);
    background: rgba(255, 255, 255, 0);
    transition: background var(--dur-fast) var(--ease-out);
    pointer-events: none;
    z-index: 4;
}
.pilot-row.is-ai .pilot-avatar:hover::before {
    background: rgba(255, 255, 255, 0.10);
}

.pilot-row.is-human .pilot-avatar {
    filter: none;
    opacity: 1;
    animation: becomeHuman 380ms var(--ease-spring) 1;
    /* HUMAN halo — was a rounded-rect box-shadow which didn't match
       the trapezoid slip ("la capa de recorte no tiene la
       inclinación"). The halo is now painted by .pilot-shape svg's
       drop-shadow filter (already in place via .is-human .pilot-shape
       svg { filter: drop-shadow(...) } above). The avatar itself
       just keeps its position untouched — no rectangular box-shadow
       can match the slanted slip cleanly, so we let the SVG-path
       drop-shadow do the work since it auto-follows the path
       geometry. */
    box-shadow: none;
    border-radius: 0;
}

/* Pilot number — colour depends on row mode:
     AI    → white (matches .pilot-name, slip is now dark/neutral)
     HUMAN → dark "helmet number" on the bright pilot-coloured slip
   Both share size + italic Quattro from the .pilot-number base
   rule above. Animated so the AI ⇄ human toggle reads as a
   colour swap, not a snap. */
.pilot-row .pilot-number {
    opacity: 1;
    /* Bolder + tighter — reads as a real painted helmet number.
       Was 800; bumped to 900 (max) so the digit holds its
       presence against the colored glow stack below. */
    font-weight: 900;
    letter-spacing: -0.8px;
    transition: color var(--dur-base) var(--ease-out),
                text-shadow var(--dur-base) var(--ease-out);
}
/* AI: number tinted with the pilot color (so the row at a glance
   reads as "this is Senna" via the matching number + colored line).
   Falls back to white when the row hasn't set --pilot-color yet.
   Human: dark "helmet number" on the bright pilot-coloured slip. */
.pilot-row.is-ai .pilot-number {
    color: var(--pilot-color, var(--White, #fff));
    text-shadow: none;
    /* Stacked drop-shadows in the pilot's own colour — matches the
       same lighting language as .pilot-line / pilot-shape (their
       drop-shadow filters use 6+14px halos). The digit reads as
       an emissive helmet number lit from within. */
    filter:
        drop-shadow(0 0 4px rgba(var(--pilot-tint, 255, 255, 255), 0.62))
        drop-shadow(0 0 12px rgba(var(--pilot-tint, 255, 255, 255), 0.40))
        drop-shadow(0 0 22px rgba(var(--pilot-tint, 255, 255, 255), 0.22))
        saturate(1.1);
}
.pilot-row.is-human .pilot-number {
    color: rgba(0, 0, 0, 0.82);
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.22);
    filter: none;
}
/* HDR glow ONLY on active (human) pilot rows */
.pilot-row.is-human .pilot-name { text-shadow: var(--glow-hdr-soft); }
@keyframes becomeHuman {
    0%   { transform: scale(1);    filter: brightness(0.75) saturate(0.7); }
    55%  { transform: scale(1.10); filter: none; }
    100% { transform: scale(1);    filter: none; }
}
/* Marca discreta de "controlado por humano" — un punto luminoso junto al número */
/* Removed: the human-active dot indicator under the number. The
   activation cue now reads via the slip lighting up to full pilot
   colour + the A→M letter swap on the badge — no extra dot needed. */
.pilot-row.is-human .pilot-number::before { content: none; }

/* Nombre: editable solo cuando es humano */
.pilot-name {
    transition: color var(--dur-fast) var(--ease-out);
}
.pilot-row.is-human .pilot-name {
    cursor: text;
}
.pilot-row.is-human .pilot-name:focus {
    outline: none;
    box-shadow: var(--ring-focus);
    border-radius: var(--r-xs);
}
/* AI: name stays pure white (user feedback: "siguen como gris,
   deberían estar como en blanco y simplificados con el color del
   número"). Visual hierarchy between AI vs human now reads via the
   slip's brightness + the A→M letter on the badge, not via a faded
   name. */
.pilot-row.is-ai .pilot-name {
    color: var(--White, #fff);
    opacity: 1;
}

/* Durante carrera: lobby bloqueado */
body.race-running .pilot-avatar {
    cursor: default;
}
body.race-running .pilot-row.is-ai .pilot-avatar:hover {
    filter: grayscale(1) brightness(0.55) contrast(0.95);
    opacity: 0.7;
}
body.race-running .pilot-row.is-ai .pilot-avatar:hover::before {
    box-shadow: 0 0 0 1px transparent inset;
}

.pilot-avatar {
    width: 71px;
    height: 68px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: visible;
}

.pilot-number {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(calc(-50% - 6px), -50%);
    z-index: 3;
    color: var(--White, #FFF);
    text-align: center;
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off, 'tnum' on;
    /* Bigger + italic Quattro — reads as a real painted car number,
       and matches the italic upgrade on .pilot-name above. Click to
       edit (contenteditable wired in lobby.js). */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 26px;
    font-style: italic;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -1.5px;
    text-transform: none;
    cursor: text;
    caret-color: var(--White);
    /* Outline only on actual edit focus, not on hover */
    outline: none;
    min-width: 1ch;
}
.pilot-number[contenteditable="true"]:focus {
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);
}

.pilot-line {
    position: absolute;
    right: 0;
    z-index: 3;
    width: 8px;
    height: 71px;
    transform: rotate(10deg);
    border: 1px solid var(--White-Stroke, rgba(255, 255, 255, 0.6));
    background: var(--User-1, #3091B0);

    /* User/1 Shadow */
    box-shadow: 0 1px 9px 0 #3091B0, 0 1px 9px 0 #3091B0;
}

/* .pilot-color was a 40% BLACK overlay covering the entire avatar.
   It muddied the pilot slip into a dark brown/gray and — because
   the avatar is 68px tall inside a 64px row with overflow:visible —
   leaked the black 4px below the row, creating the "notch" the user
   spotted in the gap between rows. Killed it; the slip now reads
   in its true colour with the HDR halo below. */
.pilot-color { display: none; }

.pilot-shape {
    position: absolute;
    z-index: 0;
    width: 72px;
    height: 68px;
}

/* ============================================
   PILOT-INFO: CSS Grid. Filas alineadas pixel-perfect. La columna del
   nombre absorbe el espacio sobrante para eliminar el "hueco" muerto
   a la derecha; los indicadores se agrupan a la derecha con gap
   consistente.

   Columnas (de izquierda a derecha):
     1. pilot-name-row   → 1fr (crece, ellipsis si rebasa)
     2. pilot-laps       → auto (mínimo 24px)
     3. pilot-time       → auto (mono nums)
     4. indicator-group  → auto (gas)
     5. indicator-group  → auto (tyre)
     6. tire-indicator   → auto

   .pilot-col-left/right son `display: contents` así sus hijos se
   convierten en cells del grid directamente.
============================================ */
.pilot-info {
    flex: 1;
    min-width: 0;
    display: grid;
    grid-template-columns:
        minmax(120px, 1fr)            /* name + #id grows */
        minmax(24px, max-content)     /* laps */
        minmax(72px, max-content)     /* last lap time */
        auto                          /* gas indicator cluster */
        auto                          /* tyre indicator cluster */
        auto;                         /* tire compound */
    align-items: center;
    column-gap: clamp(14px, 1.6vw, 24px);
}

.pilot-col-left,
.pilot-col-right {
    display: contents;
}

.pilot-name-row {
    display: flex;
    align-items: baseline;
    justify-content: flex-start;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
}

.pilot-name {
    /* Principal element — white at full opacity. Size bumped 22→24
       to match .pilot-laps presence (user: "iguala el tamaño
       visual de jugador y número con vuelta y tiempo"). HDR glow
       ONLY when the row is active (is-human). */
    color: var(--White, #FFF);
    opacity: 1;
    text-shadow: none;
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 24px;
    font-style: italic;
    font-weight: 800;
    line-height: 1.2;
    letter-spacing: -0.2px;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Removed: the standalone "#12 / #5 / #44" next to the name was a
   duplicate of the avatar's grid number. Hidden by collapsing the
   separator dot + id span together. The pilot number lives ONLY in
   the avatar slip now — bigger, italic, click-editable. */
.pilot-dot,
.pilot-id { display: none; }

/* Laps + lap-time are the "same component" — both 7-Segment LCD
   readouts of race state on each pilot row. Sized to ~22px (same
   league as .pilot-name) and lit/dimmed in lockstep so they read
   as a single instrument. Both fade to --White-40 when the row's
   time slot still holds the dummy ("--:--.---") sentinel before
   a lap has been completed, so the row reads "no data yet"
   without literally hiding the digits.
   .pilot-laps gets the brighter glow because it's the headline
   integer; .pilot-time is the supporting detail. */
.pilot-laps {
    color: var(--White, #FFF);
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;
    font-family: "7-Segment", "Funnel Display", monospace;
    font-size: 24px;
    font-weight: 400;
    line-height: 1;
    text-align: right;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.12);
}

.pilot-status {
    font-size: 16px;
    font-weight: 600;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.pilot-status.pit { color: var(--Red); }

.pilot-time {
    font-family: "7-Segment", monospace;
    font-size: 22px;
    font-weight: 400;
    color: var(--White, #FFF);
    text-align: right;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 6px rgba(255, 255, 255, 0.10);
}

/* Pre-race / no-lap-yet state — both digits read at low brightness
   so the row says "no data" without going blank. The lobby init
   sets pilot-laps="0" and pilot-time="--:--.---" before any race;
   we match those sentinels via attribute-ish content classes. */
.pilot-row:not(.is-leader) .pilot-laps,
.pilot-row .pilot-time {
    transition: color var(--dur-fast) var(--ease-out),
                text-shadow var(--dur-fast) var(--ease-out);
}
body:not(.race-running) .pilot-laps,
body:not(.race-running) .pilot-time {
    color: var(--White-40);
    text-shadow: none;
}

.pilot-time.pit { color: var(--Red); }

.pilot-indicators {
    display: flex;
    gap: 24px;
    justify-items: center;
}

.indicator-group {
    display: flex;
    align-items: center;
    gap: 12px;
}

.indicator-label {
    color: var(--White-56, rgba(255, 255, 255, 0.56));
    leading-trim: both;
    text-edge: cap;
    font-feature-settings: 'liga' off, 'clig' off;

    /* 14 l UC */
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-style: normal;
    font-weight: 450;
    line-height: 140%; /* 19.6px */
    letter-spacing: 0.28px;
    text-transform: uppercase;
    min-width: 30px;
}

.indicator-lights {
    display: flex;
    align-items: center;
    gap: 4px;
}

.light {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.4);
    transition: background-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                transform var(--dur-base) var(--ease-spring),
                border-color var(--dur-base) var(--ease-out),
                opacity 380ms var(--ease-out);
}

/* Cascade entry — each light fades in with a staggered delay so the
   gas + tyre clusters "boot up" instead of all snapping on at once.
   Per-row delay = row index × 80ms (set by JS via --row-delay);
   per-light delay = nth-child × 60ms within the row. Net effect:
   8 rows × 5 lights × 2 indicators ≈ a confident hardware-startup
   sweep across the whole grid. */
body:not(.is-ready) .indicator-lights .light { opacity: 0; transform: scale(0.6); }
body.is-ready      .indicator-lights .light { opacity: 1; transform: scale(1); }
body.is-ready .indicator-lights .light:nth-child(1) { transition-delay: calc(1100ms + var(--row-delay, 0ms) +   0ms); }
body.is-ready .indicator-lights .light:nth-child(2) { transition-delay: calc(1100ms + var(--row-delay, 0ms) +  60ms); }
body.is-ready .indicator-lights .light:nth-child(3) { transition-delay: calc(1100ms + var(--row-delay, 0ms) + 120ms); }
body.is-ready .indicator-lights .light:nth-child(4) { transition-delay: calc(1100ms + var(--row-delay, 0ms) + 180ms); }
body.is-ready .indicator-lights .light:nth-child(5) { transition-delay: calc(1100ms + var(--row-delay, 0ms) + 240ms); }
/* indicator-group hover/focus state */
.indicator-group { transition: opacity var(--dur-base) var(--ease-out), max-width var(--dur-base) var(--ease-out); }
.indicator-group:hover { opacity: 0.92; }
.indicator-group:focus-visible { outline: none; box-shadow: var(--ring-focus); border-radius: 8px; }

.light.warning {
    background-color: var(--Amber);
    box-shadow: 0 1px 9px 0 var(--Amber), 0 1px 9px 0 var(--Amber);
}

.light.ok {
    background-color: var(--Green);
    box-shadow: 0 1px 9px 0 var(--Green), 0 1px 9px 0 var(--Green);
}

.light.off {
    background-color: rgba(255, 255, 255, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.2);
    box-shadow: none;
}

.light.is-pulsing {
    animation: lightPulse 1.4s var(--ease-in-out) infinite;
}

.light.just-changed {
    animation: lightSquash var(--dur-base) var(--ease-spring) 1;
}

.indicator-group { position: relative; }

.indicator-group::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(0,0,0,0.92);
    color: var(--White);
    font-size: 11px;
    font-weight: 450;
    letter-spacing: 0.22px;
    text-transform: uppercase;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
    z-index: 20;
    border: 1px solid var(--White-8);
}

.indicator-group:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.pilot-actions {
    display: flex;
    align-items: center;
    padding: 0 8px;
}

.action-icon {
    width: 24px;
    height: 24px;
    color: rgba(255, 255, 255, 0.5);
    cursor: pointer;
    transition: color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.action-icon:hover {
    color: #ffffff;
    transform: scale(1.1);
}

/* Tire indicator — repurposed as the AI/MANUAL pilot-control badge.
   AI rows show a dim "A" inside the brackets; human-controlled rows
   show a lit "M" with a soft white glow. The original SVG M letter
   (the third path with fill="white") is hidden so our ::before
   replacement reads as the only character. The golden brackets in
   the SVG stay — they're the badge frame either way. */
.tire-indicator {
    position: relative;
    width: 40px;
    height: 36px;
}
.tire-indicator > svg > path[fill="white"] { display: none; }
.tire-indicator::before {
    /* Pilot control badge — "A" for autopilot (default), "M" for
       manual. Letter sits inside the golden brackets that the SVG
       still renders. Upright (no italic) per user feedback —
       reads as a hard system indicator, not a typographic label. */
    content: 'A';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-style: normal;
    font-weight: 800;
    color: var(--White-40);
    pointer-events: none;
    z-index: 2;
    transition: color var(--dur-base) var(--ease-out),
                text-shadow var(--dur-base) var(--ease-out);
}
/* AI seat → badge reads as OFF in the same language as the tyre /
   menu-item OFF states: neutral grey outline, NO amber glow. We
   override the golden bracket fill AND neutralise the SVG's inline
   drop-shadow filter (whose feColorMatrix bakes in the amber
   #BE990A glow — that's what was making the A area still read
   yellow even after the fill was changed). */
.pilot-row.is-ai .tire-indicator > svg path[fill="#BE990A"],
.pilot-row.is-ai .tire-indicator > svg > g > path {
    fill: rgba(255, 255, 255, 0.30);
    /* Kill the white inner-stroke too — the SVG paints a second
       path with stroke="white" mix-blend-mode:overlay over each
       bracket arc. In AI mode we want a solid grey FILL, no
       outline, so the badge reads as a single shape (matching
       the user's "rellenas del mismo gris" feedback). */
    stroke: transparent;
    transition: fill var(--dur-base) var(--ease-out),
                stroke var(--dur-base) var(--ease-out);
}
.pilot-row.is-ai .tire-indicator > svg > g {
    filter: none !important;
}
.pilot-row.is-ai .tire-indicator > svg {
    opacity: 1;
    filter: none;
    transition: opacity var(--dur-base) var(--ease-out);
}
.pilot-row.is-ai .tire-indicator::before {
    color: var(--White-40);
    text-shadow: none;
}
.pilot-row.is-ai:hover .tire-indicator > svg > g > path {
    fill: rgba(255, 255, 255, 0.45);
}
.pilot-row.is-ai:hover .tire-indicator::before { color: var(--White-56); }

/* Human seat → badge READS AS LIT: brackets at full amber, letter
   pure white with a glow that matches the golden bracket halo, so
   the whole thing looks like a single illuminated lamp module. */
.pilot-row.is-human .tire-indicator > svg { opacity: 1; }
.pilot-row.is-human .tire-indicator::before {
    content: 'M';
    color: var(--White);
    text-shadow:
        0 0 6px rgba(190, 153, 10, 0.85),
        0 0 14px rgba(190, 153, 10, 0.50);
}

.tire-indicator img {
    width: 100%;
    height: 100%;
    transition: transform var(--dur-base) var(--ease-spring),
                opacity var(--dur-base) var(--ease-out);
}

.tire-indicator.is-swapping img {
    animation: tireSwap var(--dur-slow) var(--ease-out) 1;
}

.tire-indicator::after {
    content: attr(data-tire);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(0,0,0,0.92);
    color: var(--White);
    font-size: 11px;
    font-weight: 450;
    letter-spacing: 0.22px;
    text-transform: uppercase;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
    z-index: 20;
    border: 1px solid var(--White-8);
}

.tire-indicator:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ========================================
TABLET STYLES LANDSCAPE (1024px - 1199px)
======================================== */

@media (min-width: 1024px) and (max-width: 1199px) and (orientation: landscape) {

    .menu {
        padding: 0;
    }

    .submenu,
    .pilot-list {
        padding-left: 48px;
        padding-right: 48px;
    }

    .menu-item {
        width: 130px;
        padding: 18px 8px;
    }

    .submenu {
        margin-top: 20px;
    }

    .timer-section {
        padding: 20px;
        gap: 20px;
    }

    .timer-number,
    .timer-suffix,
    .timer-ms {
        font-size: 52px;
    }

    /* Pilot-info grid columns at tablet-landscape are tuned via
       @media (max-width: 1199px) above — no per-cell overrides needed */

    .tire-indicator {
        width: 24px;
        height: 24px;
    }
}

/* ========================================
TABLET STYLES PORTRAIT (768px - 1023px)
======================================== */

@media (min-width: 768px) and (max-width: 1023px) and (orientation: portrait) {
    .menu {
        padding: 12px 16px;
    }

    /* Keep the menu-left / menu-right groups HORIZONTAL — when the
       viewport is too narrow for the full text labels, we hide the
       span and let the icons + dividers carry the meaning. Dividers
       go back to their default vertical line shape so they read as
       separators between icons, not horizontal rules.
       (Earlier this query forced flex-direction:column which stacked
       the icons in a vertical column and pushed the menu too tall.) */
    .menu-left,
    .menu-right {
        flex-direction: row;
        align-items: center;
        gap: 10px;
    }

    .divider {
        width: 1px;
        height: 28px;
    }

    .menu-item span {
        display: none;
    }

    /* Icon-only mode: drop the wide clamp so 4-5 items per side fit
       comfortably even at ~800px wide. */
    .menu-item {
        width: 40px;
        padding: 6px;
        gap: 0;
    }

    .submenu {
        margin-top: 6px;
    }

    /* Push the pilot list further down so the EMPEZAR button (which
       sits inside the timer's "halo" area, top:128 + ~44 = bottom
       y≈172) keeps a 32 px+ breathing room from the first row. */
    .pilot-list {
        padding: 156px 8px 24px;
    }

    .pilot-info {
        gap: 16px;
    }

}

/* ========================================
   NARROW LANDSCAPE — viewport between ~768 and ~1100px wide in
   landscape orientation. The default desktop menu doesn't fit
   horizontally with the timer's reserved column-gap, so we use
   the same icon-only treatment as portrait tablet without the
   stacking. Keeps the chrome usable on small windows / older
   laptops / split-screen layouts.
   ======================================== */
@media (min-width: 768px) and (max-width: 1100px) and (orientation: landscape) {
    .menu-item span { display: none; }
    .menu-item {
        width: 40px;
        padding: 6px;
        gap: 0;
    }
    .menu {
        padding: 12px 16px;
        column-gap: clamp(16px, 4vw, 64px);
    }
    .pilot-list {
        padding: 150px 32px 24px;
    }
}

/* ========================================
MOBILE STYLES (390px - 767px)
======================================== */

@media (max-width: 767px) {

    .menu {
        display: none;
    }

    .timer-section {
        padding: 16px 0 16px 16px;
        gap: 16px;
    }

    .timer-block.weather .timer-label,
    .timer-divider:has(+ .timer-block.weather) {
        display: none;
    }

    .weather-icon {
        position: absolute;
        width: 16px;
        height: 16px;
        top: 8px;
        right: 16px;
    }

    .weather-icon svg {
        width: 16px;
        height: 16px;
    }

    .timer-value,
    .timer-suffix,
    .timer-number,
    .timer-ms {
        font-size: 48px;
    }

    .submenu {
        margin-top: 96px;
    }

    .pilot-line{
        height: 100px;
    }

    .pilot-list {
        padding: 24px 8px;
    }

    .pilot-row {
        max-width: auto;
        height: 89px;
    }

    .pilot-info {
        padding: 8px 0;
        align-items: left;
        gap: 16px;
    }

    .pilot-avatar {
        height: 100%;
    }

    .pilot-color {
        height: 110px;
    }

    .pilot-shape {
        height: 110px;
    }

    .pilot-shape svg {
        position: absolute;
        left: -20px;
        width: 130%;
        height: 100%;
    }

    .pilot-col-left,
    .pilot-col-right {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }

    .pilot-col-left > *,
    .pilot-col-right > * {
        height: 16px;
        display: flex;
        align-items: center;
    }

    .indicator-group {
        width: 100%;
        justify-content: space-between;
    }

    .tire-indicator {
        width: 28px;
        height: 16px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
}

/* ========================================
   ANIMATIONS & STATE LAYERS
   ======================================== */

/* Boot entry */
@keyframes rowIn {
    from { opacity: 0; transform: translateY(12px) scale(0.985); filter: blur(2px); }
    to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}

@keyframes timerIn {
    0%   { opacity: 0; transform: translateX(-50%) translateY(-16px) scale(0.97); filter: blur(3px); }
    60%  { opacity: 1; filter: blur(0); }
    100% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); filter: blur(0); }
}

/* Disabled — the keyframe was holding the timer at translateY(-16)
   even after completing, pushing its visual top above the intended
   `top: 42` anchor. Without it the timer animates via the body
   .is-ready transition (opacity/translateY) defined elsewhere. */
/* .timer-section { animation: timerIn var(--dur-x) var(--ease-out) both; } */

.pilot-row {
    animation: rowIn 420ms var(--ease-out) both;
    animation-delay: calc(55ms * var(--row-i, 0) + 220ms);
}

/* Lap counter flash */
@keyframes lapFlash {
    0% { color: var(--White); text-shadow: none; }
    20% {
        color: var(--Red);
        text-shadow: 0 0 12px rgba(227, 6, 19, 0.9), 0 0 24px rgba(227, 6, 19, 0.5);
    }
    100% { color: var(--White); text-shadow: none; }
}

.pilot-laps { transition: color var(--dur-fast) var(--ease-out); }

/* Light pulse (low resource warning) */
@keyframes lightPulse {
    0%, 100% { transform: scale(1); filter: brightness(1); }
    50% { transform: scale(1.15); filter: brightness(1.4); }
}

@keyframes lightSquash {
    0% { transform: scale(1); }
    40% { transform: scale(0.7); }
    100% { transform: scale(1); }
}

/* Pit stripe */
@keyframes pitStripeIn {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
}

/* Fastest lap pulse */
@keyframes fastestPulse {
    0%, 100% {
        box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.40) inset,
                    0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                    0 5px 7px 0 rgba(0, 0, 0, 0.24),
                    0 5px 14px 0 rgba(0, 0, 0, 0.25);
    }
    50% {
        box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.40) inset,
                    0 -1px 1px 0 rgba(255, 255, 255, 0.14),
                    0 5px 7px 0 rgba(0, 0, 0, 0.24),
                    0 0 32px -4px rgba(180, 80, 255, 0.7);
    }
}

/* Tire swap */
@keyframes tireSwap {
    0% { transform: scale(1) rotate(0); opacity: 1; }
    50% { transform: scale(0.4) rotate(-90deg); opacity: 0; }
    51% { transform: scale(0.4) rotate(90deg); opacity: 0; }
    100% { transform: scale(1) rotate(0); opacity: 1; }
}

/* Button loading dots */
@keyframes btnDots {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 1; }
}

/* Colon blink in timer — onda suave en vez de step duro */
@keyframes colonBlink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.32; }
}
.timer-number .colon { display: inline-block; animation: colonBlink 1.05s var(--ease-in-out) infinite; }

/* Weather */
.weather-icon { position: relative; }
.weather-icon svg { transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-spring); }
.weather-icon.is-changing svg { opacity: 0; transform: scale(0.6) rotate(-30deg); }

/* Countdown overlay */
.countdown {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(0,0,0,0.7);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease-out);
}

.countdown.is-active {
    opacity: 1;
    pointer-events: auto;
}

.countdown-number {
    font-family: "7-Segment", monospace;
    font-size: 200px;
    font-weight: 400;
    color: var(--White);
    text-shadow: 0 4px 8px rgba(0,0,0,0.5),
                 0 0 24px rgba(255,255,255,0.7),
                 0 0 80px rgba(255,255,255,0.4);
    letter-spacing: 4px;
}

.countdown-number.go {
    color: var(--Red);
    text-shadow: 0 4px 8px rgba(0,0,0,0.5),
                 0 0 24px var(--Red),
                 0 0 80px var(--Red-Glow);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-weight: 800;
    text-transform: uppercase;
    font-size: 160px;
    letter-spacing: 8px;
}

@keyframes countIn {
    0% { transform: scale(0.4); opacity: 0; }
    20% { transform: scale(1.1); opacity: 1; }
    80% { transform: scale(1); opacity: 1; }
    100% { transform: scale(1.6); opacity: 0; }
}

.countdown-number.is-animating { animation: countIn 800ms var(--ease-spring) 1 forwards; }

.countdown-flash {
    position: fixed;
    inset: 0;
    background: var(--White);
    z-index: 1100;
    opacity: 0;
    pointer-events: none;
}

.countdown-flash.is-firing {
    animation: flashGo 280ms var(--ease-out) 1;
}

@keyframes flashGo {
    0% { opacity: 0; }
    15% { opacity: 0.85; }
    100% { opacity: 0; }
}

/* Rain overlay */
.rain-overlay {
    position: fixed;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(40,80,140,0.18), rgba(20,40,80,0.08));
    opacity: 0;
    transition: opacity var(--dur-x) var(--ease-out);
    z-index: 5;
    mix-blend-mode: screen;
}
.rain-overlay.is-active { opacity: 1; }

/* Toast */
.toast {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%) translateY(-120%);
    background: rgba(20,20,20,0.95);
    color: var(--White);
    padding: 10px 16px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.3px;
    border: 1px solid var(--White-8);
    box-shadow: 0 8px 24px -8px rgba(0,0,0,0.6);
    z-index: 900;
    transition: transform var(--dur-slow) var(--ease-spring);
    text-transform: uppercase;
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 90vw;
}

.toast.is-visible { transform: translateX(-50%) translateY(0); }

.toast .toast-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--Red);
    box-shadow: 0 0 8px var(--Red-Glow);
}

/* Podium / race end */
.podium {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: radial-gradient(ellipse at center, rgba(40,20,20,0.6), rgba(0,0,0,0.92));
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 24px;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-x) var(--ease-out);
    padding: 32px;
}

.podium.is-visible { opacity: 1; pointer-events: auto; }

.podium-title {
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 14px;
    font-weight: 450;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--White-56);
}

.podium-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
    max-width: 600px;
}

.podium-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 20px;
    border-radius: 8px;
    background: var(--Black-Linear);
    border: 1px solid var(--Black);
    box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.20) inset,
                0 5px 14px 0 rgba(0, 0, 0, 0.35);
    color: var(--White);
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    text-transform: uppercase;
}

.podium-row .place {
    font-family: "7-Segment", monospace;
    font-size: 36px;
    color: var(--White);
    min-width: 48px;
    text-align: center;
    text-shadow: 0 0 8px rgba(255,255,255,0.4);
}

.podium-row .pname { flex: 1; font-weight: 600; font-size: 16px; }
.podium-row .ptime { font-family: "7-Segment", monospace; font-size: 18px; color: var(--White-56); }

.podium-row.p1 {
    box-shadow: 0 1px 1px 1px rgba(255, 255, 255, 0.40) inset,
                0 0 32px -4px rgba(227, 6, 19, 0.5),
                0 5px 14px 0 rgba(0, 0, 0, 0.4);
    transform: scale(1.04);
}
.podium-row.p1 .place { color: var(--Red); text-shadow: 0 0 12px var(--Red-Glow); }

.podium-close {
    margin-top: 24px;
    background: transparent;
    color: var(--White-56);
    border: 1px solid var(--White-8);
    padding: 10px 20px;
    border-radius: 8px;
    cursor: pointer;
    font-family: 'iA Writer Quattro', "Funnel Display", system-ui, sans-serif;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    transition: color var(--dur-fast), border-color var(--dur-fast);
}
.podium-close:hover { color: var(--White); border-color: var(--White-56); }

/* Confetti */
.confetti {
    position: absolute;
    width: 8px; height: 14px;
    pointer-events: none;
    will-change: transform;
}

@keyframes confettiFall {
    0% { transform: translateY(-20vh) rotate(0); opacity: 1; }
    100% { transform: translateY(120vh) rotate(720deg); opacity: 0; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
        scroll-behavior: auto !important;
    }
    .pilot-row.is-overtaking-up,
    .pilot-row.is-overtaking-down { box-shadow: none; }
}
