/* === GoFast Overlays — Figma Design System === */

/* --- Design Tokens --- */
:root {
    --gf-green: #4DE95F;
    --gf-red: #FF3C22;
    --gf-cyan: #33DAEC;
    --gf-purple: #E285FF;
    --gf-orange: #FFB84D;
    --gf-blue: #549AFF;
    --gf-teal: #00C1D5;

    /* Damage readout status colours (defaults = original literals; overridden
       per colourblind type below). */
    --gf-dmg-ok: #00FF6A;
    --gf-dmg-ok-2: #4DE99C;
    --gf-dmg-ok-glow: rgba(0, 255, 106, 0.45);
    --gf-dmg-warn: #FF7919;
    --gf-dmg-warn-2: #FF5622;
    --gf-dmg-warn-glow: rgba(255, 121, 25, 0.50);
    --gf-dmg-crit: #FF0051;
    --gf-dmg-crit-2: #FF3C22;
    --gf-dmg-crit-glow: rgba(255, 0, 81, 0.60);
    /* Damage METER shares the readout colours but uses stronger glow opacity. */
    --gf-dmgm-ok-glow: rgba(0, 255, 106, 0.55);
    --gf-dmgm-warn-glow: rgba(255, 121, 25, 0.55);
    --gf-dmgm-crit-glow: rgba(255, 0, 81, 0.65);

    /* Delta-bar pill colours (ahead/behind). Ahead literal differs from
       --gf-green; behind equals --gf-red so it reuses that token below. */
    --gf-deltabar-ahead: #00FF6A;

    /* Pedal / input bar colours. */
    --gf-throttle: #27E88D;

    /* Steering-delta gradient colours (steerOrange band in PedalsOverlay). */
    --gf-steer-orange: #FF6F1B;
    --gf-steer-orange-2: #FF3A20;

    /* EssentialInputs gear-icon accent colour. */
    --gf-ei-gear: #3DDC6A;

    /* EssentialInputs throttle / brake bar gradients (good / bad pair). */
    --gf-ei-throttle: #3DDC6A;
    --gf-ei-throttle-2: #5BFFA1;
    --gf-ei-brake: #FF4136;
    --gf-ei-brake-2: #FF7567;

    /* Corner-analysis delta colours (good = faster, bad = slower). Distinct
       literals from --gf-green/red; defaults = originals, overridden per type. */
    --gf-corner-good: #3ddc84;
    --gf-corner-bad: #ff4d4d;

    /* Position-marker "marginal" (yellow) gradient. Yellow stays distinguishable
       for red-green types, so only tritanopia overrides it. */
    --gf-posmid-1: #FFD700;
    --gf-posmid-2: #FFA500;

    --gf-bg: rgba(0, 0, 0, 0.50);
    --gf-bg-row-alt: rgba(255, 255, 255, 0.03);
    --gf-bg-player: rgba(77, 233, 95, 0.10);
    --gf-border: rgba(255, 255, 255, 0.06);
    --gf-text: #FFFFFF;
    --gf-text-dim: rgba(255, 255, 255, 0.50);
    --gf-text-muted: rgba(255, 255, 255, 0.35);

    --gf-radius: 8px;
    --gf-radius-sm: 4px;
    --gf-font-data: 'Satoshi', sans-serif;
    --gf-font-label: 'Satoshi', sans-serif;
    --gf-row-height: 32px;
    --gf-font-size: 13px;
}

/* --- Reset --- */
/* SCOPED to .gf-ov so this bundle can be loaded app-wide (index.html) for the
   in-app Overlays preview pane without its universal reset / transparent body /
   scrollbar-hide leaking into MainLayout. The overlay host page (overlay-host.html)
   carries .gf-ov on #app, so live overlay rendering is byte-identical there.
   If overlays.css is ever re-imported, RE-APPLY this .gf-ov scoping. */
/* Overlays are display-only: never allow text selection/highlight (WebView2
   sometimes lets a drag highlight overlay text, which looks broken). */
.gf-ov, .gf-ov * { box-sizing: border-box; margin: 0; padding: 0; user-select: none; -webkit-user-select: none; }

/* newui.css (loaded app-wide by the main app's index.html, but NOT by the
   overlay host / WebHost) sets `div, form { display: grid; position: relative }`
   as a layout primitive. Overlays were authored against the host (no newui), so
   their container divs assume normal block flow — under newui's grid default the
   children stretch to fill (the Target lap-picker rows ballooned in the in-app
   settings preview while the live overlay stayed correct). Reset divs inside the
   overlay scope back to block so the preview matches the host (WYSIWYG). Wrapped
   in :where() so the specificity stays at the .gf-ov class level — every overlay
   that needs flex/grid sets it explicitly later in this file and still wins. */
.gf-ov :where(div) { display: block; }

.gf-ov {
    background: transparent;
    font-family: var(--gf-font-data);
    font-size: var(--gf-font-size);
    color: var(--gf-text);
    -webkit-font-smoothing: antialiased;
}

.gf-ov ::-webkit-scrollbar { display: none; }

/* "Hide when not driving" gate. Class toggled by OverlayRoot when
   ShouldHideForDriving() returns true. !important + visibility-collapse
   in case any inline style on the wrapper or descendant panels would
   otherwise win the cascade. Belt-and-braces so this can't be defeated
   by inline styles set elsewhere. */
#gf-overlay-root.gf-overlay-root-hidden,
#gf-overlay-root.gf-overlay-root-hidden * {
    display: none !important;
    visibility: hidden !important;
}

/* --- Position Change Flash --- */
@keyframes pos-flash-green {
    0%   { background: rgba(77, 233, 95, 0.25); }
    100% { background: transparent; }
}
@keyframes pos-flash-red {
    0%   { background: rgba(255, 60, 34, 0.25); }
    100% { background: transparent; }
}
.pos-gained { animation: pos-flash-green 1.5s ease-out forwards; }
.pos-lost   { animation: pos-flash-red 1.5s ease-out forwards; }

/* --- Overlay Panel (base container) --- */
.overlay-panel {
    color: var(--gf-text);
    border-radius: var(--gf-radius);
    font-family: var(--gf-font-data);
    font-size: var(--gf-font-size);
    overflow: visible;
    animation: overlay-panel-enter 0.45s cubic-bezier(0.2, 0.9, 0.25, 1.05) both;
    /* Isolate each panel's layout scope. Without containment, an update
       inside one panel (e.g. Standings cell value change) can invalidate
       layout for the entire document. `contain: layout` tells the browser
       the panel's box affects only itself for layout — no ancestor
       recompute, no cross-panel layout invalidation.
       NOTE: `paint` is deliberately NOT included — it would clip painted
       content to the panel's padding box, cutting off the lock badge
       (which sits half-outside via negative top/right), the Standings
       fastest-lap badge, the Target slide-out dropdown, and other
       intentional overflow. `style` and `size` are also excluded because
       per-panel CSS-variable inheritance is load-bearing for the
       depth-treatment + colourblind systems. */
    contain: layout;
    /* Touch (tablet Second Screen): claim the gesture so a press-drag moves the
       panel instead of the browser scrolling/zooming the page. Without this,
       pointermove gets cancelled the instant a touch-drag starts. */
    touch-action: none;
}

@keyframes overlay-panel-enter {
    0%   { opacity: 0; filter: blur(6px); }
    60%  { opacity: 1; filter: blur(0); }
    100% { opacity: 1; filter: blur(0); }
}

/* Stale-telemetry state: sim connected but data frozen (watchdog, Phase 3).
   Subtle dim only — do NOT use filter/backdrop/overflow here, they break
   WebGL canvases in WebView2 (overlay WebGL memory). opacity is compositor-safe. */
.overlay-panel.overlay-stale {
    opacity: 0.5;
    transition: opacity 0.25s ease;
}

/* --- Waiting-for-sim placeholder: dark liquid-glass card, 10px rounded,
       hairline border, top-left title + pulsing cyan dot. Matches
       mockup/waiting-hush-v2.html. --- */
.overlay-waiting-placeholder {
    box-sizing: border-box;
    position: fixed; /* overridden by inline style */
    padding: calc(16px * var(--panel-inv, 1)) calc(18px * var(--panel-inv, 1));
    overflow: visible;
    isolation: isolate;
    background:
        linear-gradient(155deg,
            rgba(255, 255, 255, 0.04) 0%,
            rgba(255, 255, 255, 0.008) 40%,
            rgba(255, 255, 255, 0) 75%),
        rgba(0, 0, 0, 0.45);
    border: none;
    border-radius: 10px;
    backdrop-filter: blur(calc(18px * var(--gf-bdf-k, 1))) saturate(105%);
    -webkit-backdrop-filter: blur(calc(18px * var(--gf-bdf-k, 1))) saturate(105%);
    box-shadow:
        0 6px 22px rgba(0, 0, 0, 0.35),
        0 2px 6px rgba(0, 0, 0, 0.25);
    user-select: none;
    animation:
        overlay-waiting-breath 5.2s ease-in-out infinite,
        overlay-waiting-fade-in 0.35s ease-out both;
}
/* Specular sheen across the top — the tell of a liquid-glass surface. */
.overlay-waiting-placeholder::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 40%;
    pointer-events: none;
    border-radius: 10px 10px 0 0;
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.05) 0%,
        rgba(255, 255, 255, 0.01) 50%,
        transparent 100%);
    mix-blend-mode: overlay;
    z-index: 0;
}

.overlay-waiting-content {
    position: relative;
    z-index: 1;
    display: inline-block;
    font-family: 'Satoshi', sans-serif;
}

.overlay-waiting-name {
    display: block;
    font-family: 'Satoshi', sans-serif;
    font-weight: 900;
    font-size: calc(14px * var(--panel-inv, 1));
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: #d8d8d8;
    line-height: 1;
}

.overlay-waiting-status {
    display: inline-flex;
    align-items: center;
    gap: calc(7px * var(--panel-inv, 1));
    margin-top: calc(10px * var(--panel-inv, 1));
    font-family: 'Satoshi', sans-serif;
    font-weight: 900;
    font-size: calc(10px * var(--panel-inv, 1));
    letter-spacing: 0.18em;
    text-transform: lowercase;
    color: #8a8a8a;
    line-height: 1;
    white-space: nowrap;
}

.overlay-waiting-dot {
    width: calc(5px * var(--panel-inv, 1));
    height: calc(5px * var(--panel-inv, 1));
    border-radius: 50%;
    background: #3ddc84;
    box-shadow:
        0 0 4px rgba(61, 220, 132, 0.75),
        0 0 9px rgba(61, 220, 132, 0.45);
    animation: overlay-waiting-pulse 1.8s ease-in-out infinite;
    flex-shrink: 0;
}

@keyframes overlay-waiting-breath {
    0%, 100% { opacity: 0.9; }
    50%      { opacity: 1; }
}

@keyframes overlay-waiting-pulse {
    0%, 100% { opacity: 0.35; transform: scale(0.85); }
    50%      { opacity: 1;    transform: scale(1); }
}

@keyframes overlay-waiting-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* --- Edit Mode --- */
.overlay-panel.edit-mode {
    /* Crisp GO FAST green outline (Input Comparison throttle green #27E88D),
       always visible while editable — no hover gating. Previously the rule
       was hover-only and would blink off when the cursor moved onto the
       corner-action discs that sit above the panel; making it persistent
       sidesteps that hit-test edge case entirely. */
    outline: 1.5px solid #27E88D;
    cursor: move;
    pointer-events: auto;
}

/* Handles live inside the scaled panel, so we size them in panel coord
   space using calc() with --panel-inv (= 1 / panel scale). That way the
   final visual size after the panel's transform:scale is constant. */
.panel-scale-btn {
    --btn-size: calc(28px * var(--panel-inv, 1));
    --btn-half: calc(14px * var(--panel-inv, 1));
    --btn-icon: calc(14px * var(--panel-inv, 1));
    position: absolute;
    width: var(--btn-size);
    height: var(--btn-size);
    border-radius: 50%;
    background: #fff no-repeat center center;
    background-size: var(--btn-icon) var(--btn-icon);
    opacity: 0;
    transition: opacity 120ms ease;
    z-index: 100;
    pointer-events: auto;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
/* Invisible hit-area extender — grows with the inverse scale too. */
.panel-scale-btn::before {
    content: "";
    position: absolute;
    inset: calc(-12px * var(--panel-inv, 1));
}
/* Width handle — floats on the right edge, vertical middle */
.panel-scale-btn.horizontal {
    right: calc(-1 * var(--btn-half));
    top: 50%;
    margin-top: calc(-1 * var(--btn-half));
    background-image: url('../icons/scale-horizontal.svg');
    cursor: ew-resize;
}
/* Height handle — floats on the bottom edge, horizontal middle */
.panel-scale-btn.vertical {
    bottom: calc(-1 * var(--btn-half));
    left: 50%;
    margin-left: calc(-1 * var(--btn-half));
    background-image: url('../icons/scale-vertical.svg');
    cursor: ns-resize;
}
/* Uniform-scale handle — bottom-right corner */
.panel-scale-btn.diagonal {
    right: calc(-1 * var(--btn-half));
    bottom: calc(-1 * var(--btn-half));
    background-image: url('../icons/scale-diagonal.svg');
    cursor: nwse-resize;
}
body.wpf-unlocked .overlay-panel .panel-scale-btn,
.overlay-panel.edit-mode .panel-scale-btn {
    opacity: 1;
}
.panel-scale-btn:hover {
    transform: scale(1.25);
    background-color: rgba(255, 255, 255, 1);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
.panel-scale-btn:active {
    transform: scale(1.1);
    background-color: rgba(200, 200, 200, 1);
}

/* --- Per-panel lock badge ---
   Floats just outside the top-right corner of any panel in live mode.
   Hidden by default — only becomes visible once the WPF host unlocks the
   window via hover-dwell (body gets `wpf-unlocked`) OR when this specific
   panel has been explicitly unlocked by the user (so the re-lock toggle
   stays accessible). Clicking toggles PanelLocks for this OverlayId. */
.panel-lock-btn {
    /* Icon is rendered via ::after with translate(-50%, -50%) rather than
       background-image. Why: --panel-inv produces fractional raw pixel sizes
       at non-1.0 panel scales (e.g. badge raw 13px at scale 2.0), and
       background-position: center then snaps subpixels inconsistently —
       icon drifts horizontally and the drift compounds as panel scale grows.
       ::after's translate(-50%, -50%) centers in terms of the element's own
       size, so the two halves cancel into stable integer positions. */
    --btn-size: calc(26px * var(--panel-inv, 1));
    --btn-half: calc(13px * var(--panel-inv, 1));
    --btn-icon: calc(13px * var(--panel-inv, 1));
    position: absolute;
    top: calc(-1 * var(--btn-half));
    right: calc(-1 * var(--btn-half));
    width: var(--btn-size);
    height: var(--btn-size);
    box-sizing: border-box;
    border-radius: 50%;
    background: #0a0a0a;
    border: calc(1px * var(--panel-inv, 1)) solid rgba(61, 220, 132, 0.5);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(8px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.6),
        0 0 calc(8px * var(--panel-inv, 1)) rgba(61, 220, 132, 0.25);
    opacity: 0;
    transform-origin: center center;
    transition: opacity 140ms ease, transform 140ms ease;
    z-index: 101;
    pointer-events: auto;
    cursor: pointer;
}
.panel-lock-btn::before {
    /* Invisible hit-area halo extending outside the badge. */
    content: "";
    position: absolute;
    inset: calc(-10px * var(--panel-inv, 1));
}
.panel-lock-btn::after {
    /* The icon. Centered via translate(-50%, -50%) so position math collapses
       to integer pixels regardless of panel scale. */
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--btn-icon);
    height: var(--btn-icon);
    transform: translate(-50%, -50%);
    background: url('../icons/lock.svg') no-repeat center / contain;
    pointer-events: none;
}
.panel-lock-btn.unlocked::after {
    background-image: url('../icons/unlock.svg');
}
.panel-lock-btn.unlocked {
    border-color: rgba(61, 220, 132, 0.9);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(8px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.6),
        0 0 calc(12px * var(--panel-inv, 1)) rgba(61, 220, 132, 0.55);
}
/* Locked badge is a status indicator only — the press-and-hold gesture
   (drag.js, hold-to-toggle-lock affordance) is the way to unlock.
   pointer-events:none kills the hover scale AND any click route, so the
   badge sits inert. Only .unlocked is interactive (click-to-re-lock). */
.panel-lock-btn.locked {
    pointer-events: none;
    cursor: default;
}
/* Hover feedback uses brightness + glow (no transform scale). Scaling a 26px
   circular badge by 1.08 resamples the 14×14 SVG strokes at non-integer
   subpixel positions on every hover-in/out, which reads as the icon
   "wobbling". A non-transform cue keeps the icon pixel-stable. */
.panel-lock-btn.unlocked:hover {
    border-color: rgba(61, 220, 132, 1);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(8px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.6),
        0 0 calc(16px * var(--panel-inv, 1)) rgba(61, 220, 132, 0.75);
}

/* Once a panel is unlocked, its badge stays visible as the "unlocked" cue and
   an alternate click-to-re-lock. (Unlocking itself is the press-and-hold
   gesture below, not the badge.) */
body.wpf-unlocked .panel-lock-btn,
.overlay-panel .panel-lock-btn.unlocked {
    opacity: 1;
}

/* ── Hold-to-toggle-lock affordance (driven by drag.js) ─────────────────────
   Press and hold a panel to unlock it (green border) or re-lock it (slate
   border). drag.js builds these as body-level elements so Blazor re-renders
   can't wipe them. A dim layer covers the panel; the app's footer spinner
   (icons/loader.svg) sits at the panel's centre while the hold runs;
   completing fires a pulse. */
.gf-hold {
    position: fixed;
    z-index: 2147483646;
    pointer-events: none;
    border-radius: 10px;
    background: rgba(8, 10, 14, 0.28);
    box-shadow: inset 0 0 0 1.5px rgba(39, 232, 141, 0.45);
    animation: gf-hold-in 120ms ease both;
}
.gf-hold.gf-hold--relock {
    box-shadow: inset 0 0 0 1.5px rgba(168, 188, 207, 0.45);
}
@keyframes gf-hold-in { from { opacity: 0; } to { opacity: 1; } }
.gf-hold__spinner {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 40px;
    height: 40px;
    margin: -20px 0 0 -20px;   /* centre on the panel, not the cursor */
    filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.55));
}
/* Completion: no flash / glow bloom — the dim veil + spinner simply fade out.
   (An earlier version bloomed a coloured glow into the background on the
   toggle; removed per feedback.) The resting green/slate border just fades
   with the layer. Keep in sync with drag.js _endHold removal delay. */
.gf-hold.gf-hold--done { animation: gf-hold-out 180ms ease forwards; }
@keyframes gf-hold-out { to { opacity: 0; } }

/* The OverlayRoot container is pointer-events:none in live mode (so the page
   doesn't swallow clicks — window-level region click-through handles the gaps).
   That left the panel BODY non-interactive: only explicitly-auto children (the
   lock badge) got hover/press, so the hold-to-unlock gesture and its hint never
   fired on the overlay itself. Opt the panel back in so press/hover reach it;
   the gaps between panels still pass through at the window level. */
.overlay-panel {
    pointer-events: auto;
}

/* Hold-to-unlock HOVER VEIL removed 2026-06-11 (user: distracting while
   driving — the dim + "Hold left-click to unlock" prompt covered live data on
   every accidental mouse-over). The hold GESTURE itself still works (drag.js)
   and the corner lock badge still appears once a panel is unlocked; only the
   hover prompt visual is gone. The first-run intro card teaches the controls
   instead. */

/* Placeholder already has its own dashed border — don't double it up in edit mode. */
.overlay-panel.overlay-waiting-placeholder.edit-mode {
    outline: none;
}

/* Kill the specular sheen's blend mode WHILE editable (the only state the
   placeholder is ever dragged in). mix-blend-mode: overlay forces Chromium to
   recompute the blend against the backdrop every frame, and doing that as the
   panel moves via left/top makes it flicker. The real (live) state keeps the
   sheen untouched — flicker only ever shows during a drag, which is edit-only.
   The faint white gradient still reads; it just composites with plain alpha. */
.overlay-panel.overlay-waiting-placeholder.edit-mode::before {
    mix-blend-mode: normal;
}

/* Per-overlay default sizing. The inner wrapper fills the panel at 100%, so
   the edit-mode guide always hugs the visible content. Inline width/height
   from saved Position.Width/Height overrides these defaults. */
.overlay-panel[data-overlay-id="delta"]:not(.overlay-waiting-placeholder)    { min-width: 270px; width: max-content; }
.overlay-panel[data-overlay-id="position"]:not(.overlay-waiting-placeholder) { min-width: 340px; width: max-content; }
/* Full track-map mode → square (380×380, aspect-ratio locked).
   Position-bar mode → wide horizontal strip with the bar's natural height. */
.overlay-panel[data-overlay-id="trackMap"]:not(.overlay-waiting-placeholder):has(.track-map-bar) {
    min-width: 480px; width: max-content;
}
.overlay-panel[data-overlay-id="trackMap"]:not(.overlay-waiting-placeholder):not(:has(.track-map-bar)) {
    width: 380px;
    aspect-ratio: 1;
}
.overlay-panel[data-overlay-id="miniMap"]:not(.overlay-waiting-placeholder)  { width: 220px; aspect-ratio: 1; }
/* Damage (2026-06 redesign): a compact fixed-size HUD. Hug the content so the
   panel box, the hover/edit border and the preview fit-scale all match the
   232-wide rendered overlay EXACTLY. Without this the box stays at the saved /
   old min-width/min-height (e.g. 500×664), so it's larger than the body — the
   border doesn't hug it and there's dead space clipped at the bottom. !important
   beats the inline min-width/min-height GetPositionStyle writes. */
.overlay-panel[data-overlay-id="damage"]:not(.overlay-waiting-placeholder) {
    min-width: 0 !important;
    min-height: 0 !important;
    width: 252px;          /* = .damage-body; definite (max-content collapses the width:100% child) */
    height: auto;          /* hug the content height so the box matches the body, no dead space */
}
.overlay-panel[data-overlay-id="weather"]:not(.overlay-waiting-placeholder)  { min-width: 360px; width: max-content; }
/* Vertical weather is a FIXED narrow column (not the 360px horizontal strip).
   The vertical layout stretches/wraps its content to fill the box
   (align-items:stretch, .weather-cell width:100% + space-between), so it must
   NOT use width:max-content: the live values (air/track temp, wind speed,
   compass label, sky/track text) change the widest line every tick, so
   max-content makes the panel width JUMP on each update. A fixed width holds
   steady; the saved Position.Width (inline min-width floor) still lets the user
   drag-grow it. MUST also set min-width here: the base weather rule above sets
   min-width:360px, so overriding `width` alone would leave that 360 floor in
   force (max(min-width:360, width:200) = 360) and pin vertical at the
   horizontal width. min-width:200 lowers the floor to match. */
.overlay-panel[data-overlay-id="weather"]:not(.overlay-waiting-placeholder):has(.weather-panel.vertical) { min-width: 200px; width: 200px; }
/* Delta bar default width 22em -> 26em (beta feedback: too small out of the
   box). The inner track/panel are width:100%, so the side drag still widens it
   further; this only lifts the floor a new user sees. */
.overlay-panel[data-overlay-id="deltaBar"]:not(.overlay-waiting-placeholder) { min-width: 26em; width: max-content; }
.overlay-panel[data-overlay-id="pedals"]:not(.overlay-waiting-placeholder)   { min-width: 380px; width: max-content; }
/* Pedals hug-on-untick: the 380px floor exists for the trace graph (the row's
   flex:1 element, the only thing that stretches). With the trace hidden
   nothing flexes, so the floor just shows as empty background to the right of
   the remaining widgets and strands the delta tab (justify-end) far from the
   content — kill the floor and let width:max-content hug exactly. !important
   also beats the saved-width inline min-width from GetPositionStyle, same as
   the damage rule above. Applies everywhere the stylesheet does: live window,
   settings preview, VR capture. */
.overlay-panel[data-overlay-id="pedals"]:not(.overlay-waiting-placeholder):not(:has(.inp-traces)) {
    min-width: 0 !important;
}
.overlay-panel[data-overlay-id="essentialInputs"]:not(.overlay-waiting-placeholder) { min-width: 540px; width: max-content; }
.overlay-panel[data-overlay-id="radar"]:not(.overlay-waiting-placeholder)    { width: 280px; aspect-ratio: 1; }
.overlay-panel[data-overlay-id="damage"]:not(.overlay-waiting-placeholder)   { min-width: 470px; width: max-content; }
/* Relatives: empty-state rows have no content so `min-width: min-content` on
   .rel-row collapses to 0, making the whole panel shrink when no cars are
   loaded (and grow back when data arrives — a visible size jump on every
   session start / lap-start in LMU especially). Anchor a sensible default
   width like the other table overlays so the panel size is stable from
   empty → full. */
/* width:max-content so the panel GROWS to fit enabled columns (SR/iR/Best/Last/
   Avg/…). With .rel-name now a FIXED 170px slot, max-content is fully
   deterministic (columns + 170) — so the old 380px floor drops to 280:
   unticking columns genuinely narrows the table ("always as tight as
   possible"). 280 only catches the empty-state collapse (no-cars rows have
   no content; .rel-row's min-width:min-content would let the panel implode
   and re-grow on session start). The side drag stays available: a saved
   drag width floors the panel via the inline min-width and the name column
   (flex-grow) absorbs the extra room; drag back inward to return to the
   tight width. Standings: same model below. */
.overlay-panel[data-overlay-id="relatives"]:not(.overlay-waiting-placeholder) { min-width: 280px; width: max-content; }
.overlay-panel[data-overlay-id="standings"]:not(.overlay-waiting-placeholder) { min-width: 280px; width: max-content; }

/* Invisible edge hit areas — full-length strips along the panel edges
   so the user can drag-resize from anywhere on the dashed outline.
   These share the resize-handle-* classes with the icon buttons so
   drag.js treats both identically. */
.panel-edge-right {
    position: absolute;
    top: 0;
    right: -5px;
    width: 10px;
    height: 100%;
    cursor: ew-resize;
    z-index: 9;
    pointer-events: auto;
}
.panel-edge-bottom {
    position: absolute;
    bottom: -5px;
    left: 0;
    width: calc(100% - 14px);
    height: 10px;
    cursor: ns-resize;
    z-index: 9;
    pointer-events: auto;
}
/* Bottom-right corner scale grip — drawn as a textarea-style diagonal
   stripe in the corner. Visible only in edit mode (via .edit-mode parent). */
.panel-edge-corner {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 14px;
    height: 14px;
    cursor: nwse-resize;
    z-index: 10;
    pointer-events: auto;
    background: linear-gradient(135deg,
        transparent 0%,
        transparent 45%,
        rgba(255,255,255,0.85) 45%,
        rgba(255,255,255,0.85) 60%,
        transparent 60%,
        transparent 70%,
        rgba(255,255,255,0.65) 70%,
        rgba(255,255,255,0.65) 85%,
        transparent 85%);
}

.edit-overlay-name {
    position: absolute;
    top: -20px;
    left: 0;
    font-size: 10px;
    font-family: var(--gf-font-label);
    color: var(--gf-text-dim);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    font-weight: 600;
    pointer-events: none;
}

/* Per-panel close button — paired with the lock badge for "hide this overlay
   while driving" workflow. Visible only when the panel is per-panel-unlocked
   via the lock badge; clicking persists IsVisible=false on the settings record.
   Structured identically to .panel-lock-btn (circular badge, ::after icon
   centered with translate(-50%, -50%) so position math is integer-stable at
   any panel scale). */
.panel-close-btn {
    --btn-size: calc(26px * var(--panel-inv, 1));
    --btn-half: calc(13px * var(--panel-inv, 1));
    --btn-icon: calc(13px * var(--panel-inv, 1));
    --btn-gap: calc(6px * var(--panel-inv, 1));
    position: absolute;
    /* Sits on the TOP edge, immediately to the LEFT of the lock badge. Keeps
       the right edge fully clear so .resize-handle-right has room to grab on
       narrow panels (the prior "stacked below lock" layout ate the right-edge
       drag strip on small overlays). Lock occupies the top-right corner;
       close sits just inside that, both sticking up by btn-half. */
    top: calc(-1 * var(--btn-half));
    right: calc(var(--btn-half) + var(--btn-gap));
    width: var(--btn-size);
    height: var(--btn-size);
    box-sizing: border-box;
    padding: 0;
    border-radius: 50%;
    background: #0a0a0a;
    border: calc(1px * var(--panel-inv, 1)) solid rgba(61, 220, 132, 0.5);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(8px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.6),
        0 0 calc(8px * var(--panel-inv, 1)) rgba(61, 220, 132, 0.25);
    cursor: pointer;
    pointer-events: auto;
    transform-origin: center center;
    transition: border-color 140ms ease, box-shadow 140ms ease;
    z-index: 101;
}
.panel-close-btn::before {
    /* Hit-area halo — matches the lock badge's ::before. */
    content: "";
    position: absolute;
    inset: calc(-10px * var(--panel-inv, 1));
}
.panel-close-btn::after {
    /* The × icon. Centered via translate(-50%, -50%). */
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--btn-icon);
    height: var(--btn-icon);
    transform: translate(-50%, -50%);
    background: url('../icons/close.svg') no-repeat center / contain;
    pointer-events: none;
}
.panel-close-btn:hover {
    border-color: rgba(61, 220, 132, 1);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(8px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.6),
        0 0 calc(16px * var(--panel-inv, 1)) rgba(61, 220, 132, 0.75);
}

/* ============================================================
   INSET CORNER ACTIONS — integrated panel chrome
   ============================================================
   The lock indicator and close button live ON the panel surface, in the
   top-right corner, rather than as a separate floating bar. This reads as
   panel chrome — part of the same designed object as the panel itself —
   instead of a disconnected widget hovering above. The title is rendered
   separately as the existing .edit-overlay-name label above the panel.

   Both buttons share .corner-btn so size/hover/icon footprint are guaranteed
   identical. Icons via CSS `mask` so the same SVG can be recolored (white at
   rest, full white on hover, green for unlocked lock state, soft red wash
   on close hover) without separate asset files.

   Visibility (driven by Razor):
     - Lock indicator button: only in live mode (per-panel unlock semantics)
     - Close button: only when this panel is per-panel-unlocked

   Sizes inverse-scaled via --panel-inv so chrome stays a consistent visual
   size regardless of the panel's --panel-scale.
   ============================================================ */

.overlay-corner-actions {
    position: absolute;
    /* Sits ABOVE the panel — floating chrome on top of the overlay rather
       than inside it. Calculated so the discs hover with a 6px gap above
       the panel's top edge. cb-size (26px) + gap (6px) = 32px lift, all
       inverse-scaled so the gap stays visually consistent at any panel scale. */
    top: calc(-32px * var(--panel-inv, 1));
    right: calc(6px * var(--panel-inv, 1));
    display: flex;
    align-items: center;
    gap: calc(6px * var(--panel-inv, 1));
    z-index: 101;
    pointer-events: none; /* Container is purely a layout box; buttons re-enable. */

    /* Promote this subtree to its own compositing layer so the white discs +
       mask icons paint atomically the first frame they appear. Without this,
       Chromium can commit the disc background and the mask::after paint in
       separate frames when the parent panel has contain:layout + transform —
       which reads as a "half rendered" cut on the unlock transition. */
    transform: translateZ(0);
    will-change: transform;
}

.corner-btn {
    --cb-size: calc(26px * var(--panel-inv, 1));
    --cb-icon: calc(14px * var(--panel-inv, 1));

    width: var(--cb-size);
    height: var(--cb-size);
    padding: 0;
    box-sizing: border-box;

    /* Secondary-button pattern: clean white disc at rest, throttle-green
       fill on hover. Icons (rendered via mask on ::after) stay dark in both
       states for consistent legibility. */
    background: white;
    border: calc(1px * var(--panel-inv, 1)) solid rgba(0, 0, 0, 0.12);
    border-radius: 50%;
    box-shadow: 0 calc(2px * var(--panel-inv, 1)) calc(6px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.35);
    cursor: pointer;

    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;

    pointer-events: auto;
    transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}

.corner-btn:hover {
    background: var(--gf-throttle);
    border-color: color-mix(in srgb, var(--gf-throttle) 60%, black);
    box-shadow:
        0 calc(2px * var(--panel-inv, 1)) calc(6px * var(--panel-inv, 1)) rgba(0, 0, 0, 0.35),
        0 0 calc(14px * var(--panel-inv, 1)) color-mix(in srgb, var(--gf-throttle) 70%, transparent);
}

/* Icon rendered as a CSS mask so background-color can recolor it. Dark
   ink against the bright green fill gives clean contrast and matches the
   sim's HUD readability conventions. */
.corner-btn::after {
    content: "";
    width: var(--cb-icon);
    height: var(--cb-icon);
    background-color: #0a0e14;
    -webkit-mask: var(--cb-icon-url, none) no-repeat center / contain;
    mask: var(--cb-icon-url, none) no-repeat center / contain;
    transition: background-color 140ms ease;
    pointer-events: none;
}

/* ── Lock indicator ─────────────────────────────────────────────────────── */
.corner-btn-lock {
    --cb-icon-url: url('../icons/lock.svg');
}
.corner-btn-lock.unlocked {
    --cb-icon-url: url('../icons/unlock.svg');
}
/* Locked is a status indicator only — actual unlock is the press-and-hold
   gesture (drag.js). No hover, no click. Dimmed so the contrast with the
   active "unlocked" state reads clearly. */
.corner-btn-lock.locked {
    pointer-events: none;
    cursor: default;
    opacity: 0.55;
}

/* ── Close button ──────────────────────────────────────────────────────── */
.corner-btn-close {
    --cb-icon-url: url('../icons/close.svg');
}

/* ============================================================
   STANDINGS — Multiclass v13
   ============================================================ */
.st-root {
    display: flex;
    flex-direction: column;
    gap: var(--st-section-gap, 10px);
}

.st-root.compact {
    --st-section-gap: 3px;
    --st-row-gap: 5px;
    --st-row-pad-y: 2px;
    --st-head-pad-y: 2px;
    --st-head-mb: 2px;
    --st-pit-h: 17px;
    --st-badge-h: 23px;
}

.st-row {
    display: flex;
    align-items: center;
    gap: var(--st-row-gap, 8px);
    padding: var(--st-row-pad-y, 5px) 10px;
    position: relative;
    font-variant-numeric: tabular-nums;
    min-width: min-content;
    /* Isolate per-row reflow: position/lap/delta/fuel updates on one row
       don't invalidate layout across the other 22-30 rows. `layout` only —
       NOT `paint` — because `.st-fastest-badge` uses translateX(100%) to
       sit outside the row's right edge and paint containment would clip it. */
    contain: layout;
}

.st-row > * { z-index: 1; }

.st-row .st-grad {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 50px;
    z-index: 0;
    pointer-events: none;
}

.st-row.is-player {
    background: linear-gradient(90deg, transparent 0%, var(--player-color, rgba(74, 207, 132, 0.20)) 50%, transparent 100%);
}

.st-pos {
    font-weight: 800;
    font-size: 15px;
    width: 22px;
    text-align: center;
    flex-shrink: 0;
}

.st-num {
    font-weight: 700;
    font-size: 14px;
    width: 36px;
    text-align: center;
    color: rgba(255, 255, 255, 0.5);
    flex-shrink: 0;
}

.st-logo {
    width: 18px;
    height: 18px;
    border-radius: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    flex-shrink: 0;
    object-fit: contain;
}

.st-name {
    /* 170px BASIS name slot — see .rel-name for the full rationale: the
       tight (natural) width stays deterministic (columns + 170) so unticking
       columns narrows the table and long names can't widen it, while a
       drag-widened panel gives all the extra room to the name via grow. */
    flex: 1 1 170px;
    font-size: 14px;
    font-weight: 500;
    overflow: hidden;
    white-space: nowrap;
    mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
}

/* Endurance team layout (StandingsSettings.ShowTeamName): team name is the
   primary line, the current driver sits dim beneath it. Applied per row via
   .team-stack — only on entries that carry real team data, so single-driver
   rows are unaffected. The row grows naturally; .st-row already centres the
   taller cell. The base .st-name mask still fades long team names on the right. */
.st-name.team-stack {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.08;
    gap: 1px;
    white-space: normal;
}
.st-name.team-stack .st-team {
    font-size: 13.5px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
}
.st-name.team-stack .st-driver {
    font-size: 11px;
    font-weight: 500;
    color: var(--gf-text-dim);
    white-space: nowrap;
    overflow: hidden;
}

.st-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    border-radius: 4px;
    padding: 3px 6px;
    font-size: 11px;
    font-weight: 700;
    flex-shrink: 0;
    box-sizing: border-box;
    height: 22px;
}

.st-license {
    width: 52px;
    text-align: center;
    background: var(--lic-bg);
    border: 1px solid var(--lic-color);
    color: var(--lic-color);
}

.st-irating {
    width: 76px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.st-ir-val {
    color: rgba(255, 255, 255, 0.7);
    font-weight: 600;
    line-height: 1;
}

.st-ir-arrow {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
}

.st-ir-arrow svg {
    width: 8px;
    height: 8px;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
    display: block;
}

.st-ir-change { font-weight: 600; line-height: 1; }

.st-data {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    flex-shrink: 0;
}

.st-gap {
    /* Width tracks the gap/interval decimal count via --gapdec (set on the overlay
       root from Settings.Decimals), same pattern as --lapdec on the lap columns:
       ~7px (one tabular digit) narrower per decimal below 3. Also .st-int/.rel-gap.
       Base 54 (was 58): FormatGap NEVER emits minute form (+NL takes over when
       lapped), so the worst case is 3-digit seconds ("+199.9" ≈ 38.5px at 1 dec,
       52.5px at 3) — 54 still clears that at every decimal count while dropping
       the typical "+12.3" dead air to match the lap columns' slack. */
    width: calc(54px - (3 - var(--gapdec, 3)) * 7px);
    text-align: right;
    font-weight: 600;
    font-size: 13px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

/* Optional columns (default off). Position-change arrow sits beside the
   position; Average lap matches the gap/last column metrics, dimmed. */
.st-poschg {
    width: 16px;
    text-align: center;
    font-weight: 700;
    font-size: 10px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.st-avg {
    /* Lap-time column width scales with the decimal count via --lapdec (set on the
       overlay root): ~7px (one tabular digit) narrower per decimal below 3, so 1-2
       decimals don't reserve the 3-decimal width. Same on .st-last/.st-best/.rel-lap.
       Base 68 MATCHES .st-best/.st-last exactly: Avg renders the same FormatLapTime
       string, and its old 58px base sat ~10px tighter against its neighbour than the
       other lap columns (uneven column spacing). */
    width: calc(68px - (3 - var(--lapdec, 3)) * 7px);
    text-align: right;
    font-weight: 600;
    font-size: 13px;
    flex-shrink: 0;
    color: var(--gf-text-dim);
    font-variant-numeric: tabular-nums;
}

/* Race-control flags. Session flag sits by the race badge (green/yellow/red)
   and gently flutters; per-car checkered overlays the row's far-right edge in
   the EXISTING space (absolute → no reserved width, no row jump). */
.rcflag { display: block; }
/* Session flag = static flag on a thin staff with a waving banner, filled with
   the state gradient. A soft dark shadow keeps it legible over any row colour. */
.st-rcflag {
    display: inline-flex;
    align-items: center;
    width: 25px;
    height: 16px;
    flex: 0 0 auto;
    margin: 0 3px;
}
.st-rcflag .rcflag {
    width: 25px;
    height: 16px;
    filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.5));
}
.st-finflag {
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 9;
    width: 22px;
    height: 17px;
    pointer-events: none;
}
/* Checkered keeps the dark depth shadow the old shared `.rcflag` rule used to
   provide (the session pill now glows instead). */
.st-finflag .rcflag { width: 22px; height: 17px; filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55)); }

/* ── Per-car flag/penalty indicators (Standings + Relative) ──────────────────
   A RESERVED fixed-width slot sits after the car number on EVERY row (rendered
   even when empty) so a flag never shifts the columns. The indicator is a
   uniform rounded rectangle — the flag banner shape, no pole — all variants the
   same footprint. Finished cars instead get a short checkered FILL that fades in
   from the right edge (.ovflag-chk, absolute -> no reserved width). Blue (being
   lapped) is NOT here -- it stays the row/text colour treatment.
   See project_overlay_percar_flags_design. */
.ovflag-slot {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 32px; width: 32px; height: 15px; margin-left: 5px;
}
.ovflag {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 14px; border-radius: 2.5px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 1px 1px rgba(0, 0, 0, 0.55);
    font-weight: 800; font-size: 8px; letter-spacing: 0.02em; line-height: 1;
    background: #16181c; color: #fff;
}
.ovflag-dot { width: 6px; height: 6px; border-radius: 50%; background: #FF7A1A; display: block; }
.ovflag-pen { background: #FFC400; color: #1c1402; }
.ovflag-dsq { background: #E5352B; color: #fff; }
.ovflag-bw  { background: linear-gradient(90deg, #16181c 0 50%, #e8e8e8 50% 100%); }
/* Checkered fill + right vignette for a finished car. z-index 2 to sit above the
   row content (`.st-row > * { z-index: 1 }`). The host row must be positioned
   (st-row / rel-row already are, for their gradient layer). */
.ovflag-chk {
    position: absolute; top: 0; right: 0; bottom: 0; width: 34px;
    pointer-events: none; z-index: 0; opacity: 0.85;
    background-color: #cfd3d8;
    background-image: linear-gradient(45deg, #15171a 25%, transparent 25%, transparent 75%, #15171a 75%),
                      linear-gradient(45deg, #15171a 25%, transparent 25%, transparent 75%, #15171a 75%);
    background-size: 7px 7px; background-position: 0 0, 3.5px 3.5px;
    -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.35) 55%, rgba(0, 0, 0, 1) 100%);
    mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.35) 55%, rgba(0, 0, 0, 1) 100%);
}

/* Per-car flag as a RIGHT-EDGE fill that fades in from the right — same family
   and vignette as the checkered finish fill above, but sitting BEHIND the row
   text (z-index:0; the gap/name float on top with a legibility shadow). Built
   by OverlayFlagHelper.RightFill (severity precedence); checkered (.ovflag-chk,
   finished) is the same family. Host row is positioned. */
.ovflag-rt {
    position: absolute; top: 0; right: 0; bottom: 0; width: 34px;
    pointer-events: none; z-index: 0; opacity: 0.85;
    -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.35) 55%, rgba(0, 0, 0, 1) 100%);
    mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.35) 55%, rgba(0, 0, 0, 1) 100%);
}
.ovflag-rt-dsq      { background: #e5352b; }
/* black-and-white (furled) warning */
.ovflag-rt-warn     { background: repeating-linear-gradient(45deg, #101012 0 6px, #e9e9e9 6px 12px); }
/* meatball (repair) — orange/black hazard stripes (distinct from the b/w warn) */
.ovflag-rt-meatball { background: repeating-linear-gradient(45deg, #ff7a00 0 7px, #201406 7px 14px); }
/* penalty — amber fill + a vertical label (SG30 / DT / …) */
.ovflag-rt-pen      { background: #ffc400; }
/* black flag — black can't read as a faded tint on a dark row, so it's a glossy
   black GRADIENT (grey→black, top-lit) at full opacity with a shorter fade. */
.ovflag-rt-black {
    opacity: 1;
    background: linear-gradient(180deg, #7a7e88 0%, #2c2f35 40%, #060607 100%);
    -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.6) 32%, #000 68%);
    mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.6) 32%, #000 68%);
}
/* vertical label (penalty / DSQ): reads UP with tops to the LEFT, flush at the
   far-right edge (opaque zone) so it stays legible behind the gap number. */
.ovflag-rt-lbl {
    position: absolute; right: 1px; top: 50%; transform: translateY(-50%) rotate(180deg);
    writing-mode: vertical-rl; text-orientation: mixed; white-space: nowrap;
    font-weight: 800; font-size: 8.5px; letter-spacing: 0.04em; line-height: 1;
}
.ovflag-rt-pen .ovflag-rt-lbl { color: #1c1402; }
.ovflag-rt-dsq .ovflag-rt-lbl { color: #fff; }
/* legibility: the gap/name float above the flag fill with a soft dark shadow so
   they stay crisp over the bright flags (amber/red/checkered). */
.st-row .st-gap, .st-row .st-name,
.rel-row .rel-gap, .rel-row .rel-name { text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 2px rgba(0, 0, 0, 0.6); }

/* Country-flag cell (iRacing flair). flag-icons paints the SVG via the `fi
   fi-<code>` classes; we just fix the box size + rounded corners. Empty (no
   flair / non-iRacing) → blank reserved slot so columns stay aligned. */
.st-flag,
.rel-flag {
    width: 20px;
    height: 14px;
    flex-shrink: 0;
    border-radius: 2px;
    background-size: cover;
    /* Extra gap from the car logo so the flag reads with the driver name
       (number + logo = the car; flag + name = the driver). */
    margin-left: 6px;
}

.st-int {
    /* Base 54 — same sizing + rationale as .st-gap above. */
    width: calc(54px - (3 - var(--gapdec, 3)) * 7px);
    text-align: right;
    font-weight: 600;
    font-size: 13px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.st-last {
    width: calc(68px - (3 - var(--lapdec, 3)) * 7px);
    text-align: right;
    font-size: 13px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.st-best {
    width: calc(68px - (3 - var(--lapdec, 3)) * 7px);
    text-align: right;
    font-size: 13px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.st-pit { text-align: center; height: var(--st-pit-h, 22px); }

/* 4-corner tyre-compound grid (Standings). FL/FR = front, RL/RR = rear.
   Cell colours live in .tc-* classes so colourblind mode can remap them; an
   Unknown corner keeps the faint base fill. */
.st-tyre-grid {
    display: grid;
    grid-template-columns: 9px 9px;
    grid-template-rows: 9px 9px;
    gap: 2px;
    flex-shrink: 0;
    align-self: center;
    margin-left: 2px;
}

.st-tyre-cell {
    border-radius: 2px;
    background: rgba(154, 166, 178, 0.22);
}

/* Single circle = compound RING: coloured rim + dark core + compound-colour
   letter (no outer glow). The two-class .st-tyre-dot.tc-* selectors out-specify
   the filled .tc-* rule below so the core stays dark. */
.st-tyre-dot {
    width: 19px;
    height: 19px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 800;
    line-height: 1;
    text-align: center;
    flex-shrink: 0;
    align-self: center;
    margin-left: 2px;
    background: radial-gradient(circle at 50% 36%, #11161d, #06090d);
    border: 1.5px solid rgba(154, 166, 178, 0.5);
    color: #cdd5e0;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75);
}

.st-tyre-dot.tc-soft { background: radial-gradient(circle at 50% 36%, #11161d, #06090d); border-color: #F2F2F2; color: #F2F2F2; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75); }
.st-tyre-dot.tc-med  { background: radial-gradient(circle at 50% 36%, #11161d, #06090d); border-color: #FFD23F; color: #FFD23F; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75); }
.st-tyre-dot.tc-hard { background: radial-gradient(circle at 50% 36%, #11161d, #06090d); border-color: #FF3B3B; color: #FF6E6E; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75); }
.st-tyre-dot.tc-wet  { background: radial-gradient(circle at 50% 36%, #11161d, #06090d); border-color: #2EA6FF; color: #6FC4FF; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75); }
.st-tyre-dot.tc-dry  { background: radial-gradient(circle at 50% 36%, #11161d, #06090d); border-color: #9AA6B2; color: #C2CAD4; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.75); }

/* LMU compound colours (LMU's own convention — NOT F1's): Soft = white,
   Medium = yellow, Hard = red, Wet = blue. Dry = grey (iRacing single dry /
   generic fallback). */
.tc-soft { background: #F2F2F2; }
.tc-med  { background: #FFD23F; }
.tc-hard { background: #FF3B3B; }
.tc-wet  { background: #2EA6FF; }
.tc-dry  { background: #9AA6B2; }

/* Pit indicator — fixed-width column rendered inside every row when ANY pit
   activity exists in the session. Centred content; .is-empty placeholder
   keeps the column reserved on rows that haven't pitted so the gap / int /
   best / last columns line up vertically across every row. Row tint
   (.st-row.has-pit-active / .has-pit-done) provides the "live" cue. Width
   sized for the worst-case L###·###s label (≈ 85 px text + dot + gap). */
.st-pit-col {
    width: 100px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    color: #00FFDC;
    white-space: nowrap;
    box-sizing: border-box;
}
.st-pit-col.is-done {
    color: rgba(0, 255, 220, 0.68);
    font-weight: 600;
}
.st-pit-col.is-empty {
    /* keeps the 100 px width contribution; renders no chrome */
}
.st-pit-dotmark {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 6px currentColor;
    flex-shrink: 0;
}
.st-pit-col.is-done .st-pit-dotmark {
    box-shadow: none;
    background: transparent;
    border: 1.5px solid currentColor;
    width: 7px;
    height: 7px;
}
.st-pit-text { display: inline-block; }
.st-pit-timer { font-variant-numeric: tabular-nums; }

/* Subtle cyan wash that fades in from the right end of the row. Stronger
   for an active stop (you're looking at someone in pit RIGHT NOW), barely
   there for a past stop. Sits on .st-row so it co-exists with the left-side
   .st-grad class-colour gradient. */
.st-row.has-pit-active {
    background: linear-gradient(90deg, transparent 60%, rgba(0, 255, 220, 0.08));
}
.st-row.has-pit-done {
    background: linear-gradient(90deg, transparent 75%, rgba(0, 255, 220, 0.035));
}
/* The pit washes above share .st-row's specificity with .is-player and are
   declared LATER, so on the PLAYER's own pitting row they were overriding the
   green self-highlight — making you impossible to find after your first stop
   (has-pit-done sticks all race). Re-assert the player highlight at higher
   specificity, LAYERED on top of the pit wash so both still read: you stay
   highlighted AND the pit cue remains. */
.st-row.is-player.has-pit-active {
    background:
        linear-gradient(90deg, transparent 0%, var(--player-color, rgba(74, 207, 132, 0.20)) 50%, transparent 100%),
        linear-gradient(90deg, transparent 60%, rgba(0, 255, 220, 0.08));
}
.st-row.is-player.has-pit-done {
    background:
        linear-gradient(90deg, transparent 0%, var(--player-color, rgba(74, 207, 132, 0.20)) 50%, transparent 100%),
        linear-gradient(90deg, transparent 75%, rgba(0, 255, 220, 0.035));
}

.st-battery {
    width: auto;
    gap: 6px;
    /* A touch more horizontal padding than the base .st-badge (6px) so the
       right-aligned used-energy value isn't flush against the pill border. */
    padding: 3px 9px;
    font-size: var(--font-size, 12px);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.st-battery-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.st-bat-val {
    width: 36px;
    text-align: right;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.st-bat-used {
    width: 42px;
    text-align: right;
    color: #fff;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* Category bar */
.st-cat-bar {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: var(--st-head-pad-y, 4px) 10px;
    margin-bottom: var(--st-head-mb, 3px);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: 6px;
    overflow: hidden;
    /* Session header bar: fixed-size, infrequent updates. Free isolation. */
    contain: layout;
}

.st-cat-bar > * { z-index: 1; }

.st-session-badge {
    font-weight: 900;
    font-size: 15px;
    color: rgba(255, 255, 255, 0.95);
    letter-spacing: 0.5px;
}

/* Class name fallback in the category bar — shown for classes we don't ship
   an icon for (the long tail of iRacing categories). Styled to mirror the
   class-icon SVGs: a rounded-rect badge with a 1px border + text, both in the
   class colour. The icons use stroke+fill in the class colour; here `color`
   is set inline to the class colour and `currentColor` drives the border so
   the badge matches. Height matches the 28px icons so the bar lines up. */
.st-cat-name {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 8px;
    box-sizing: border-box;
    border: 1px solid currentColor;
    border-radius: 4px;
    font: 800 14px/1 var(--gf-font-label, 'Satoshi', sans-serif);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

/* One-make class header: the actual car name (e.g. "Mazda MX-5") in place of a
   generic class label/icon. Same bordered chip as .st-cat-name but mixed-case
   and width-capped with an ellipsis so long names ("Mercedes-AMG GT3 …") don't
   blow out the header. inline-block (not flex) so text-overflow works. */
.st-car-name {
    display: inline-block;
    max-width: 150px;
    height: 28px;
    padding: 0 8px;
    box-sizing: border-box;
    border: 1px solid currentColor;
    border-radius: 4px;
    /* Line-height MUST live inside the `font` shorthand: a separate
       `line-height` before it gets clobbered by the shorthand's implicit value,
       which left the text sitting high. 26px = the 28px chip minus 1px top +
       1px bottom border, so the single line centres vertically. */
    font: 800 13px/26px var(--gf-font-label, 'Satoshi', sans-serif);
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
}


.st-cat-grad {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 50px;
    z-index: 0;
    pointer-events: none;
}

.st-cat-info {
    font-size: 13px;
    font-weight: 600;
    color: rgba(255, 255, 255, 1);
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-variant-numeric: tabular-nums;
}

.st-cat-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.st-cat-icon svg {
    width: 14px;
    height: 14px;
    stroke: rgba(255, 255, 255, 1);
    fill: none;
    stroke-width: 1.5;
}

.st-mat-icon svg {
    fill: rgba(255, 255, 255, 1);
    stroke: none;
    stroke-width: 0;
}

/* Fastest lap badge */
.st-rows-wrap { position: relative; }

.st-fastest-badge {
    position: absolute;
    right: 0;
    transform: translateX(100%);
    height: var(--st-badge-h, 28px);
    width: 28px;
    border-radius: 0 6px 6px 0;
    background: linear-gradient(90deg, rgba(180, 80, 255, 0.45), rgba(180, 80, 255, 0.1));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3;
}

.st-fastest-badge svg {
    width: 16px;
    height: 16px;
    stroke: #C470FF;
    fill: none;
    stroke-width: 2;
}

/* ============================================================
   RELATIVE OVERLAY — v3
   ============================================================ */
.rel-root {
    display: contents;
}
.rel-root.compact {
    --rel-row-gap: 4px;
    --rel-row-pad-y: 2px;
    --rel-row-min-h: 25px;
    --rel-info-pad-y: 3px;
    --rel-info-mb: 2px;
    --rel-foot-pad-y: 3px;
    --rel-foot-mt: 2px;
}
.rel-row {
    display: flex;
    align-items: center;
    gap: var(--rel-row-gap, 6px);
    padding: var(--rel-row-pad-y, 6px) 12px;
    position: relative;
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    min-width: min-content;
    min-height: var(--rel-row-min-h, 38px);
    box-sizing: border-box;
    /* Per-row reflow isolation. See .st-row for the rationale. */
    contain: layout;
}
.rel-row.rel-row-empty {
    pointer-events: none;
}

.rel-row > * { z-index: 1; }

.rel-row .rel-grad {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 50px;
    z-index: 0;
    pointer-events: none;
}

.rel-row.is-player {
    background: linear-gradient(90deg, transparent 0%, var(--player-color, rgba(74, 207, 132, 0.20)) 50%, transparent 100%);
}

.rel-pos {
    font-weight: 800;
    font-size: 17px;
    width: 26px;
    text-align: center;
    flex-shrink: 0;
    color: #fff;
}

.rel-pit-active {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    border-radius: 4px;
    padding: 3px 6px;
    font-size: 11px;
    font-weight: 700;
    height: 22px;
    box-sizing: border-box;
    border: 1px solid #00FFDC;
    background: rgba(0, 255, 220, 0.10);
    color: #00FFDC;
    letter-spacing: 0.5px;
    flex-shrink: 0;
    white-space: nowrap;
    min-width: 38px;
}
.rel-pit-active.is-hidden { visibility: hidden; }

.rel-num {
    font-weight: 700;
    font-size: 15px;
    width: 40px;
    text-align: center;
    color: rgba(255, 255, 255, 0.5);
    flex-shrink: 0;
}

.rel-logo {
    width: 26px;
    height: 26px;
    border-radius: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    flex-shrink: 0;
    object-fit: contain;
}

.rel-name {
    /* 170px BASIS name slot ("always tight" + draggable): the panel is
       width:max-content, and per flex intrinsic sizing an item with non-zero
       grow contributes AT MOST its flex base size (and with non-zero shrink
       AT LEAST it) — so the name contributes exactly 170 to the panel's
       natural width no matter how long the text is. Tight width is therefore
       deterministic (enabled columns + 170; untick a column and the panel
       shrinks by exactly that column, names can never jump it), while a
       drag-widened panel (saved min-width floor) pours ALL the extra room
       into the name via grow. Long names fade out via the right-edge mask.
       Same treatment on .st-name. */
    flex: 1 1 170px;
    font-size: 15px;
    font-weight: 500;
    overflow: hidden;
    white-space: nowrap;
    color: #fff;
    mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
}

.rel-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    border-radius: 4px;
    padding: 3px 6px;
    font-size: 11px;
    font-weight: 700;
    flex-shrink: 0;
    box-sizing: border-box;
    height: 24px;
}

.rel-lap-badge {
    width: 38px;
    text-align: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.6);
}

.rel-license {
    width: 56px;
    text-align: center;
    background: var(--lic-bg);
    border: 1px solid var(--lic-color);
    color: var(--lic-color);
}

.rel-pit-badge {
    width: 36px;
    background: rgba(255, 176, 0, 0.18);
    border: 1px solid rgba(255, 176, 0, 0.55);
    color: #ffb000;
    letter-spacing: 0.5px;
}
.rel-pit-badge.is-hidden {
    visibility: hidden;
}

.rel-row.on-pit:not(.is-player) {
    opacity: 0.55;
}

.rel-irating {
    width: 80px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.rel-ir-val { color: rgba(255, 255, 255, 0.7); font-weight: 600; line-height: 1; }
.rel-ir-arrow { width: 8px; height: 8px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; line-height: 0; }
.rel-ir-arrow svg { width: 8px; height: 8px; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; fill: none; display: block; }
.rel-ir-change { font-weight: 600; line-height: 1; }

.rel-gap {
    /* 16px font → ~8px per tabular digit (vs 7px on the 13px Standings columns).
       Base 62 (was 72): right-aligned, so all the reserve shows as empty space
       between the lap columns and Rel. Typical content "+12.3"/"+12.345" is
       37-53px across the decimal range; 62 keeps a consistent ~9px of slack
       instead of the old ~19px hole after Avg.
       margin-left:auto pairs with .rel-name's max-width cap: when the 380px
       floor leaves more free space than the capped name can soak up, the auto
       margin absorbs the residue so Rel stays pinned to the right edge
       (auto margins resolve to 0 during max-content sizing, so this never
       affects the panel's computed width). */
    margin-left: auto;
    width: calc(62px - (3 - var(--gapdec, 3)) * 8px);
    text-align: right;
    font-weight: 700;
    font-size: 16px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

/* === Column header row (Settings.ShowColumnHeaders) =========================
   A dim label row rendered as the FIRST child inside the rows card (.st-flip),
   for both Standings and Relative. It REUSES the data column classes so labels
   stay locked to the columns; this block only restyles the look. Fixed-width
   columns can drop their chrome freely (border-box width is unchanged); the
   AUTO-width energy badge must KEEP its box width (transparent border, not
   removed) or the right-anchored .st-data cluster drifts.
   NOTE: header height is fixed at 22px — the Standings fastest-lap badge offset
   in StandingsOverlay.razor adds this same 22px when ShowColumnHeaders is on, so
   keep the two in sync. */
.st-row.col-head, .rel-row.col-head {
    height: 22px;
    min-height: 0;
    font-variant-numeric: normal;
    pointer-events: none;
}
.col-head .st-pos, .col-head .st-num, .col-head .st-poschg, .col-head .st-name,
.col-head .st-gap, .col-head .st-int, .col-head .st-best, .col-head .st-last, .col-head .st-avg,
.col-head .st-license, .col-head .st-irating, .col-head .st-bat-val, .col-head .st-ir-val, .col-head .st-pit-text,
.col-head .rel-pos, .col-head .rel-num, .col-head .rel-poschg, .col-head .rel-name,
.col-head .rel-lap, .col-head .rel-license, .col-head .rel-irating, .col-head .rel-ir-val, .col-head .rel-gap, .col-head .rel-lap-badge {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--gf-text-muted);
}
.col-head .st-name, .col-head .rel-name { -webkit-mask-image: none; mask-image: none; }
.col-head .st-logo, .col-head .rel-logo,
.col-head .st-flag, .col-head .rel-flag { visibility: hidden; }
/* fixed-width badges: drop chrome (outer width unchanged — border-box fixed) */
.col-head .st-license, .col-head .st-irating,
.col-head .rel-license, .col-head .rel-irating, .col-head .rel-lap-badge {
    background: none; border: none; padding: 0; height: auto;
}
/* relative PIT chip is contextual — reserve its width, hide the text */
.col-head .rel-pit-active { background: transparent; border-color: transparent; color: transparent; }
/* energy badge is AUTO-width — keep the box width, hide only the chrome */
.col-head .st-battery { background: transparent; border-color: transparent; height: auto; }
.col-head .st-battery-icon, .col-head .st-bat-used { visibility: hidden; }

/* Optional Relative columns (default off): pos-change arrow + Best/Last/Avg lap
   times. Sit just before the gap; lap columns are dim so the gap stays the hero. */
.rel-poschg {
    width: 16px;
    text-align: center;
    font-weight: 700;
    font-size: 10px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.rel-lap {
    /* Base 56 (was 50): a real lap is always over the minute, so FormatLapTime
       renders "1:23.45" ≈ 45px at this 12px font — the old 44px box (2 decimals)
       was flush-to-overflowing, bleeding left and eating the inter-column gap
       (uneven spacing vs the other columns). 56 gives every decimal count a
       consistent ~5px of slack like the rest of the row.
       Colour mirrors Standings: Best/Last default white, only Avg dimmed (the
       old all-dim look read washed-out next to the Standings table). */
    width: calc(56px - (3 - var(--lapdec, 3)) * 6px);
    text-align: right;
    font-weight: 600;
    font-size: 12px;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.rel-lap.rel-avg {
    color: var(--gf-text-dim);
}

/* Info bars */
.rel-info-bar {
    display: flex;
    align-items: center;
    justify-content: space-evenly;
    padding: var(--rel-info-pad-y, 8px) 12px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 8px;
    margin-bottom: var(--rel-info-mb, 4px);
    font-size: 14px;
    color: rgba(255, 255, 255, 0.55);
}

.rel-info-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-variant-numeric: tabular-nums;
    color: #fff;
}

.rel-info-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.rel-info-icon svg {
    width: 18px;
    height: 18px;
    stroke: #fff;
    fill: none;
    stroke-width: 1.5;
}

.rel-mat-icon svg {
    fill: #fff;
    stroke: none;
    stroke-width: 0;
}

.rel-bottom-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--rel-foot-pad-y, 8px) 12px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 8px;
    margin-top: var(--rel-foot-mt, 4px);
    font-size: 14px;
    color: #fff;
}

/* ============================================================
   FUEL OVERLAY v2
   ============================================================ */
.fuel-panel-v2 {
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 8px);
    overflow: hidden;
    padding: 4px 0;
    /* Floor sized to the FINISH/PIT strip's worst case (PIT NOW + per-stop add)
       so the matrix 1fr columns don't squash. The predicted cards now stack their
       reference under the number, so they no longer drive the width past this. */
    min-width: 215px;
}

/* ── Status Bar (separate panel) ── */
.fuel-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 14px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 8px);
    margin-bottom: 6px;
    min-width: 215px;
}

.fuel-status-lap {
    display: flex;
    align-items: baseline;
    gap: 6px;
}

.fuel-status-lap b {
    font-size: 16px;
    font-weight: 700;
    color: #fff;
    line-height: 1;
}

.fuel-status-lap span {
    font-size: 15px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.5);
}

.fuel-status-lap em {
    font-style: normal;
    font-size: 15px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.5);
}

.fuel-status-time {
    margin-left: auto;
    font-size: 15px;
    font-weight: 600;
    color: #fff;
}

/* ── Resources ── */
.fuel-resources {
    padding: 10px 8px 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.fuel-res {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.fuel-res-info {
    display: flex;
    align-items: center;
}

.fuel-res-val {
    flex: 1;
    font-size: 16px;
    font-weight: 700;
    color: #fff;
    line-height: 1;
    order: 1;
}

.fuel-res-icon {
    width: 22px;
    height: 22px;
    flex: 0 0 22px;
    color: #fff;
    order: 2;
}

.fuel-res-unit {
    display: none;
}

.fuel-res-laps {
    flex: 1;
    font-size: 14px;
    font-weight: 700;
    color: #fff !important;
    text-align: right;
    order: 3;
}

.fuel-res-laps.c-green,
.fuel-res-laps.c-orange,
.fuel-res-laps.c-red {
    color: #fff !important;
}

.fuel-res-laps small {
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    margin-left: 4px;
    text-transform: none;
}

.fuel-res-bar {
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    position: relative;
}

.fuel-res-bar.fuel-bar-track-fuel {
    background: linear-gradient(90deg, var(--gf-red) 0%, var(--gf-orange) 50%, var(--gf-green) 100%);
}

.fuel-res-bar.fuel-bar-track-energy {
    background: linear-gradient(90deg, #24FFA7 0%, #55CF4A 100%);
}

.fuel-res-bar-mask {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    transform-origin: right center;
    transform: scaleX(var(--mask-x, 0));
    transition: transform 1.2s linear;
    will-change: transform;
    border-radius: 0 5px 5px 0;
}

.fuel-bar-track-fuel {
    background: linear-gradient(90deg, var(--gf-red) 0%, var(--gf-orange) 50%, var(--gf-green) 100%);
}

.fuel-bar-track-energy {
    background: linear-gradient(90deg, #24FFA7 0%, #55CF4A 100%);
}

.fuel-bar-track-fuel .fuel-res-bar-mask {
    background:
        linear-gradient(rgba(255, 60, 34, 0.12), rgba(255, 60, 34, 0.12)),
        #2a2a2a;
}

.fuel-bar-track-energy .fuel-res-bar-mask {
    background:
        linear-gradient(rgba(77, 233, 95, 0.12), rgba(77, 233, 95, 0.12)),
        #2a2a2a;
}

/* ── VE Prediction ── */
.fuel-ve {
    margin: 0 8px;
    padding: 8px 8px;
    display: flex;
    align-items: center;
    gap: 5px;
    background:
        linear-gradient(90deg, rgba(39, 232, 141, 0.22) 0%, rgba(39, 232, 141, 0) 18%),
        rgba(255, 255, 255, 0.02);
    border-radius: 14px;
}

.fuel-ve.fuel-ve-warn {
    background:
        linear-gradient(90deg, rgba(255, 60, 34, 0.25) 0%, rgba(255, 60, 34, 0) 18%),
        rgba(255, 255, 255, 0.02);
}

.fuel-ve.fuel-ve-warn .fuel-ve-icon,
.fuel-ve.fuel-ve-warn .fuel-ve-num { color: var(--gf-red); }

.fuel-ve-icon {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    color: var(--gf-green);
}

.fuel-ve-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

/* P2 — number on the left, comparison reference right-aligned on the same row. */
.fuel-ve-row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 8px;
}

.fuel-ve-lbl {
    font-size: 13px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.85);
    letter-spacing: 0;
    text-transform: none;
    line-height: 1;
}

.fuel-ve-num {
    font-size: 22px;
    font-weight: 700;
    color: var(--gf-green);
    line-height: 1;
}

.fuel-ve-num.over { color: var(--gf-red); }
.fuel-ve-num.under { color: var(--gf-green); }

.fuel-ve-ref {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
    line-height: 1.15;
}

.fuel-ve-ref-lbl {
    font-size: 10px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.4);
    text-transform: none;
    letter-spacing: 0.2px;
    line-height: 1;
}

.fuel-ve-ref-num {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.6);
    line-height: 1.2;
}

/* ── Usage Table ── */
.fuel-usage {
    padding: 16px 8px 10px;
}

.fuel-usage-grid {
    display: grid;
    grid-template-columns: 28px 1fr 1fr 1fr;
    row-gap: 6px;
    column-gap: 8px;
}

.fuel-usage-grid-lbl {
    font-size: 13px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.5);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    text-align: center;
    padding-bottom: 2px;
}

.fuel-usage-grid-icon {
    width: 20px;
    height: 20px;
    color: #fff;
    align-self: center;
}

.fuel-usage-grid-val {
    font-size: 18px;
    font-weight: 700;
    color: #fff;
    text-align: center;
    padding: 2px 0;
    align-self: center;
}

/* ── Pit Card ── */
.fuel-pit {
    margin: 8px 12px 10px;
    padding: 8px 10px;
    background: rgba(255, 255, 255, 0.028);
    border-radius: 4px;
    border: 1px solid var(--gf-border);
    position: relative;
    overflow: hidden;
}

.fuel-pit::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2px;
}

.fuel-pit.warn::before { background: var(--gf-orange); }
.fuel-pit.crit::before { background: var(--gf-red); box-shadow: 0 0 8px rgba(255, 65, 54, 0.3); }

.fuel-pit-top {
    display: flex;
    align-items: center;
    margin-bottom: 7px;
}

.fuel-pit-next {
    display: flex;
    flex-direction: column;
}

.fuel-pit-next-lbl {
    font-size: 7px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.25);
    text-transform: uppercase;
    letter-spacing: 1.2px;
    line-height: 1;
}

.fuel-pit-next-lap {
    font-size: 22px;
    font-weight: 800;
    color: #fff;
    letter-spacing: -0.8px;
    line-height: 1.1;
}

.fuel-pit-next-lap small {
    font-size: 10px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.25);
    letter-spacing: 0;
}

.fuel-pit-badge {
    margin-left: auto;
    padding: 2px 7px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.3px;
    border-radius: 3px;
    line-height: 1.4;
}

.fuel-pit-badge.warn {
    color: var(--gf-orange);
    background: rgba(255, 178, 64, 0.08);
    border: 1px solid rgba(255, 178, 64, 0.12);
}

.fuel-pit-badge.crit {
    color: var(--gf-red);
    background: rgba(255, 65, 54, 0.08);
    border: 1px solid rgba(255, 65, 54, 0.12);
}

.fuel-pit-adds {
    display: flex;
    gap: 8px;
    padding-top: 7px;
    border-top: 1px solid var(--gf-border);
}

.fuel-pit-add {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    background: rgba(255, 255, 255, 0.025);
    border-radius: 3px;
    border: 1px solid rgba(255, 255, 255, 0.04);
}

.fuel-pit-add-icon {
    width: 11px;
    height: 11px;
    flex-shrink: 0;
    color: #fff;
}

.fuel-pit-add-val {
    font-size: 11px;
    font-weight: 700;
    color: var(--gf-text);
    letter-spacing: -0.3px;
}

/* ── Icons (fuel + bolt, CSS mask) ── */
.i-fuel {
    display: inline-block;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M200-192.31v-543.07q0-27.62 18.5-46.12Q237-800 264.62-800h190.76q27.62 0 46.12 18.5Q520-763 520-735.38v240h36.92q26.66 0 45.64 18.98t18.98 45.63v183.08q0 21.61 15.34 36.96 15.35 15.35 36.97 15.35 21.61 0 36.96-15.35 15.34-15.35 15.34-36.96v-272.62q-9 5.77-19 8.43-10 2.65-21 2.65-31.66 0-53.52-21.86-21.86-21.86-21.86-53.53 0-27.38 16.35-48.26 16.34-20.89 43.03-25.74l-83.77-83.76q-5.15-5.16-5.53-12.16-.39-7 5.76-13.15 5.47-5.46 12.2-5.58 6.73-.11 12.65 5.58l124.69 124q11.93 11.92 18.66 27.38 6.73 15.46 6.73 31.69v336.93q0 36.83-25.39 62.26Q710.77-160 674-160q-36.77 0-62.31-25.43t-25.54-62.26v-187.69q0-10.77-6.92-17.7-6.92-6.92-17.69-6.92H520v267.69q0 13.73-9.2 23.02T488-160H231.99q-13.61 0-22.8-9.29-9.19-9.29-9.19-23.02ZM240-540h240v-195.38q0-9.24-7.69-16.93-7.69-7.69-16.93-7.69H264.62q-9.24 0-16.93 7.69-7.69 7.69-7.69 16.93V-540Zm446.15-4.62q17 0 28.5-11.5t11.5-28.5q0-17-11.5-28.5t-28.5-11.5q-17 0-28.5 11.5t-11.5 28.5q0 17 11.5 28.5t28.5 11.5ZM240-200h240v-300H240v300Zm240 0H240h240Z'/%3E%3C/svg%3E") center/contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M200-192.31v-543.07q0-27.62 18.5-46.12Q237-800 264.62-800h190.76q27.62 0 46.12 18.5Q520-763 520-735.38v240h36.92q26.66 0 45.64 18.98t18.98 45.63v183.08q0 21.61 15.34 36.96 15.35 15.35 36.97 15.35 21.61 0 36.96-15.35 15.34-15.35 15.34-36.96v-272.62q-9 5.77-19 8.43-10 2.65-21 2.65-31.66 0-53.52-21.86-21.86-21.86-21.86-53.53 0-27.38 16.35-48.26 16.34-20.89 43.03-25.74l-83.77-83.76q-5.15-5.16-5.53-12.16-.39-7 5.76-13.15 5.47-5.46 12.2-5.58 6.73-.11 12.65 5.58l124.69 124q11.93 11.92 18.66 27.38 6.73 15.46 6.73 31.69v336.93q0 36.83-25.39 62.26Q710.77-160 674-160q-36.77 0-62.31-25.43t-25.54-62.26v-187.69q0-10.77-6.92-17.7-6.92-6.92-17.69-6.92H520v267.69q0 13.73-9.2 23.02T488-160H231.99q-13.61 0-22.8-9.29-9.19-9.29-9.19-23.02ZM240-540h240v-195.38q0-9.24-7.69-16.93-7.69-7.69-16.93-7.69H264.62q-9.24 0-16.93 7.69-7.69 7.69-7.69 16.93V-540Zm446.15-4.62q17 0 28.5-11.5t11.5-28.5q0-17-11.5-28.5t-28.5-11.5q-17 0-28.5 11.5t-11.5 28.5q0 17 11.5 28.5t28.5 11.5ZM240-200h240v-300H240v300Zm240 0H240h240Z'/%3E%3C/svg%3E") center/contain no-repeat;
}

.i-bolt {
    display: inline-block;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='280 -800 400 640'%3E%3Cpath d='m422-232 207-248H469l29-227-185 267h139l-30 208Zm-15.85-168H286.77q-16.31 0-23.58-14.19t2.12-27.27l225.15-326.16q6.16-8.61 15.23-11.42 9.08-2.81 19.16.89 10.07 3.69 14.61 12.15 4.54 8.46 3.31 18.54L514.62-520h143.46q16.77 0 23.81 15.31 7.03 15.31-3.81 28.38L427.54-176.15q-6.39 7.61-15.46 9.69-9.08 2.08-17.93-1.85-8.84-3.92-13.5-11.88-4.65-7.96-3.42-18.04L406.15-400Z'/%3E%3C/svg%3E") center/contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='280 -800 400 640'%3E%3Cpath d='m422-232 207-248H469l29-227-185 267h139l-30 208Zm-15.85-168H286.77q-16.31 0-23.58-14.19t2.12-27.27l225.15-326.16q6.16-8.61 15.23-11.42 9.08-2.81 19.16.89 10.07 3.69 14.61 12.15 4.54 8.46 3.31 18.54L514.62-520h143.46q16.77 0 23.81 15.31 7.03 15.31-3.81 28.38L427.54-176.15q-6.39 7.61-15.46 9.69-9.08 2.08-17.93-1.85-8.84-3.92-13.5-11.88-4.65-7.96-3.42-18.04L406.15-400Z'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ── Utility ── */
@keyframes fuel-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}
.fuel-panel-v2 .blink { animation: fuel-pulse 1.2s ease-in-out infinite; }

.fuel-panel-v2 .c-green { color: var(--gf-green); }
.fuel-panel-v2 .c-orange { color: var(--gf-orange); }
.fuel-panel-v2 .c-red { color: var(--gf-red); }

/* ── Reach matrix ── */
.fc-tbl { padding: 4px 12px 4px; }
.fc-trow { display: grid; grid-template-columns: 58px 1fr 1fr; align-items: center; padding: 2px 4px; font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.fc-trow span:not(.fc-rlabel) { text-align: right; }
.fc-thead { font-size: 9px; font-weight: 700; letter-spacing: 1px; color: var(--gf-text-dim); text-transform: uppercase; padding: 2px 4px; }
.fc-thead .fc-rlabel { text-align: left; }
.fc-rlabel { font-size: 11px; font-weight: 800; letter-spacing: .4px; color: var(--gf-text-dim); text-align: left; }
.fc-trow.hl { background: rgba(255,255,255,.06); border-radius: 6px; }
.fc-trow.hl .fc-rlabel { color: #fff; }
.fc-trow .rate { color: var(--gf-text-dim); }
/* Save ladder — plain extra-info rows (no highlight) under a dim group label. */
.fc-grouplbl { font-size: 8.5px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gf-text-dim); padding: 6px 4px 2px; }
.fc-trow.is-proj .fc-rlabel { color: rgba(255,255,255,.80); }
.fc-trow.is-proj span:last-child { color: #fff; font-weight: 700; }
/* Limit marker — the OTHER budget (fuel/energy) runs out first; small inline glyph before the lap. */
.fc-limit-ico { width: 9px; height: 9px; margin-right: 3px; vertical-align: -1px; opacity: .65; }
/* Fuel-as-time: laps -> mm:ss/h:mm:ss subline. On the resource bar (under the
   laps figure) and the usage-table ENDS column (under the run-dry lap). Always
   shown when a lap time is known. See project_fuel_refuel_redesign. */
.fuel-res-time { display: block; text-align: right; font-size: 11px; font-weight: 700; line-height: 1; color: var(--gf-text-dim); }
/* ENDS time = a tight second line UNDER the run-dry lap (right-aligned). line-height:1
   + no margin so it hugs the lap and the double-line row stays compact. */
.fc-ends-time  { display: block; text-align: right; font-size: 9px; font-weight: 700; line-height: 1; margin-top: 1px; color: var(--gf-text-dim); }
.laps-ok   { color: var(--gf-green);  font-weight: 800; }
.laps-warn { color: var(--gf-orange); font-weight: 800; }
.laps-crit { color: var(--gf-red);    font-weight: 800; }

/* ── FINISH / PIT strip ── */
.fin { display: flex; align-items: center; gap: 10px; margin: 6px 10px 12px; padding: 9px 12px; border-radius: 12px; background: rgba(255,255,255,.04); }
.fin-when { display: flex; flex-direction: column; gap: 3px; }
.fin-when .lbl { font-size: 9.5px; font-weight: 700; letter-spacing: .9px; text-transform: uppercase; color: var(--gf-text-dim); line-height: 1; }
.fin-when .v { font-size: 17px; font-weight: 900; color: #fff; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
.fin-when .v.crit { color: var(--gf-red); }
.fin-when .v small { font-size: 11px; font-weight: 600; color: var(--gf-text-dim); margin-left: 1px; }
.fin-out { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.fin-amt { font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.15; white-space: nowrap; }
.fin-amt small { font-size: 10px; font-weight: 600; color: var(--gf-text-dim); margin-left: 1px; }
.fin-amt.ok { color: var(--gf-green); }
.fin-amt.crit { color: var(--gf-red); }
.fin-stopN { font-size: 14px; font-weight: 800; letter-spacing: .4px; text-transform: uppercase; line-height: 1; color: rgba(255,255,255,.72); }
.fin-stopN.crit { color: var(--gf-red); }

/* ============================================================
   TYRE OVERLAY — v20 Front/Rear stacked sections
   ============================================================ */
.tyre-wrap {
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
    color: var(--gf-text);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.tyre-section-header {
    text-align: center;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    padding: 8px 0 10px;
    border-radius: 8px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    position: relative;
    overflow: hidden;
}

.tyre-section-header::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.00), rgba(255, 255, 255, 0.40), rgba(255, 255, 255, 0.00));
}

.tyre-section-body {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 8px;
    padding: 12px 16px 14px;
}

.tyre-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.tyre-pressure {
    font-size: 14px;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

/* Quiet small-caps unit label after a bare number (psi / % / °C). */
.tyre-unit {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.05em;
    color: rgba(255, 255, 255, 0.45);
    margin-left: 2px;
    text-transform: uppercase;
}

/* The tyre is a vertical capsule seen face-on (2026-06-10 redesign — the
   "G3" studio variant): the heatmap is the rubber's surface, the carcass
   rim + recess come from overlays-depth.css, and ::before paints the
   curvature (shoulders rolling into shade, light on the crown). No zone
   divider lines — the gradient flows uninterrupted. */
.tyre-shape {
    width: 58px;
    height: 92px;
    border-radius: 17px;
    overflow: hidden;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

.tyre-shape::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        /* shoulders rolling away — kept light so the I/O colours stay readable */
        linear-gradient(90deg, rgba(0, 0, 0, 0.38) 0%, rgba(0, 0, 0, 0) 20%, rgba(0, 0, 0, 0) 80%, rgba(0, 0, 0, 0.38) 100%),
        /* crown light / base shade */
        linear-gradient(180deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 28%, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 0.28) 100%);
}

.tyre-zones {
    position: absolute;
    inset: 0;
    display: flex;
    z-index: 2;
}

.tyre-zone-info {
    flex: 1;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 6px;
}

.tyre-zone-label {
    font-size: 9px;
    font-weight: 900;
    color: rgba(255, 255, 255, 0.5);
    text-transform: uppercase;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.tyre-core {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3;
    pointer-events: none;
}

.tyre-core-val {
    /* 3-digit core temps (e.g. 104°) fit the 58px capsule at this size —
       studio-verified; don't enlarge without re-checking. */
    font-size: 22px;
    font-weight: 900;
    color: #fff;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85), 0 0 12px rgba(0, 0, 0, 0.5);
}

.tyre-wear {
    font-size: 14px;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

.brake-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
}

.brake-disc-svg {
    /* brake2.svg is 42×40 artwork; size the box to it (the old 48×132 box
       letterboxed ~43px of empty space above/below the disc, stranding the
       temp far below the image). */
    width: 44px;
    height: 42px;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}

.brake-temp {
    font-size: 14px;
    font-weight: 800;
    text-align: center;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
    /* Reserve worst-case width (LMU brake temps reach 4 digits, e.g. 1200°C + the
       °C unit label — studio-verified to fit 56px). Without this the brake column
       grows as the temp gains/loses a digit and the centered panel reflows and
       jumps while driving. tabular-nums via .tyre-wrap. */
    min-width: 56px;
}

.brake-temp-hot {
    color: var(--gf-red);
}

/* Brake pad usable life (ACC only — PadLife mm mapped to 0-100%). Sits
   above the disc icon; same reserved width as .brake-temp so the column
   never reflows when the value gains/loses a digit. */
.brake-pad {
    font-size: 13px;
    font-weight: 700;
    text-align: center;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
    color: rgba(255, 255, 255, 0.82);
    min-width: 56px;
}

.brake-pad-low {
    color: var(--gf-orange);
}

/* ============================================================
   PEDALS / INPUTS OVERLAY — v4/v5
   ============================================================ */
.inp-wrap {
    overflow: hidden;
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
    color: var(--gf-text);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 8px;
}

.inp-delta-tab {
    display: flex;
    justify-content: flex-end;
    position: relative;
}

.inp-delta-tab-shape {
    position: relative;
    width: 86px;
    height: 30px;
}

.inp-delta-tab-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 86px;
    height: 30px;
    overflow: visible;
}

.inp-delta-val {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.inp-rev-lights {
    display: flex;
    gap: 4px;
    padding: 11px 13px 0;
    justify-content: center;
}

.inp-rev-dot {
    flex: 1;
    height: 6px;
    border-radius: 3px;
    transition: background 0.05s, box-shadow 0.05s;
}

/* Lee's rev-flash atom — paired with the box-shadow transition above. */
.inp-rev-flash {
    box-shadow: 0 0 8px 1px rgba(255, 60, 34, 0.25);
}

.inp-main {
    display: flex;
    align-items: center;
    padding: 11px 13px 12px;
    gap: 15px;
}

.inp-traces {
    flex: 1;
    /* Floor so the user can't shrink the panel narrow enough to make
       the trace graph unreadable. To hide entirely, toggle ShowTraceGraph
       in settings instead. */
    min-width: 200px;
}

.inp-trace-wrap {
    background: rgba(255, 255, 255, 0.02);
    border-radius: 6px;
    height: 70px;
    position: relative;
}

.inp-trace-wrap canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
}

.inp-pedals {
    display: flex;
    gap: 9px;
    align-items: center;
    justify-content: center;
}

.inp-pedal-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

.inp-pedal-bar {
    width: 24px;
    height: 70px;
    border-radius: 4px;
    position: relative;
}

.inp-pedal-fill {
    position: absolute;
    left: 0;
    bottom: 0;
    right: 0;
    border-radius: 4px;
    transition: height 50ms linear;
}

.inp-pedal-tick {
    /* Reference-lap marker INSIDE the .ei-bar pedal bars used by the Pedals
       overlay. JS (_tickPctStr in pedalsGraph.js) scales the bottom% so the
       whole 5px tick sits flush with the bar's top/bottom edge at 100%/0%
       — no overflow clipping needed. Bold + strong glow + dark halo so it
       reads over a fully-filled green/red bar. */
    position: absolute;
    left: 0;
    right: 0;
    height: 5px;
    background: #fff;
    border-radius: 5px;
    box-shadow:
      0 0 8px rgba(255, 255, 255, 0.95),
      0 0 2px rgba(255, 255, 255, 1),
      0 0 0 1px rgba(0, 0, 0, 0.55);
    z-index: 5;
    pointer-events: none;
    transition: bottom 150ms ease-out;
}

.inp-throttle-bg { background: rgba(77, 233, 95, 0.12); }
.inp-throttle-bg.maxed { box-shadow: 0 -4px 12px rgba(0, 255, 106, 0.6); }
.inp-throttle-fill { background: linear-gradient(to top, var(--gf-dmg-ok), var(--gf-dmg-ok-2)); }
.inp-brake-bg { background: rgba(255, 60, 34, 0.12); }
.inp-brake-bg.maxed { box-shadow: 0 -4px 12px rgba(255, 0, 81, 0.6); }
.inp-brake-fill { background: linear-gradient(to top, var(--gf-dmg-crit), var(--gf-red)); }
.inp-clutch-bg { background: rgba(51, 218, 236, 0.12); }
.inp-clutch-bg.maxed { box-shadow: 0 -4px 12px rgba(57, 145, 245, 0.6); }
.inp-clutch-fill { background: linear-gradient(to top, #3991F5, #33DAEC); }

.inp-data {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex-shrink: 0;
}

.inp-data-row {
    display: flex;
    align-items: flex-start;
    gap: 6px;
}

.inp-speed-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.inp-speed {
    font-size: 18px;
    font-weight: 800;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
    width: 3ch;
    text-align: center;
}

.inp-speed-unit {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.6);
    font-weight: 600;
    line-height: 1.2;
}

.inp-gear {
    font-size: 38px;
    font-weight: 900;
    line-height: 0.85;
    color: #fff;
    min-width: 1.2ch;
    text-align: center;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.inp-speed-inline {
    display: flex;
    align-items: baseline;
    gap: 3px;
}

.inp-speed-inline .inp-speed {
    font-size: 22px;
    width: 3ch;
    text-align: right;
}

.inp-gear-group {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

.inp-gear-group .inp-gear {
    font-size: 22px;
    line-height: 1;
    min-width: 1.2ch;
    text-align: center;
}

.inp-ref-row {
    margin-top: -2px;
}

.inp-ref-row .inp-speed-inline .inp-speed {
    font-size: 22px;
    color: rgba(255, 255, 255, 0.45);
}

.inp-ref-row .inp-speed-unit {
    color: rgba(255, 255, 255, 0.3);
}

.inp-ref-row .inp-gear-group .inp-gear {
    font-size: 22px;
    color: rgba(255, 255, 255, 0.45);
}

.inp-tacho {
    width: 70px;
    height: 70px;
    flex-shrink: 0;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

.inp-ff-bar-bg {
    height: 6px;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 3px;
    overflow: hidden;
}

.inp-ff-bar-fill {
    height: 100%;
    border-radius: 3px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.1));
}

/* ============================================================
   DISCONNECTED STATE
   ============================================================ */
.not-connected {
    padding: 16px 20px;
    color: var(--gf-text-muted);
    font-size: 12px;
    font-family: var(--gf-font-label);
    text-align: center;
    font-weight: 500;
    letter-spacing: 0.3px;
}

/* ============================================================
   UTILITIES
   ============================================================ */
.flex-1 { flex: 1; }
.mono {
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   POSITION COMPARISON OVERLAY
   ============================================================ */
.pos-bar {
    width: 100%;
    min-width: 280px;
    padding: 0;
    font-family: var(--gf-font-data);
}

.pos-track {
    position: relative;
    height: 28px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 14px;
    /* Inline-size container so the marker / centre tick / zone lines below
       can scale with the track's width via cqw units. Without this they're
       fixed 2-16px and look tiny when the user resizes the panel wider,
       leaving the accuracy feedback feeling lost in a stretched bar. */
    container-type: inline-size;
}

.pos-zone-left,
.pos-zone-right {
    position: absolute;
    top: 0;
    bottom: 0;
    /* Width scales with track width (0.6% of container, clamped 2-5px) so
       the zone "fence" lines grow with the panel instead of staying as
       hairline 2px lines in a wide track. */
    width: clamp(2px, 0.6cqw, 5px);
    background: rgba(255, 255, 255, 0.2);
    border-radius: 1px;
}

.pos-zone-left {
    left: 45%;
}

.pos-zone-right {
    left: 55%;
}

.pos-center-tick {
    position: absolute;
    left: 50%;
    top: 15%;
    bottom: 15%;
    width: clamp(2px, 0.6cqw, 5px);
    /* translateX centres the tick around the 50% mark regardless of width;
       replaces the old `margin-left: -1px` trick which assumed a fixed 2px. */
    transform: translateX(-50%);
    background: rgba(255, 255, 255, 0.45);
    border-radius: 1px;
}

.pos-marker {
    position: absolute;
    top: 10%;
    bottom: 10%;
    left: 50%;            /* centred default until the JS animator takes over */
    /* Width scales with track width (3.5% of container, clamped 12-28px).
       brakeBarAnim sets style.left and never touches transform, so the
       translateX centring below doesn't fight the rAF animator. */
    width: clamp(12px, 3.5cqw, 28px);
    transform: translateX(-50%);
    border-radius: 6px;
    /* NO `left` transition: the marker's left is driven per-frame by
       brakeBarAnim's rAF loop (60fps), so a CSS transition would fight it.
       The remaining transitions are for the colour-zone / size changes only. */
    transition: background 300ms ease, box-shadow 300ms ease, width 200ms ease;
}

.pos-marker--green {
    border-radius: 2px;
    background: linear-gradient(0deg, var(--gf-dmg-ok-2) 0%, var(--gf-dmg-ok) 100%);
    box-shadow: 0 -1px 10px 0 rgba(255, 255, 255, 0.25) inset, 0 0 10px 0 rgba(39, 232, 141, 0.80);
}

.pos-marker--yellow {
    border-radius: 2px;
    background: linear-gradient(0deg, var(--gf-posmid-1) 0%, var(--gf-posmid-2) 100%);
    box-shadow: 0 0 10px 0 rgba(255, 215, 0, 0.6);
}

.pos-marker--red {
    border-radius: 2px;
    background: linear-gradient(0deg, var(--gf-red) 0%, var(--gf-dmg-crit) 100%);
    box-shadow: 0 0 10px 0 rgba(255, 60, 34, 0.6);
}

.pos-marker--in-zone {
    /* In-zone marker is ~33% wider than default; same proportional scaling
       (4.7cqw vs 3.5cqw with the same 12→16 / 28→38 ratio at the bounds). */
    width: clamp(16px, 4.7cqw, 38px);
}

.pos-track--in-zone .pos-zone-left,
.pos-track--in-zone .pos-zone-right {
    background: rgba(77, 233, 95, 0.4);
    box-shadow: 0 0 6px rgba(77, 233, 95, 0.3);
}

.pos-no-ref {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.25);
}

/* === Delta Overlay === */

.delta-overlay {
    width: 100%;
    min-width: 240px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.delta-top {
    border-radius: var(--gf-radius);
    overflow: hidden;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
}

.delta-bottom {
    border-radius: var(--gf-radius);
    overflow: hidden;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
}

.delta-header {
    position: relative;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 3px 10px;
    border-radius: var(--gf-radius) var(--gf-radius) 0 0;
    overflow: hidden;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.delta-header > * { z-index: 1; }

.delta-header-grad {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 50px;
    pointer-events: none;
    z-index: 0;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.15), transparent);
}

.delta-header .title {
    font-size: 12px;
    font-weight: 900;
    letter-spacing: 0.5px;
}

.delta-header .vs-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--gf-text-dim);
}

.delta-sectors { padding: 0; }

.delta-row {
    display: flex;
    align-items: center;
    padding: 7px 14px;
    position: relative;
    overflow: hidden;
    transition: opacity 0.3s;
}

.delta-row.dimmed { opacity: 0.25; }
.delta-row.current { background: rgba(255, 255, 255, 0.03); }

.delta-row-grad {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 42px;
    pointer-events: none;
    z-index: 0;
}

.delta-row-fill {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    background: rgba(255, 255, 255, 0.06);
    border-right: 1px solid rgba(255, 255, 255, 0.15);
    pointer-events: none;
    z-index: 0;
    transition: width 0.3s ease-out;
}

.delta-sector-label,
.delta-sector-time,
.delta-sector-delta { position: relative; z-index: 1; }

.delta-sector-label {
    font-size: 12px;
    font-weight: 700;
    width: 28px;
    flex-shrink: 0;
}

.delta-sector-time {
    flex: 1;
    text-align: center;
    font-size: 13px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: rgba(255, 255, 255, 0.8);
}

.delta-sector-delta {
    font-size: 13px;
    font-weight: 600;
    width: 68px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.delta-green { color: var(--gf-green); }
.delta-purple { color: var(--gf-purple); }
.delta-red { color: var(--gf-red); }
.delta-neutral { color: var(--gf-text-muted); }

.delta-summary {
    display: flex;
    padding: 7px 14px 9px;
    gap: 4px;
}

.delta-summary-col {
    flex: 1;
    text-align: center;
}

.delta-summary-label {
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--gf-text-muted);
    margin-bottom: 3px;
}

.delta-summary-time {
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: rgba(255, 255, 255, 0.85);
    margin-bottom: 2px;
}

.delta-summary-delta {
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   Comparison status bar
   ============================================================ */

.comparison-status-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    font-size: 11px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.5);
    background: rgba(255, 255, 255, 0.04);
    border-radius: 4px;
    margin-bottom: 4px;
}

.comparison-status-bar.comparison-warning {
    color: var(--gf-orange);
    background: rgba(255, 184, 77, 0.1);
    border: 1px solid rgba(255, 184, 77, 0.2);
}

.comparison-status-icon {
    font-size: 13px;
}

/* ============================================================
   TRACE COMPARISON
   ============================================================ */
/* Panels containing a trace canvas need to be flex columns so the wrap can
   claim remaining space via flex:1. Percentage heights (height:100%) fail
   because the panel only has min-height, not an explicit height. */
.overlay-panel:has(> .trace-wrap),
.overlay-panel:has(> .speed-trace-wrap) {
    display: flex;
    flex-direction: column;
}

.trace-wrap {
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: var(--gf-radius);
    overflow: hidden;
    width: 100%;
    flex: 1 1 auto;
    min-height: 40px;
    position: relative;
}

#traceCanvas {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* ============================================================
   SPEED TRACE
   ============================================================ */
.speed-trace-wrap {
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: var(--gf-radius);
    overflow: hidden;
    width: 100%;
    flex: 1 1 auto;
    min-height: 40px;
    position: relative;
}

#speedTraceCanvas {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* === Track Map ============================================================ */
.track-map-wrap {
    width: 100%;
    height: 100%;
    min-width: 200px;
    min-height: 200px;
    position: relative;
}
.track-map-wrap.track-map-bar {
    width: 100%;
    height: 60px;
    min-height: 0;
    min-width: 0;
}
.track-map-wrap canvas,
#trackMapCanvas {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* === Radar ================================================================ */
.radar-wrap {
    width: 100%;
    height: 100%;
    opacity: 0;
    transition: opacity 220ms ease-in-out;
    min-width: 150px;
    min-height: 150px;
    position: relative;
}
.radar-wrap.radar-active {
    opacity: 1;
}
.radar-wrap canvas {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* === Mini Map ============================================================= */
.mini-map-wrap {
    width: 100%;
    height: 100%;
    min-width: 160px;
    min-height: 160px;
    position: relative;
    border-radius: 1000px;
    border: 1px solid rgba(255, 255, 255, 0.10);
    background: radial-gradient(50% 50% at 50% 50%, rgba(255, 255, 255, 0.00) 0%, rgba(0, 0, 0, 0.20) 100%);
    overflow: hidden;
}
.mini-map-wrap canvas,
#miniMapCanvas {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* ────────────────────────────────────────────────────────────── */
/*  WEATHER OVERLAY                                                */
/* ────────────────────────────────────────────────────────────── */
/* ============================================================
   WEATHER OVERLAY
   ============================================================
   Token-based design. Every section is a flex row of `.weather-cell`
   atoms (icon + value + unit). Sections are split by 1px dividers and
   share the same horizontal padding so visual rhythm is consistent.

   Three section variants:
     .weather-section            — horizontal cells (Ambient default)
     .weather-section--wind      — dial + stacked-cell
     .weather-section--stack     — vertical cell stack (Conditions)
*/
.weather-panel,
.weather-panel * { box-sizing: border-box; }

.weather-panel {
    /* Colour tokens */
    --w-border: rgba(255, 255, 255, 0.08);
    --w-text:   rgba(255, 255, 255, 1);
    --w-muted:  rgba(255, 255, 255, 0.5);

    /* Spacing tokens */
    --w-pad-x:    14px;
    --w-pad-y:    10px;
    --w-cell-gap: 10px;   /* gap between icon and text inside one cell */

    /* Type + icon tokens */
    --w-icon:    16px;
    --w-text-lg: 16px;    /* primary value (numbers + short labels) */
    --w-text-sm: 10px;    /* unit / secondary label */

    font-family: 'Satoshi', sans-serif;
    font-variant-numeric: tabular-nums;
    color: var(--w-text);

    background: var(--gf-bg);
    border: 1px solid var(--w-border);
    border-radius: var(--border-radius, 10px);
    backdrop-filter: blur(calc(8px * var(--gf-bdf-k, 1)));
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

/* --- Header -------------------------------------------------- */
/* Mirrors the .delta-header pattern: icon + title on the left,
   muted secondary label on the right, thin bottom border. */
.weather-panel .weather-header {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Match the body's horizontal padding (--w-pad-x) so the header-sub
       (track grip / wet state) right-aligns with the body's track-temp cell
       directly below it, instead of sitting 2px further out. */
    padding: 8px var(--w-pad-x);
    border-bottom: 1px solid var(--w-border);
    flex-shrink: 0;
}
.weather-panel .weather-header-icon {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
}
.weather-panel .weather-header-title {
    font-size: 12px;
    font-weight: 900;
    letter-spacing: 0.5px;
    color: var(--w-text);
    white-space: nowrap;
}
.weather-panel .weather-header-sub {
    margin-left: auto;
    font-size: 11px;
    font-weight: 500;
    color: var(--w-muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.weather-panel .weather-header-sub-icon {
    width: 14px;
    height: 14px;
    opacity: 0.85;
    flex-shrink: 0;
}
.weather-panel .weather-header-sub-pct {
    margin-left: 2px;
}

/* --- Body ---------------------------------------------------- */
.weather-panel .weather-body {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: var(--w-pad-x);
    padding: var(--w-pad-y) var(--w-pad-x);
    min-height: 0;
}
.weather-panel .weather-ambient {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    column-gap: 20px;
    row-gap: 10px;
}
.weather-panel .weather-wind {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-left: var(--w-pad-x);
    border-left: 1px solid var(--w-border);
    flex-shrink: 0;
}
.weather-panel .weather-wind-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    line-height: 1;
    min-width: 58px;
}
.weather-panel .weather-wind-dir {
    font-size: var(--w-text-sm);
    font-weight: 700;
    color: var(--w-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    line-height: 1;
}

/* --- Cell atom ----------------------------------------------- */
.weather-panel .weather-cell {
    display: flex;
    align-items: center;
    gap: var(--w-cell-gap);
    min-width: 0;
    line-height: 1;
}

.weather-panel .weather-v {
    font-size: var(--w-text-lg);
    font-weight: 800;
    letter-spacing: -0.3px;
    line-height: 1;
    color: var(--w-text);
    white-space: nowrap;
}
.weather-panel .weather-unit {
    font-size: var(--w-text-sm);
    font-weight: 600;
    color: var(--w-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-left: 4px;
}

/* --- Icons --------------------------------------------------- */
.weather-panel .weather-ico {
    display: inline-block;
    width: var(--w-icon);
    height: var(--w-icon);
    color: var(--w-muted);
    flex-shrink: 0;
    background: currentColor;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}
.weather-panel .i-thermo { -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><path d='M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0Z'/></svg>"); mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><path d='M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0Z'/></svg>"); }
.weather-panel .i-lines  { -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><path d='M3 6h18M3 12h18M3 18h18'/></svg>"); mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><path d='M3 6h18M3 12h18M3 18h18'/></svg>"); }
.weather-panel .i-drop   { -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'><path d='M12 2s7 8 7 13a7 7 0 1 1-14 0c0-5 7-13 7-13Z'/></svg>"); mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'><path d='M12 2s7 8 7 13a7 7 0 1 1-14 0c0-5 7-13 7-13Z'/></svg>"); }
.weather-panel .i-wind   { -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2'/></svg>"); mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2'/></svg>"); }

/* --- Wind dial ---------------------------------------------- */
.weather-panel .weather-dial {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.35);
    position: relative;
    flex-shrink: 0;
}
.weather-panel .weather-dial::before {
    content: "";
    position: absolute;
    top: -3px;
    left: 50%;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-bottom: 6px solid #fff;
    transform: translateX(-50%);
}
.weather-panel .weather-dial::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 3px;
    height: 3px;
    background: rgba(255, 255, 255, 0.6);
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
.weather-panel .weather-arrow-wrap {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* No transform transition: the arrow snaps to the EXACT car-relative wind
       direction each update (no smoothing lag, and no long-way spin at the
       0/360 seam — a hard snap has no animation to take the wrong path). */
}
.weather-panel .weather-arrow-wrap svg {
    width: 28px;
    height: 28px;
}

/* --- Vertical layout (space-optimised, instrument cluster) --- */
/* Opt-in via `.weather-panel.vertical`; Horizontal stays untouched. A narrow
   stacked column: the sky title keeps the top, the track/grip line becomes a
   pill, ambient stats + wind become inset sub-panels, and the air/track temps
   are enlarged as the hero reading with humidity muted. */
.weather-panel.vertical {
    --w-card-bg:     rgba(255, 255, 255, 0.035);
    --w-card-radius: 9px;
    --w-temp-lg:     19px;   /* hero air/track temp size */
}
.weather-panel.vertical .weather-body {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 10px;
}

/* Header: sky icon + title on row 1; track state + grip as a pill on row 2. */
.weather-panel.vertical .weather-header {
    flex-wrap: wrap;
    gap: 8px 10px;
}
.weather-panel.vertical .weather-header-sub {
    margin-left: 0;
    flex-basis: 100%;
    width: fit-content;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--w-border);
    border-radius: 999px;
    padding: 3px 9px;
}

/* Ambient = inset sub-panel; each row pushes its value to the right edge. */
.weather-panel.vertical .weather-ambient {
    grid-template-columns: 1fr;
    row-gap: 0;
    background: var(--w-card-bg);
    border: 1px solid var(--w-border);
    border-radius: var(--w-card-radius);
    padding: 2px 11px;
}
.weather-panel.vertical .weather-ambient .weather-cell {
    justify-content: space-between;
    width: 100%;
    padding: 8px 0;
    border-bottom: 1px solid var(--w-border);
}
.weather-panel.vertical .weather-ambient .weather-cell:last-child {
    border-bottom: none;
}
/* Hero readings — air, track AND humidity all share the same size/weight/colour
   (humidity is no longer muted/smaller). */
.weather-panel.vertical .weather-ambient .weather-cell:nth-child(1) .weather-v,
.weather-panel.vertical .weather-ambient .weather-cell:nth-child(2) .weather-v,
.weather-panel.vertical .weather-ambient .weather-cell:nth-child(3) .weather-v {
    font-size: var(--w-temp-lg);
}

/* Wind = inset sub-panel; dial centered with speed/dir below it. */
.weather-panel.vertical .weather-wind {
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 11px;
    background: var(--w-card-bg);
    border: 1px solid var(--w-border);
    border-radius: var(--w-card-radius);
}
.weather-panel.vertical .weather-wind-text {
    align-items: center;
    text-align: center;
    min-width: 0;
}

/* ============================================================
   BRAKE INDICATOR
   ============================================================ */

.brake-indicator-idle {
    padding: 8px 14px;
    border-radius: var(--border-radius, 6px);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(10px * var(--gf-bdf-k, 1)));
    color: rgba(255,255,255,0.55);
    font-family: 'Satoshi', 'Inter', system-ui, sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-align: center;
}

/* ----- Bar mode ----- */
.brake-bar-panel {
    width: 280px;
    padding: 10px 14px 12px;
    border-radius: var(--border-radius, 6px);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(10px * var(--gf-bdf-k, 1)));
    font-family: 'Satoshi', 'Inter', system-ui, sans-serif;
    color: #fff;
    box-sizing: border-box;
}
.brake-bar-track {
    position: relative;
    height: 16px;
    border-radius: 8px;
    background: rgba(255, 60, 34, 0.08);
    overflow: hidden;
    /* 220ms eases the Waiting→Approaching→Braking colour + glow flip into a
       perceptually smooth crossfade instead of an 80ms snap. The bar FILL
       itself stays JS-driven (rAF) — only the panel-level colour/shadow
       state transitions use CSS. */
    transition: background 220ms ease, box-shadow 220ms ease;
}
.brake-bar-fill {
    position: absolute;
    top: 0; bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(90deg, #8a1a0a, #ff3c22);
    /* scaleX is GPU-composited. Easing is driven by brakeBarAnim.js rAF loop,
       not CSS transitions — CSS transitions stutter under Blazor's bursty
       render cadence. NO transition property here on purpose. */
    transform-origin: left center;
    transform: scaleX(0);
    will-change: transform;
}
.brake-bar-tick {
    position: absolute;
    top: 0; bottom: 0;
    width: 1px;
    background: rgba(255,255,255,0.3);
    pointer-events: none;
}

.brake-bar-footer {
    position: relative;
    height: 18px;
    margin-top: 10px;
}
.brake-bar-labels,
.brake-bar-brake-text {
    position: absolute;
    inset: 0;
    transition: opacity 80ms linear;
}
.brake-bar-label {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    font-size: 11px;
    font-weight: 600;
    color: rgba(255,255,255,0.75);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.4px;
    white-space: nowrap;
}
.brake-bar-brake-text {
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    letter-spacing: 2.5px;
    font-size: 13px;
    color: #fff;
    text-shadow: 0 1px 3px rgba(0,0,0,0.7);
    opacity: 0;
    pointer-events: none;
}

.brake-bar-panel.state-braking .brake-bar-track,
.brake-bar-panel.state-predicted-braking .brake-bar-track {
    background: linear-gradient(90deg, rgba(255,60,34,0.45), #ff3c22 25%, #ff3c22);
    box-shadow: 0 0 20px 3px rgba(255,60,34,0.6);
}
.brake-bar-panel.state-braking .brake-bar-fill,
.brake-bar-panel.state-predicted-braking .brake-bar-fill { display: none; }
.brake-bar-panel.state-braking .brake-bar-labels,
.brake-bar-panel.state-predicted-braking .brake-bar-labels { opacity: 0; }
.brake-bar-panel.state-braking .brake-bar-brake-text,
.brake-bar-panel.state-predicted-braking .brake-bar-brake-text { opacity: 1; }

/* ----- Countdown mode ----- */
.brake-cd-panel {
    position: relative;
    width: 220px;
    height: 52px;
    border-radius: var(--border-radius, 6px);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(10px * var(--gf-bdf-k, 1)));
    border: 1.5px solid rgba(255,255,255,0.08);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'Satoshi', 'Inter', system-ui, sans-serif;
    font-weight: 800;
    color: #fff;
    box-sizing: border-box;
    /* Ring panel matches the bar's smoother 220ms colour/glow cross-fade
       between Waiting/Approaching/Braking. The ring fill itself is
       JS-driven via the --p CSS var. */
    transition: background 220ms ease, box-shadow 220ms ease, border-color 220ms ease;
}

/* Register --p as an animatable number so the conic ring interpolates between
   ticks instead of snapping. Without this, CSS custom properties step instantly. */
@property --p {
    syntax: '<number>';
    inherits: false;
    initial-value: 0;
}

.brake-cd-progress {
    position: absolute;
    inset: -1.5px;
    border-radius: 6px;
    pointer-events: none;
    background:
        conic-gradient(from 0deg at 50% 50%,
            #ff3c22 calc(var(--p, 0) * 1%),
            rgba(255,60,34,0) calc(var(--p, 0) * 1%));
    -webkit-mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    padding: 1.5px;
    filter: drop-shadow(0 0 4px rgba(255,60,34,0.5));
    /* --p matches the bar fill's 50ms so both modes feel equally smooth */
    /* --p easing is driven by brakeBarAnim.js rAF loop. Only opacity keeps
       a CSS transition because opacity changes are state toggles, not ticks. */
    transition: opacity 120ms linear;
}

.brake-cd-digit {
    position: relative;
    z-index: 2;
    font-size: 28px;
    letter-spacing: 1px;
    transition: font-size 80ms, letter-spacing 80ms;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
}

.brake-cd-panel.state-waiting {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    backdrop-filter: none;
}
.brake-cd-panel.state-waiting .brake-cd-progress { opacity: 0; }
.brake-cd-panel.state-waiting .brake-cd-digit {
    opacity: 0;
}

.brake-cd-panel.state-braking,
.brake-cd-panel.state-predicted-braking {
    background: linear-gradient(180deg, #ff3c22, #b31a0a);
    border-color: #ff3c22;
    box-shadow:
        0 0 24px 2px rgba(255,60,34,0.7),
        inset 0 0 20px rgba(255,255,255,0.08);
}
.brake-cd-panel.state-braking .brake-cd-progress,
.brake-cd-panel.state-predicted-braking .brake-cd-progress { opacity: 0; }
.brake-cd-panel.state-braking .brake-cd-digit,
.brake-cd-panel.state-predicted-braking .brake-cd-digit {
    font-size: 22px;
    letter-spacing: 3px;
    text-shadow: 0 1px 3px rgba(0,0,0,0.5);
}

/* ============================================================
   CORNER ANALYSIS
   ============================================================ */

.corner-wrap {
    width: 340px;
    color: #e8e8e8;
    font-family: -apple-system, system-ui, sans-serif;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Mirrors .tyre-section-header — centered title with rounded dark
   background, blur, and a faint highlight strip along the bottom edge. */
.corner-section-header {
    text-align: center;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    padding: 8px 0 10px;
    border-radius: 8px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    position: relative;
    overflow: hidden;
}
.corner-section-header::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.00), rgba(255, 255, 255, 0.40), rgba(255, 255, 255, 0.00));
}

.corner-body {
    position: relative;
    box-sizing: border-box;
    height: 180px;
    padding: 14px 16px 12px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 6px);
    display: flex;
    flex-direction: column;
}

.corner-analysis-status {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: #9aa0a8;
    font-size: 13px;
}

.hero-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    position: relative;
    z-index: 2;
}

.hero-label {
    font-size: 20px;
    font-weight: 700;
    text-shadow: 0 2px 8px rgba(0,0,0,0.85);
}

.hero-deltas {
    text-align: right;
    text-shadow: 0 2px 8px rgba(0,0,0,0.85);
}

.hero-deltas .big {
    font-size: 26px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.hero-deltas .sm {
    font-size: 11px;
    color: #c6ccd4;
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
}

.unit { font-size: 12px; color: #9aa0a8; font-weight: 500; }

.corner-body .hero-deltas .big { color: #ffffff; }
.corner-body.delta-neg .hero-deltas .big { color: var(--gf-corner-good); }
.corner-body.delta-pos .hero-deltas .big { color: var(--gf-corner-bad); }

.hero-svg {
    display: block;
    width: 100%;
    flex: 1;
    min-height: 0;
    margin-top: 10px;
    position: relative;
    z-index: 2;
}

.line-ref {
    stroke: #ffffff;
    /* Bolder dotted reference line — thicker stroke + fuller dots + full opacity
       so it reads clearly against the live trace (was 2px / "1 3" / 0.85). */
    stroke-width: 3;
    fill: none;
    /* Short-dot blips (Race Engineer segment-view ShortDot lineage), scaled up
       with the heavier stroke so the dots stay round, not pinpricks. */
    stroke-dasharray: 2 4;
    stroke-linecap: round;
    opacity: 1;
    vector-effect: non-scaling-stroke;
}

.line-live {
    stroke: #ffffff;
    stroke-width: 2;
    fill: none;
    vector-effect: non-scaling-stroke;
}

.corner-body.delta-neg .line-live { stroke: var(--gf-corner-good); }
.corner-body.delta-pos .line-live { stroke: var(--gf-corner-bad); }

/* ============================================================
   DELTA BAR
   A thin horizontal bar showing current delta with a tabular-
   nums pill. Two fill elements (left/right) are driven by
   brakeBarAnim.js rAF interpolator. Sizing is em-based so the
   entire overlay responds to the global font-size slider.
   ============================================================ */

.delta-bar-panel {
    font-family: var(--font-family);
    font-size: var(--font-size);
    color: rgba(255, 255, 255, 0.55);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.55em;
    width: 100%;
}

.delta-bar-idle {
    font-family: var(--font-family);
    font-size: var(--font-size);
    color: rgba(255, 255, 255, 0.6);
    padding: 0.5em 1em;
    background: var(--gf-bg);
    border-radius: var(--border-radius, 6px);
    backdrop-filter: blur(calc(10px * var(--gf-bdf-k, 1)));
}

.delta-bar-track {
    position: relative;
    width: 100%;
    height: 1.4em;
    background: var(--gf-bg);
    border-radius: 0.7em;
    overflow: hidden;
}

.delta-bar-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    transform: scaleX(0);
    will-change: transform;
    transition: background-color 400ms ease;
}

.delta-bar-fill-left {
    right: 50%;
    border-radius: 0.7em 0 0 0.7em;
    transform-origin: right center;
}

.delta-bar-fill-right {
    left: 50%;
    border-radius: 0 0.7em 0.7em 0;
    transform-origin: left center;
}

.delta-bar-tick {
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 1px;
    background: rgba(255, 255, 255, 0.45);
    transform: translateX(-0.5px);
}

.delta-bar-pill {
    background: rgba(0, 0, 0, 0.75);
    border-radius: 0.55em;
    padding: 0.35em 0.85em;
    font-weight: 700;
    font-size: 1.17em; /* ~14px when root font-size is 12px (default token) */
    font-variant-numeric: tabular-nums;
    text-align: center;
    min-width: 4.8em;
    box-sizing: border-box;
    color: #FFFFFF;
    transition: color 400ms ease;
}

.delta-bar-ahead   .delta-bar-pill { color: var(--gf-deltabar-ahead); }
.delta-bar-behind  .delta-bar-pill { color: var(--gf-red); }
.delta-bar-neutral .delta-bar-pill { color: #FFFFFF; }
.delta-bar-invalid .delta-bar-pill { color: rgba(255, 255, 255, 0.55); }

/* Fill colour is driven by state (gain/loss/equal), not by which side fills.
   Only one fill is visible at a time, so whichever is active takes the state colour. */
.delta-bar-ahead   .delta-bar-fill { background: linear-gradient(270deg, var(--gf-dmg-ok-2) 0%, var(--gf-dmg-ok) 100%); }
.delta-bar-behind  .delta-bar-fill { background: linear-gradient(270deg, var(--gf-red) 0%, var(--gf-dmg-crit) 100%); }
.delta-bar-neutral .delta-bar-fill { background: #FFFFFF; }

/* === Weather Forecast Overlay === */
.forecast-panel {
    background: var(--gf-bg);
    border-radius: var(--gf-radius);
    padding: 10px 14px;
    font-family: var(--gf-font-data);
    font-size: var(--gf-font-size);
    color: var(--gf-text);
    width: fit-content;
    transition: padding 280ms ease;
}

.forecast-bar {
    display: flex;
    align-items: center;
    gap: 6px;
}

.forecast-pip {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 56px;
    gap: 4px;
    animation: forecast-pip-in 320ms ease both;
}

@keyframes forecast-pip-in {
    from { opacity: 0; transform: translateY(-4px) scale(0.92); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.forecast-label {
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--gf-text-dim);
}

.forecast-icon {
    width: 24px;
    height: 24px;
    display: block;
    animation: forecast-icon-pop 520ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes forecast-icon-pop {
    0%   { opacity: 0; transform: scale(0.55) rotate(-12deg); filter: blur(2px) drop-shadow(0 0 0 rgba(120, 200, 255, 0)); }
    55%  { opacity: 1; transform: scale(1.18) rotate(3deg);   filter: blur(0)   drop-shadow(0 0 8px rgba(120, 200, 255, 0.55)); }
    100% { opacity: 1; transform: scale(1)    rotate(0);      filter: blur(0)   drop-shadow(0 0 0 rgba(120, 200, 255, 0)); }
}

.forecast-icon-placeholder { opacity: 0; animation: none; }

.forecast-value {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    font-size: 13px;
}

.forecast-connector {
    flex: 1;
    height: 2px;
    background: linear-gradient(90deg, rgba(255,255,255,0.25), rgba(255,255,255,0.10));
    border-radius: 1px;
    align-self: center;
    margin-top: 20px;
}

.damage-panel {
    display: flex;
    flex-direction: column;
    gap: 6px;
    color: var(--gf-text);
    width: 100%;
    align-items: center;            /* keep the compact body centred if the panel box is wider */
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
}

.damage-body {
    background: var(--gf-bg, rgba(0, 0, 0, 0.70));
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    border-radius: 8px;
    padding: 14px 20px 16px;        /* roomier than the tight 11/13/12 */
    width: 252px;                   /* fixed width (car 206 + 40 padding + breathing); gauge bar + car stay aligned */
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}

/* ── Aero gauge — flat horizontal header strip (number + AERO + 10-seg bar) ── */
.dmg-hdr { display: flex; align-items: center; gap: 9px; width: 100%; margin-bottom: 8px; }
.dmg-num { font-size: 26px; font-weight: 800; line-height: 1; letter-spacing: -0.5px; color: #fff;
           font-family: var(--gf-font-data); font-variant-numeric: tabular-nums; }
.dmg-pct { font-size: 12px; font-weight: 600; margin-left: 1px; color: var(--gf-dmg-warn); }
.dmg-lbl { font-size: 9px; font-weight: 700; letter-spacing: 2.2px; color: rgba(200, 210, 230, 0.55); }
.dmg-num { flex: 0 0 auto; }
.dmg-bar { margin-left: auto; flex: 0 0 auto; display: flex; gap: 2px; height: 13px; }
.dmg-bar .seg { width: 6px; border-radius: 2px; background: rgba(255, 255, 255, 0.045);
                transition: background 0.35s ease; }
.dmg-bar .seg.on { background: var(--gf-dmg-warn); }            /* flat solid — no gloss/glow */
.dmg-hdr.dmg-crit .dmg-pct { color: var(--gf-dmg-crit); }
.dmg-hdr.dmg-crit .dmg-bar .seg.on { background: var(--gf-dmg-crit); }

/* ── Damage zones — dim/neutral OK, colour only on damage (class per severity).
   var()/color-mix only resolve via CSS, NOT in SVG fill=/stroke= attributes. ── */
/* Ramp matches the approved mock 1:1 — grey(none) -> yellow(light) -> orange(heavy)
   -> red(crit). Heavy/crit use the colourblind-aware --gf-dmg-* vars (their default
   hex IS the mock's orange/red); "light" has no palette var, so it's literal yellow. */
.gf-ov .dmg-z0 { fill: rgba(140, 155, 175, 0.07); stroke: rgba(150, 165, 185, 0.38); stroke-width: 1.5px; }
.gf-ov .dmg-z1 { fill: rgba(245, 197, 24, 0.32); stroke: #F5C518; stroke-width: 1.5px; }
.gf-ov .dmg-z2 { fill: color-mix(in srgb, var(--gf-dmg-warn) 34%, transparent); stroke: var(--gf-dmg-warn); stroke-width: 1.5px; }
.gf-ov .dmg-z3 { fill: color-mix(in srgb, var(--gf-dmg-crit) 34%, transparent); stroke: var(--gf-dmg-crit); stroke-width: 1.5px; }

/* ── Tyres (outside the body) + suspension chevrons — colour via class ── */
.gf-ov .dmg-tyre-ok   { fill: rgba(225, 232, 244, 0.30); stroke: rgba(255, 255, 255, 0.6); }
.gf-ov .dmg-tyre-flat { fill: #F5C518;                   stroke: rgba(255, 235, 150, 0.9); }
.gf-ov .dmg-tyre-det  { fill: none;                      stroke: var(--gf-dmg-crit); }
.gf-ov .dmg-susp      { fill: none; stroke: rgba(150, 165, 185, 0.45); }
.gf-ov .dmg-susp-det  { fill: none; stroke: var(--gf-dmg-crit); }

@keyframes damagePartPulse {
    0%   { opacity: 1 }
    15%  { opacity: 0.35 }
    30%  { opacity: 1 }
    45%  { opacity: 0.35 }
    60%  { opacity: 1 }
    75%  { opacity: 0.35 }
    100% { opacity: 1 }
}

.damage-panel .fresh { animation: damagePartPulse 3.2s ease-in-out forwards; }

/* ============================================================
   ESSENTIAL INPUTS OVERLAY — Race Team style (Direction B)
   Top green accent line + header strip + body row.
   ============================================================ */
.ei-panel {
    font-family: var(--gf-font-data);
    font-variant-numeric: tabular-nums;
    color: var(--gf-text);
    background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 8px);
    overflow: hidden;
    /* The "powered by" strip is absolutely placed on the right edge; reserve its
       width here so the body content never slides under it. min-width:max-content
       keeps the panel at least as wide as its content so the body can't overflow
       and shove the wheel into the strip. One panel = one background + border +
       emboss wrapping everything (no seam). */
    position: relative;
    padding-right: 38px;
    min-width: max-content;
    box-sizing: border-box;
}


/* "powered by GO FAST" — a vertical strip on the panel's right edge, INSIDE the
   panel so it shares the one background + border + emboss (no separate tab look).
   Minimal: no fill, a hairline divider, and a green livery line down the outer
   edge. Content is laid out horizontally then rotated 90° (reads bottom-to-top). */
.ei-pill {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-left: 1px solid rgba(255, 255, 255, 0.06);
    background: none;
}
/* Green livery line down the strip's outer edge — the brand accent. */
.ei-pill::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 2px;
    background: #27E88D;
    box-shadow: 0 0 8px rgba(39, 232, 141, 0.6);
}
.ei-pill-content {
    display: flex;
    align-items: center;
    gap: 5px;
    transform: rotate(-90deg);
    white-space: nowrap;
    pointer-events: none;
}
.ei-poweredby {
    font-size: 7px;
    font-weight: 600;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.34);
    white-space: nowrap;
}

/* ============================================================
   TARGET SWITCHER OVERLAY
   Compact chip (collapsed) + hover panel. Green livery edge +
   brand accent match the overlay family. Scoped to .gf-ov via depth.
   ============================================================ */
/* Fixed width so the panel can't grow with content — the live delta then just
   moves within a fixed-width chip (the spacer absorbs it) instead of reflowing
   the whole bar every tick. Pair with AllowSideResize="false" in OverlayRoot. */
.tgt-wrap { position: relative; width: 360px; box-sizing: border-box; font-family: var(--gf-font-data); font-variant-numeric: tabular-nums; }

.tgt-chip {
    display: flex; align-items: center; gap: 11px; padding: 9px 13px;
    color: var(--gf-text); background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 8px); overflow: hidden; position: relative;
}
.tgt-chip::after { content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 2px;
    background: #27E88D; box-shadow: 0 0 8px rgba(39, 232, 141, 0.6); }
.tgt-src { font: 700 10px/1 var(--gf-font-data); letter-spacing: 1px; color: #27E88D;
    padding: 4px 7px; border-radius: 5px; background: rgba(39, 232, 141, 0.10); }
.tgt-rung { font: 700 12px/1 var(--gf-font-data); color: rgba(255, 255, 255, 0.55); }
/* name truncates instead of growing the chip; delta has a stable width so its
   live value changing never reflows the row. The spacer absorbs the slack, so
   the chip stays a fixed width tick-to-tick (no jumping). */
.tgt-name { font: 600 13px/1 var(--gf-font-data); letter-spacing: .2px; white-space: nowrap;
    flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tgt-time { font: 700 14px/1 var(--gf-font-data); flex: 0 0 auto; }
.tgt-spacer { flex: 1 1 auto; }
/* Fixed (not min-width) + roomy so the live value never resizes the pill. */
.tgt-delta { font: 800 14px/1 var(--gf-font-data); padding: 5px 9px; border-radius: 6px;
    flex: 0 0 auto; width: 5em; box-sizing: border-box; text-align: center; overflow: hidden; }
.tgt-delta.behind { color: #FF5A4D; background: rgba(255, 90, 77, 0.12); }
.tgt-delta.ahead  { color: #27E88D; background: rgba(39, 232, 141, 0.12); }

/* Flush to the chip (no gap) so moving the mouse from chip to panel stays
   within .tgt-wrap and never triggers mouseleave / collapse. Both are
   descendants of .tgt-wrap, so with no empty space between them the hover holds. */
.tgt-panel {
    position: absolute; top: 100%; left: 0; right: 0; z-index: 5;
    color: var(--gf-text); background: var(--gf-bg);
    backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(12px * var(--gf-bdf-k, 1)));
    border-radius: var(--border-radius, 8px); overflow: hidden;
    transform-origin: top center;
    animation: tgt-panel-in 160ms cubic-bezier(0.2, 0.9, 0.25, 1.05) both;
}
@keyframes tgt-panel-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.tgt-tabs { display: flex; gap: 4px; padding: 8px 10px 6px; }
/* Single-line tab labels: "MY SESSIONS" was wrapping to two lines while the
   others stayed one, leaving the tabs uneven. nowrap + a slightly tighter
   font/letter-spacing keeps all four on one centered line. */
.tgt-tab { flex: 1; text-align: center; white-space: nowrap; font: 700 9.5px/1 var(--gf-font-data); letter-spacing: .3px;
    padding: 7px 3px; border-radius: 6px; color: rgba(255, 255, 255, 0.45);
    background: rgba(255, 255, 255, 0.03); cursor: pointer; }
.tgt-tab.on { color: #27E88D; background: rgba(39, 232, 141, 0.12); box-shadow: inset 0 0 0 1px rgba(39, 232, 141, 0.30); }
.tgt-list { padding: 4px 8px 8px; max-height: 220px; overflow-y: auto; }
.tgt-row { display: flex; align-items: center; gap: 9px; padding: 7px 9px; border-radius: 6px; cursor: pointer; }
.tgt-row:hover { background: rgba(255, 255, 255, 0.04); }
.tgt-row.cur { background: rgba(39, 232, 141, 0.10); box-shadow: inset 0 0 0 1px rgba(39, 232, 141, 0.22); }
.tgt-pos { width: 26px; flex-shrink: 0; text-align: center; font: 700 11px/1 var(--gf-font-data); color: rgba(255, 255, 255, 0.4); }
.tgt-rn { flex: 1; font: 600 12px/1 var(--gf-font-data); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tgt-rt { font: 700 12px/1 var(--gf-font-data); }
.tgt-row.cur .tgt-rt { color: #27E88D; }
.tgt-empty { padding: 14px 9px; text-align: center; color: rgba(255, 255, 255, 0.4); font-size: 12px; }
.tgt-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 13px;
    border-top: 1px solid rgba(255, 255, 255, 0.06); font: 600 10px/1.3 var(--gf-font-data); color: rgba(255, 255, 255, 0.45); }
.tgt-toggle { font-weight: 700; color: rgba(255, 255, 255, 0.4); cursor: pointer; padding: 3px 8px; border-radius: 5px; background: rgba(255, 255, 255, 0.04); }
.tgt-toggle.on { color: #27E88D; background: rgba(39, 232, 141, 0.14); }

/* Header caption ABOVE the bar — makes the overlay's purpose obvious at a glance.
   Text-shadow keeps it legible over a bright game background. */
.tgt-header { padding: 0 2px 5px; font: 700 9px/1 var(--gf-font-data); letter-spacing: 1.4px;
    text-transform: uppercase; color: rgba(255, 255, 255, 0.62); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85); }

/* Hover-panel header — title only (the instructional hint line was cut
   2026-06-10; this is a live overlay, not a tutorial). */
.tgt-head { padding: 9px 13px 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); }
.tgt-head-title { display: block; font: 800 12px/1 var(--gf-font-data); letter-spacing: .3px; color: #fff; }

/* While a comparison source loads, dim + disable the list so re-clicks are ignored. */
.tgt-list--loading { opacity: 0.5; pointer-events: none; }

/* AUTO badge on the chip — persistent cue that the target self-advances. */
.tgt-auto { flex: 0 0 auto; font: 700 8px/1 var(--gf-font-data); letter-spacing: .8px;
    color: #27E88D; background: rgba(39, 232, 141, 0.16); padding: 3px 5px; border-radius: 4px; }

/* Stacked times: the TARGET lap (prominent) over YOUR last lap (muted). */
.tgt-times { display: flex; flex-direction: column; align-items: flex-end; flex: 0 0 auto; gap: 1px; }
.tgt-t-tgt { font: 700 13px/1 var(--gf-font-data); color: #fff; }
.tgt-t-you { font: 600 9px/1 var(--gf-font-data); letter-spacing: .3px; color: rgba(255, 255, 255, 0.45); }

/* Flash the chip green when the target auto-advances (you beat it). */
.tgt-chip--advanced { animation: tgt-flash 1.6s ease-out; }
@keyframes tgt-flash {
    0%   { background: rgba(39, 232, 141, 0.30); }
    100% { background: var(--gf-bg); }
}

/* ---- full-parity picker: Auto / Pro / Leaderboard ladder / My Sessions ---- */
/* Always-on (static) variant: the picker IS the overlay — no collapsed chip,
   no hover expand. Overrides the absolute/animated dropdown positioning. */
.tgt-panel--static { position: static; animation: none; }
/* Body HUGS each tab's content (2026-06-10 redesign — was a fixed 210px sized
   to the tallest tab). The panel is top-anchored, so tab switches grow/shrink
   downward only; long lists still cap + scroll via .tgt-scroll below. */
.tgt-body { padding: 4px 10px 10px; }
.tgt-scroll { max-height: 196px; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.tgt-scroll::-webkit-scrollbar { width: 6px; }
.tgt-scroll::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 3px; }

/* Comparison card (Auto tab) + pro hero (.tgt-ref): bar + badge left, time + name right. */
.tgt-card, .tgt-ref { display: flex; overflow: hidden; border: 1px solid rgba(39, 232, 141, 0.38);
    background: rgba(39, 232, 141, 0.09); border-radius: 10px; cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), inset 0 -1px 0 rgba(0, 0, 0, 0.3); }
.tgt-cbar { width: 4px; background: #27E88D; flex: 0 0 auto; }
.tgt-cbd { flex: 1; min-width: 0; padding: 9px 12px; display: flex; align-items: center; gap: 9px; }
.tgt-cbadge { font: 800 9px/1 var(--gf-font-data); letter-spacing: .5px; text-transform: uppercase;
    color: #0e0e10; background: #27E88D; border-radius: 999px; padding: 3px 8px; flex: 0 0 auto; }
.tgt-csp { flex: 1; }
.tgt-ct { font: 800 15px/1 var(--gf-font-data); flex: 0 0 auto; }
.tgt-cwho { font: 600 13px/1 var(--gf-font-data); color: rgba(255, 255, 255, 0.9); white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; max-width: 9rem; }
.tgt-card.lb { border-color: rgba(138, 214, 255, 0.38); background: rgba(138, 214, 255, 0.08); }
.tgt-card.lb .tgt-cbar, .tgt-card.lb .tgt-cbadge { background: #8ad6ff; }
.tgt-card.dim { opacity: .55; cursor: default; box-shadow: none; }
.tgt-ref.cur { box-shadow: inset 0 0 0 1px rgba(39, 232, 141, 0.5); }
.tgt-card-note { font: 500 11px/1.5 var(--gf-font-data); color: rgba(255, 255, 255, 0.5); margin-top: 8px; }
.tgt-alt-h { font: 700 9.5px/1 var(--gf-font-data); letter-spacing: .5px; text-transform: uppercase;
    color: rgba(255, 255, 255, 0.4); margin: 12px 0 6px; }

/* Pro-laps "other laps" rows. */
.tgt-alt { display: flex; align-items: center; gap: 9px; padding: 7px 10px; border-radius: 8px;
    background: rgba(255, 255, 255, 0.03); cursor: pointer; margin-bottom: 4px; }
.tgt-alt:hover { background: rgba(255, 255, 255, 0.06); }
.tgt-alt-tm { font: 700 12px/1 var(--gf-font-data); width: 4.2rem; flex: 0 0 auto; }
.tgt-alt-who { flex: 1; font: 600 12px/1 var(--gf-font-data); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Leaderboard Auto-advance / Pick-a-lap segmented toggle. */
.tgt-ldt { display: flex; gap: 3px; background: rgba(0, 0, 0, 0.25); border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 8px; padding: 3px; margin-bottom: 8px; }
.tgt-ldt-btn { flex: 1; text-align: center; font: 700 11px/1 var(--gf-font-data); padding: 6px;
    border-radius: 6px; color: rgba(255, 255, 255, 0.5); cursor: pointer; }
.tgt-ldt-btn.on { background: #27E88D; color: #0e0e10; }

/* Ladder rows (with the "You" row inserted). */
.tgt-ladder { display: flex; flex-direction: column; gap: 4px; }
.tgt-lrow { display: flex; align-items: center; gap: 9px; padding: 7px 10px; border-radius: 8px;
    background: rgba(255, 255, 255, 0.03); border: 1px solid transparent; }
.tgt-lrow.pick { cursor: pointer; }
.tgt-lrow.pick:hover { background: rgba(255, 255, 255, 0.06); }
.tgt-lrow.chasing { background: rgba(39, 232, 141, 0.10); border-color: rgba(39, 232, 141, 0.45); }
.tgt-lrow.chasing .tgt-gap { color: #27E88D; font-weight: 800; }
.tgt-lrow.sel { background: rgba(39, 232, 141, 0.12); border-color: rgba(39, 232, 141, 0.5); }
.tgt-lrow.you { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.18); }
.tgt-gap { font: 700 10.5px/1 var(--gf-font-data); color: rgba(255, 255, 255, 0.45); width: 2.8rem;
    text-align: right; flex: 0 0 auto; }
.tgt-pos--hide { visibility: hidden; }
.tgt-cpill { font: 800 8px/1 var(--gf-font-data); letter-spacing: .5px; text-transform: uppercase;
    color: #0e0e10; background: #27E88D; border-radius: 999px; padding: 3px 6px; flex: 0 0 auto; }
.tgt-youp { display: inline-block; font: 800 9px/1 var(--gf-font-data); letter-spacing: .5px;
    text-transform: uppercase; color: #fff; background: rgba(255, 255, 255, 0.16); border-radius: 999px; padding: 3px 8px; }
/* (.tgt-hint removed 2026-06-10 — the leaderboard footer hint lines were cut.) */

/* My Sessions list + drill-in. Rows are a two-line hierarchy (2026-06-10):
   track name primary, car + date as a dim sub-line — no dash-joined strings. */
.tgt-sess { display: flex; align-items: center; gap: 9px; padding: 7px 10px; border-radius: 8px;
    background: rgba(255, 255, 255, 0.03); cursor: pointer; margin-bottom: 4px; }
.tgt-sess:hover { background: rgba(255, 255, 255, 0.06); }
.tgt-sess-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tgt-sess-trk { font: 700 12px/1.2 var(--gf-font-data); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tgt-sess-sub { font: 500 10px/1.2 var(--gf-font-data); color: rgba(255, 255, 255, 0.5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tgt-sess-t { font: 700 12px/1 var(--gf-font-data); flex: 0 0 auto; }
.tgt-sess-chev { color: rgba(255, 255, 255, 0.4); flex: 0 0 auto; }
.tgt-drill-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.tgt-back { width: 22px; height: 22px; border-radius: 7px; border: 1px solid rgba(255, 255, 255, 0.18);
    background: rgba(255, 255, 255, 0.05); color: #fff; cursor: pointer; font-size: 13px; line-height: 1; flex: 0 0 auto; }
/* Drill header mirrors the session rows: stacked title/sub, and the session's
   BEST LAP right-aligned, inset to the rows' 10px so the time columns line up.
   Header main + time are click targets (= "use the best lap"), replacing the
   old "No individual laps — use best lap" empty-state line. */
.tgt-drill-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; cursor: pointer; }
.tgt-drill-title { font: 700 12px/1.3 var(--gf-font-data); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tgt-drill-sub { font: 500 10px/1.2 var(--gf-font-data); color: rgba(255, 255, 255, 0.5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tgt-drill-t { margin-left: auto; padding-right: 10px; cursor: pointer; }
.tgt-lap { display: flex; align-items: center; justify-content: space-between; padding: 7px 10px;
    border-radius: 8px; background: rgba(255, 255, 255, 0.03); cursor: pointer; margin-bottom: 4px; }
.tgt-lap:hover { background: rgba(255, 255, 255, 0.06); }
.tgt-lap.off { opacity: .4; pointer-events: none; }
.tgt-lap.sel { background: rgba(39, 232, 141, 0.12); box-shadow: inset 0 0 0 1px rgba(39, 232, 141, 0.5); }
.tgt-lap.sel .tgt-lap-t { color: #27E88D; }
.tgt-lap-n { font: 600 12px/1 var(--gf-font-data); }
.tgt-lap-t { font: 700 12px/1 var(--gf-font-data); }
.tgt-lap-t.best { color: #27E88D; }
.tgt-link { color: #27E88D; cursor: pointer; text-decoration: underline; }

/* Body — data band: trace, bars, stats, wheel. The trace stretches to the full
   pedal-column height so its top lines up with the pct labels. flex-shrink:0 so
   it never compresses its content (which would clip the wheel under the strip). */
.ei-body {
    display: flex;
    align-items: stretch;
    gap: 18px;
    padding: 16px;
}

.ei-trace {
    flex: 1;
    min-width: 230px;
    height: auto;
    min-height: 76px;
    position: relative;
}
.ei-trace canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
}

/* Pedals — pct labels sit above the bars and overflow the band. */
.ei-pedals {
    display: flex;
    align-items: flex-end;
}
.ei-row { display: flex; gap: 13px; align-items: flex-end; }
.ei-pedal-col {
    display: flex; flex-direction: column; align-items: center;
    gap: 8px;
}
.ei-pct {
    font-size: 10px; font-weight: 700;
    color: #fff;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.ei-bar {
    width: 16px;
    height: 76px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 100px;
    position: relative; overflow: hidden;
}
.ei-fill {
    position: absolute; left: 0; right: 0; bottom: 0;
    border-radius: 100px;
    transition: height 50ms linear;
}
.ei-fill.t { background: linear-gradient(0deg, var(--gf-ei-throttle) 0%, var(--gf-ei-throttle-2) 100%); box-shadow: 0 0 10px rgba(61, 220, 106, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.08); }
.ei-fill.b { background: linear-gradient(0deg, var(--gf-ei-brake) 0%, var(--gf-ei-brake-2) 100%); box-shadow: 0 0 10px rgba(255, 65, 54, 0.5),  inset 0 0 0 1px rgba(255, 255, 255, 0.08); }
.ei-fill.c { background: linear-gradient(0deg, #2DD4E4 0%, #6BE9F2 100%); box-shadow: 0 0 10px rgba(45, 212, 228, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.08); }

/* Pedals overlay only — align the ei-bars with the trace canvas.
   The trace canvas (.inp-trace-wrap) is 70 px tall and lives in .inp-main
   under align-items:center. We:
     1) shrink the bar from the EI default of 76 → 70 so the BAR equals the
        canvas in height,
     2) bottom-align ONLY the trace and the bar row inside .inp-main, while
        leaving the data + tacho centred — so the bar's 0 % line sits on
        the trace's bottom edge AND the bar's 100 % line on the trace's
        top edge. The % label remains a normal flex child above the bar
        (it would overlap the rev lights above if it were absolute-floated
        out of layout). JS pair: pedalsGraph._tickPctStr uses (70−5)/70
        = 92.86 to keep the ref tick fully inside the 70 px bar. */
.overlay-panel[data-overlay-id="pedals"] .ei-bar {
    height: 70px;
}
.overlay-panel[data-overlay-id="pedals"] .inp-traces {
    align-self: flex-end;
}
.overlay-panel[data-overlay-id="pedals"] .ei-row {
    align-self: flex-end;
}
/* Hug-on-untick width stability: the pct label has no fixed box, so "100"
   (~3ch at 10px) is wider than the 16px bar — once the panel shrink-wraps
   (trace graph hidden, no min-width floor) the panel edge would twitch every
   time a pedal hits 100. A 3ch floor makes the column width constant.
   Scoped to pedals; essential-inputs shares .ei-pct but sizes its own row. */
.overlay-panel[data-overlay-id="pedals"] .ei-pct {
    min-width: 3ch;
    text-align: center;
}

/* Right-data — stats + wheel, centred in the body height (the brand now lives
   in the top header strip). Divider keeps it visually separate from the bars. */
.ei-right-data {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    padding-left: 16px;
    border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.ei-right-row {
    display: flex;
    align-items: center;
    gap: 12px;
}
.ei-wheel {
    height: 76px;
    width: 76px;
}

.ei-stats-numbers {
    display: flex; flex-direction: column;
    gap: 6px;
    align-items: flex-start;
}

/* GoFast wordmark — sits in the top header strip after "powered by".
   Native SVG aspect 922:153 ≈ 6:1; explicit height controls its size. */
.ei-logo {
    height: 8px;
    width: auto;
    display: block;
}
.ei-stat { display: flex; align-items: baseline; gap: 5px; }
.ei-stat .v {
    font-weight: 700; font-size: 18px; line-height: 1;
    color: #fff; letter-spacing: -0.025em;
    font-variant-numeric: tabular-nums;
    min-width: 3ch;
    text-align: right;
}
.ei-stat .v.gear { color: var(--gf-green); letter-spacing: -0.05em; }
.ei-stat .k {
    font-size: 7px; font-weight: 600;
    letter-spacing: 1.5px; text-transform: uppercase;
    color: rgba(255, 255, 255, 0.4);
}

/* Gear block — number + shift indicator side by side (icon to the right). */
.ei-gear-block {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    gap: 6px;
}
.ei-gear {
    font-family: var(--gf-font-data);
    font-weight: 700;
    font-size: 30px;
    line-height: 0.9;
    color: var(--gf-green);
    letter-spacing: -0.05em;
    font-variant-numeric: tabular-nums;
    min-width: 2ch;
    text-align: right;
}
.ei-gear-icon { display: block; opacity: 0.85; align-self: center; }

/* === Colourblind palettes ===
   Driven by data-colorblind="<type>" on the overlay host (an ancestor of every
   panel). Each block re-declares the status tokens for its subtree; :root above
   holds the default (Off) values, so an unset / "off" attribute = original look. */
[data-colorblind="deuteranopia"],
[data-colorblind="protanopia"] {
    --gf-green: #0BA7FF;
    --gf-orange: #FFF027;
    --gf-red: #E69F00;

    --gf-dmg-ok: #0BA7FF;       --gf-dmg-ok-2: #56C6FF;   --gf-dmg-ok-glow: rgba(11, 167, 255, 0.45);
    --gf-dmg-warn: #FFF027;     --gf-dmg-warn-2: #E6D400;  --gf-dmg-warn-glow: rgba(255, 240, 39, 0.50);
    --gf-dmg-crit: #E69F00;     --gf-dmg-crit-2: #C77F00;  --gf-dmg-crit-glow: rgba(230, 159, 0, 0.60);
    --gf-dmgm-ok-glow: rgba(11, 167, 255, 0.55);
    --gf-dmgm-warn-glow: rgba(255, 240, 39, 0.55);
    --gf-dmgm-crit-glow: rgba(230, 159, 0, 0.65);

    --gf-deltabar-ahead: #0BA7FF;
    --gf-throttle: #0BA7FF;
    --gf-steer-orange: #FFF027;
    --gf-steer-orange-2: #E6D400;
    --gf-ei-gear: #0BA7FF;
    --gf-corner-good: #0BA7FF;
    --gf-corner-bad: #E69F00;
    --gf-ei-throttle: #0BA7FF;  --gf-ei-throttle-2: #56C6FF;
    --gf-ei-brake: #E69F00;     --gf-ei-brake-2: #F0B85A;
}

[data-colorblind="tritanopia"] {
    --gf-green: #009E73;
    --gf-orange: #CC79A7;
    --gf-red: #D55E00;

    --gf-dmg-ok: #009E73;       --gf-dmg-ok-2: #33B98F;   --gf-dmg-ok-glow: rgba(0, 158, 115, 0.45);
    --gf-dmg-warn: #CC79A7;     --gf-dmg-warn-2: #B3608E;  --gf-dmg-warn-glow: rgba(204, 121, 167, 0.50);
    --gf-dmg-crit: #D55E00;     --gf-dmg-crit-2: #B34E00;  --gf-dmg-crit-glow: rgba(213, 94, 0, 0.60);
    --gf-dmgm-ok-glow: rgba(0, 158, 115, 0.55);
    --gf-dmgm-warn-glow: rgba(204, 121, 167, 0.55);
    --gf-dmgm-crit-glow: rgba(213, 94, 0, 0.65);

    --gf-deltabar-ahead: #009E73;
    --gf-throttle: #009E73;
    --gf-steer-orange: #CC79A7;
    --gf-steer-orange-2: #B3608E;
    --gf-ei-gear: #009E73;
    --gf-corner-good: #009E73;
    --gf-corner-bad: #D55E00;
    --gf-posmid-1: #CC79A7;
    --gf-posmid-2: #B3608E;
    --gf-ei-throttle: #009E73;  --gf-ei-throttle-2: #33B98F;
    --gf-ei-brake: #D55E00;     --gf-ei-brake-2: #E57A33;
}

/* ============================================================
   LINE COMPARISON — MAP MODE (top-down racing-line chase-cam)
   ============================================================ */
.rl-map-wrap {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    height: 100%;
}

/* Header card — mirrors .tyre-section-header (centred title + white-gradient underline). */
.rl-map-header {
    text-align: center;
    font-family: var(--gf-font-label);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: #fff;
    padding: 8px 0 10px;
    border-radius: 8px;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    position: relative;
    overflow: hidden;
}
.rl-map-header::after {
    content: '';
    position: absolute;
    bottom: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,0.40), rgba(255,255,255,0));
}

/* Body card — the canvas. */
.rl-map-body {
    position: relative;
    flex: 1 1 auto;
    border-radius: 8px;
    overflow: hidden;
    background: var(--gf-bg);
    backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
    -webkit-backdrop-filter: blur(calc(16px * var(--gf-bdf-k, 1)));
}
.rl-map-body canvas {
    display: block;
    width: 100%;
    height: 100%;
}
.rl-map-noref {
    position: absolute;
    top: 10px; left: 50%; transform: translateX(-50%);
    font-family: var(--gf-font-label);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #7e8893;
}

/* Map mode needs a portrait panel; Bar mode keeps the existing wide sizing.
   The :has() selector targets the position panel only when it's in Map mode. */
.overlay-panel[data-overlay-id="position"]:not(.overlay-waiting-placeholder):has(.rl-map-wrap) {
    width: 360px;
    height: 500px;
}

/* VR clickable adjust bar (VR-AB) — hidden by default everywhere (desktop in-app
   WebView + OBS/second-screen). It is shown ONLY on the VR capture surface in
   adjust mode by vr-packed.css (body.vr-mode.vr-adjust), which is more specific
   and wins without !important. Keeps this DOM (always emitted by OverlayPanel)
   invisible on every non-VR path. */
.vr-adjust-bar {
    display: none;
}

/* VR floating control bar (free-cursor edit UI) — hidden by default everywhere; shown
   ONLY on the VR capture surface in adjust mode (vr-packed.css, body.vr-mode.vr-adjust).
   Keeps this always-emitted DOM invisible on desktop / OBS / second-screen. */
#vr-adjust-toolbar {
    display: none;
}

/* ============================================================
   FIRST-RUN INTRO CARD (.ov-intro) — one-shot teaching card in the overlay
   window (OverlayRoot, gated on GlobalSettings.OverlaysIntroShown). Dark
   glass: specular top sheen, hairline border, deep shadow. NO backdrop-filter
   — the page behind the card is transparent and the sim lives behind the
   WINDOW, which CSS cannot sample, so a translucent bg just reads as a faint
   tint over the game (user-reported "too clear"); near-solid layers instead.
   Title = the app's Funnel display face (overlay-host.html loads
   newui-fonts.css for it); body = Satoshi. The two newui values carried in
   as literals (the overlay window doesn't load newui.css):
   --c-primary-200 #27E88D (app primary green), Funnel Display Bold.
   Hidden on /vr capture + browser sources via browser-host.css.
   ============================================================ */
.ov-intro {
    position: fixed;
    transform: translate(-50%, -50%);
    z-index: 9000;
    pointer-events: auto;
    width: 480px;
    border-radius: 14px;
    padding: 26px 28px 22px;
    color: #e8edf4;
    font-family: 'Satoshi', sans-serif;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0) 42%),
        linear-gradient(180deg, rgba(24, 30, 37, 0.97), rgba(13, 17, 22, 0.97));
    border: 1px solid rgba(255, 255, 255, 0.13);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.18),
        inset 0 -1px 0 rgba(0, 0, 0, 0.25),
        0 24px 70px rgba(0, 0, 0, 0.55);
}

.ov-intro-brand { display: flex; align-items: center; margin-bottom: 16px; }
.ov-intro-brand img { height: 22px; display: block; }

.ov-intro h1 {
    font-family: 'Funnel Display Bold', 'Satoshi', sans-serif;
    font-weight: normal;
    font-size: 22px;
    margin: 0 0 6px;
    letter-spacing: 0.01em;
}
.ov-intro-sub { font-size: 13.5px; color: rgba(232, 237, 244, 0.6); margin: 0 0 18px; line-height: 1.45; }

.ov-intro-row { display: flex; align-items: center; gap: 14px; padding: 9px 0; }
.ov-intro-row + .ov-intro-row { border-top: 1px solid rgba(255, 255, 255, 0.07); }

.ov-intro-keys { display: flex; gap: 4px; flex: 0 0 148px; }
.ov-intro kbd {
    font-family: inherit; font-size: 11.5px; font-weight: 700;
    color: #eef2f7;
    background: rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-bottom-width: 2px;
    border-radius: 5px;
    padding: 3px 7px;
    line-height: 1;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.ov-intro-ico {
    flex: 0 0 148px; display: flex; align-items: center;
    font-size: 17px; color: #27E88D; padding-left: 4px;
    text-shadow: 0 0 12px rgba(39, 232, 141, 0.45);
}

.ov-intro-what { font-size: 13.5px; font-weight: 600; }
.ov-intro-what small { display: block; font-size: 12px; font-weight: 500; color: rgba(232, 237, 244, 0.5); margin-top: 2px; }

.ov-intro-foot {
    margin-top: 14px; padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.ov-intro-foot p { margin: 0; font-size: 11.5px; color: rgba(232, 237, 244, 0.5); line-height: 1.4; }
.ov-intro-foot p b { color: rgba(232, 237, 244, 0.78); font-weight: 600; }

.ov-intro-done {
    flex: 0 0 auto;
    font-family: inherit; font-size: 13px; font-weight: 700;
    color: #0b1209;
    background: #27E88D;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 9px;
    padding: 9px 26px;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 3px 16px rgba(39, 232, 141, 0.35);
}
.ov-intro-done:hover { filter: brightness(1.06); }
