        /* ══════════════════════════════════════════════════════════
           Cross-browser / mobile base optimizations
           ══════════════════════════════════════════════════════════ */

        /* Smooth text rendering on macOS Safari + Chrome; stop iOS from
           auto-adjusting text size on orientation change. */
        html {
            -webkit-text-size-adjust: 100%;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }

        /* Prevent iOS Safari from auto-zooming into form fields on focus.
           iOS triggers zoom whenever a TEXT input's computed font-size is
           below 16px. Applied only to text-editable fields (not buttons/
           chips/selects where we want compact typography). Font-family
           inherits so Archivo is preserved. */
        input[type="text"], input[type="search"], input[type="email"],
        input[type="number"], input[type="tel"], input[type="url"],
        input[type="password"], textarea {
            font-size: var(--text-md);
            font-family: inherit;
        }

        /* Remove iOS default gray tap-flash on interactive elements — looks
           unpolished on modern UIs. Replace with explicit :active states
           where we want feedback. */
        a, button, input, select, textarea, .view-tab, .chart-view-tab, .toggle-chip, .filter-chip, .region-chip, .category-qs-btn, .year-mode-btn, .export-btn, .reset-zoom-btn, .chart-title-btn, .autocomplete-item, .autocomplete-item *, .ac-exclude-btn, .theme-toggle, .legend-item, .legend-mfr-header {
            -webkit-tap-highlight-color: transparent;
        }

        /* touch-action: manipulation removes the iOS 300ms click delay AND
           disables double-tap-zoom on these interactive elements — critical
           for our dblclick-to-isolate gestures on chips/tabs, otherwise iOS
           would zoom the page before our dblclick handler fires. Limited to
           small interactive surfaces, not applied to the page or chart
           canvas (which needs pan-y for scroll and our own drag). */
        button, .view-tab, .toggle-chip, .filter-chip, .region-chip, .category-qs-btn, .year-mode-btn, .export-btn, .reset-zoom-btn, .chart-title-btn, .autocomplete-item, .ac-exclude-btn, .theme-toggle, .legend-item {
            touch-action: manipulation;
        }

        /* Chart canvas: allow page pan-y (vertical scroll) to pass through,
           but block the browser's horizontal-pan gesture so our measurement
           drag gets the horizontal movement. pinch-zoom still works for
           accessibility. */
        #timeChart {
            touch-action: pan-y pinch-zoom;
        }

        /* Build 20260508zzzzzzzq: mobile gesture separation. At mobile widths the
           JS drag-to-measure is suppressed for touch input (app.js onDown, see the
           MEASURE_TOUCH_DRAG_MAX_W block) — measurement moves to the two-tap
           "Measure from here" flow — so the canvas no longer needs to steal the
           horizontal-pan gesture. Hand it back: `manipulation` restores native
           panning on BOTH axes and keeps pinch-zoom, while still removing the iOS
           300ms delay and double-tap-zoom (which would otherwise fire between the
           two measure taps). Scoped to coarse+narrow so it mirrors the JS gate
           exactly: a cursor at ANY width — including a narrow desktop window —
           keeps `pan-y pinch-zoom` and the drag, unchanged. */
        @media (pointer: coarse) and (max-width: 720px) {
            #timeChart {
                touch-action: manipulation;
            }
            /* Build 20260508zzzzzzzs: make the HOVER tooltip's CTA row tappable on
               touch. The tooltip itself stays `pointer-events: none` (so taps on
               its body still reach the bars underneath, as on desktop) — only the
               button row opts back in. Without this, "Click to expand" is a
               button-shaped label that falls through to whatever bar sits under
               the tooltip, selecting the wrong year. Paired with
               _wireHoverExpandForTouch() in app.js, which forwards the tap to the
               bar the tooltip is describing; the two are scoped to the SAME
               coarse+narrow query and must stay in sync. */
            .chart-tooltip .v8x-tt-ctas {
                pointer-events: auto;
            }
            /* 2026-10-19: the hover's × (paired with the delegated handler in app.js) — shown and tappable here only */
            .chart-tooltip:not(.frozen) .v8x-tt-hclose {
                display: inline-flex;
                pointer-events: auto;
            }
            /* Build 20260508zzzzzzzt: while a two-tap measure is ARMED, hand the
               gesture back to the chart so a finger slide drives the bracket
               instead of panning the page. Scoped to the armed window only —
               `.measure-armed` is set by primeFrom() and cleared by
               completeAt()/clear()/onUp(), so ordinary scrolling over the chart
               keeps `manipulation` (above) the rest of the time. */
            #timeChartWrap.measure-armed #timeChart {
                touch-action: none;
            }
        }

        /* Year slider track + thumbs: disable all touch-action so drag
           gestures don't fight with page scroll. Specific to these small
           interactive targets. */
        .year-range-slider,
        .year-range-thumb,
        .year-range-selected,
        .year-range-track {
            touch-action: none;
        }

        /* Smooth momentum scrolling on iOS for any scroll containers */
        .table-container, .customer-autocomplete {
            -webkit-overflow-scrolling: touch;
        }

        /* iOS / Android sticky-hover fix — on touch-only devices, :hover
           states persist after tap until the user taps elsewhere, making
           chips/buttons/tabs appear permanently hovered. This media query
           block neutralizes hover-scale and hover-brightness effects on
           devices without fine-pointer hover capability. Our :active styles
           continue to provide tap feedback. Explicit background-change
           hovers (for subtle UI cues like autocomplete-item) are left in
           place — they cause less visual confusion than transform effects. */
        @media (hover: none) {
            /* Transform-based hovers that stick noticeably on touch */
            .toggle-chip:hover, .filter-chip:hover, .region-chip:hover, .category-qs-btn:hover, .year-mode-btn:hover:not(.active), .view-tab:hover, .theme-toggle:hover, .chart-title-btn:hover, .tooltip-close:hover, .mp-close:hover, .export-btn:hover, .reset-zoom-btn:hover, .variant-toggle-btn-inline:hover, .filter-bar-toggle:hover, .ac-exclude-btn:hover {
                /* Reset any hover-applied transforms and filters — let the
                   element's base state show through on touch devices. */
                transform: none;
                filter: none;
                box-shadow: inherit;
            }
        }

        @font-face {
            font-family: 'Elza';
            src: url('https://use.typekit.net/af/e2bf85/00000000000000007735a17e/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3') format('woff2');
            font-weight: 400;
            font-style: normal;
        }
        @font-face {
            font-family: 'Elza';
            src: url('https://use.typekit.net/af/9f7ad5/00000000000000007735a182/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n5&v=3') format('woff2');
            font-weight: 500;
            font-style: normal;
        }
        @font-face {
            font-family: 'Elza';
            src: url('https://use.typekit.net/af/d7d16c/00000000000000007735a186/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n6&v=3') format('woff2');
            font-weight: 600;
            font-style: normal;
        }
        @font-face {
            font-family: 'Elza';
            src: url('https://use.typekit.net/af/5765a8/00000000000000007735a18a/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3') format('woff2');
            font-weight: 700;
            font-style: normal;
        }
        :root {
            /* TAC Brand Colors */
            --tac-blue: #1870ff;
            --tac-gold: #feab40;
            /* Semantic — change indicators (measurement tool, deltas) */
            --positive: #0a9f3b;
            --negative: #c6341e;
            /* Grays */
            --gray-light: #BDBDBD;
            --gray-pale: #E0E0E0;
            /* UI Colors */
            --bg: #FAFAFA;
            --card: #FFFFFF;
            --border: #E0E0E0;
            --text: #212121;
            --text-muted: #616161;
            /* Chart colors (used by JS via getComputedStyle) */
            --chart-grid: #E0E0E0;
            --chart-tick: #616161;
            --chart-label: #333333;
            --chart-bar-border: rgba(255,255,255,0.9);
            /* Surface variants */
            --surface-hover: #f5f5f5;
            --surface-selected: #e3f2fd;
            --surface-dim: #f8f9fa;
            --surface-inset: #f0f0f0;
            --border-subtle: #f0f0f0;
            /* Tooltip — build zzzzzzzzn: light mode now uses the app's FLOATING
               PANEL language (card surface + hairline border + elevation),
               matching .measurement-panel instead of the old dark-glass slab.
               Dark mode keeps its light-glass treatment below. */
            --tooltip-bg: rgba(255, 255, 255, 0.98);
            --tooltip-text: #131313;
            --tooltip-border: rgba(19, 19, 19, 0.12);
            --tooltip-tier-bg: rgba(19, 19, 19, 0.035);
            --tooltip-muted: #5c5c5c;
            --tooltip-shadow: 0 4px 16px rgba(19,19,19,0.10), 0 1px 3px rgba(19,19,19,0.08);
            --tooltip-shadow-frozen: 0 10px 32px rgba(19,19,19,0.18), 0 2px 6px rgba(19,19,19,0.10);
            --tooltip-ring-bg: rgba(254, 171, 64, 0.16);
            /* CTA inks: raw gold (~1.9:1) and raw blue (~3.7:1) both fail on a
               white surface — deepen for light, keep brand hues on dark.
               Mirrors the --v8-accent-segment-ink precedent (light-a11y build). */
            --tooltip-ink-gold: #9a5c00;   /* release QA F-05 (2026-10-18): 5.4:1 on white, 5.1:1 on the page (#a86400 was 4.5 / 4.3) */
            --tooltip-ink-accent: #0059eb;
            --link-ink: #0059eb;              /* release QA F-14 (2026-10-18): small blue TEXT on light — 5.8:1 on white, 5.5:1 on the page (the raw blue reads 4.4 / 4.2) */
            /* Warnings / notes */
            --warning-bg: #FFF8E1;
            --warning-text: #F9A825;
            --warning-note-bg: #fff3cd;
            --warning-note-text: #856404;
            /* Export */
            --export-bg: #ffffff;
            --export-title: #1a1a2e;
            --export-subtitle: #666666;
            --export-legend-text: #333333;
            /* Shadow intensity */
            --shadow-sm: 0 1px 3px rgba(0,0,0,0.06);
            --shadow-md: 0 1px 3px rgba(0,0,0,0.08);
            --shadow-lg: 0 20px 60px rgba(0,0,0,0.3);

            /* ── Spacing scale (Pass 1 polish) ────────────────────────
               Single source of truth for gap / padding / margin. All
               existing one-off rem values across the file collapse to
               one of these. 4px base. The hairs (3px/2px) are kept as
               literals only inside chip internals where the chip's own
               border-radius rounding constraints make 4px too loose.
            */
            --space-1: 4px;     /* hairline gap (chip-color dot ↔ label) */
            --space-2: 8px;     /* default control-internal gap */
            --space-3: 12px;    /* between related controls in a row */
            --space-4: 16px;    /* between unrelated controls / panel padding */
            --space-5: 24px;    /* between sub-sections inside a panel */
            --space-6: 32px;    /* between top-level sections */
            --space-7: 48px;    /* page-level vertical rhythm */

            /* Common control padding shorthands — inline for convenience */
            --pad-chip: 4px 12px;          /* toggle chips, region pills, count badges */
            --pad-control: 8px 12px;       /* dropdowns, search inputs, segmented controls */
            --pad-button: 8px 16px;        /* Reset View, Export, primary actions */
            --pad-tab: 6px 12px;           /* view tabs, breakdown tabs */
            --pad-cell: 6px 10px;          /* table cells, small grid cells */
            --pad-panel: 16px;             /* card / panel inner padding */
            --pad-section: 24px;           /* outer section padding */

            /* ── Type scale (Pass 2 polish) ──────────────────────────
               Single source of truth for font sizes. 32 distinct values
               existed across the file before this pass; they collapse
               to these 10 tokens. The scale is roughly 1.15× each step
               in the body range (sm → base → md), looser at the display
               end where size differences need to read clearly.

               Mental map:
                  2xs / xs   metadata, microbadges, hints
                  sm / base  default UI text and body copy
                  md / lg    section titles, sub-headings
                  xl / 2xl   card titles, stat values
                  3xl / 4xl  page-level emphasis, hero count
            */
            --text-2xs:  10px;    /* microbadges (ISO codes, role tags) */
            --text-xs:   11px;    /* hint text, dropdown items, hover labels */
            --text-sm:   12px;    /* default UI text — chips, controls, table body */
            --text-base: 13px;    /* comfortable body, comments, prose */
            --text-md:   15px;    /* sub-headings, large body */
            --text-lg:   17px;    /* section titles */
            --text-xl:   20px;    /* card titles, panel headers */
            --text-2xl:  24px;    /* stat values, modal titles */
            --text-3xl:  28px;    /* page-level emphasis */
            --text-4xl:  48px;    /* hero count, the headline number */

            /* Standard line-heights — pair with the sizes above */
            --leading-tight:  1.15;   /* display sizes, tight headlines */
            --leading-snug:   1.35;   /* UI labels, controls */
            --leading-normal: 1.5;    /* body copy */
            --leading-loose:  1.7;    /* tooltip body, prose */

            /* Font families — three roles. Body inherits --font-body
               from the body rule below; UI surfaces use --font-ui.
               The mono token covers chart-export legend numerals. */
            --font-body: 'Elza', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            --font-ui:   'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            --font-mono: 'Courier New', ui-monospace, SFMono-Regular, Consolas, monospace;

            /* ── Corner radii (Pass 3 polish) ────────────────────────
               Tokens mapped 1:1 to the existing radius values across
               the file. The point of this pass is to make corner
               radii adjustable from one place, NOT to redesign the
               corner system. If we later want a tighter/looser feel
               overall, change these tokens centrally.

               Mental map (and the actual current values):
                  xs   2px  micro elements (chip color dot, tight badge)
                  sm   3px  small badges, ISO chips, role tags
                  md   4px  default — chips, buttons, inputs, dropdowns
                  lg   6px  panel headers, secondary surfaces
                  xl   8px  cards, the chart container interior surfaces
                  2xl  12px primary chart container, modals

               Compound radii (e.g. "0 0 6px 6px" for tab caps) and 50%
               for circles stay as literals — they're shape decisions,
               not visual-system choices.
            */
            --radius-xs:  2px;
            --radius-sm:  3px;
            --radius-md:  4px;
            --radius-lg:  6px;
            --radius-xl:  8px;
            --radius-2xl: 12px;

            /* ── Wave D Build 20 (xk, 2026-05-28): V8 semantic theme tokens.
               One role-named token per V8 surface/border/state. Defined here
               in :root with LIGHT values, overridden in [data-theme="dark"]
               (V8 bluer) and [data-theme="dusk"] (V7-gray surfaces). All V8
               component CSS pulls from these so the same ruleset paints
               every theme — only the values swap. Typography is universal
               (Archivo + the eyebrow/body/muted scale we've established).
               --v8-accent-x / --v8-accent-segment are the role-meaning
               colors (blue = "what's on the x-axis", gold = "segment / scope
               / engaged filter"); they stay constant across all three themes
               per Jon's Q2 / Q3.
               -------------------------------------------------------- */
            /* Surfaces: container is the section frame (gold-bordered SCOPE
               + blue-bordered VIEW). control is the pill/chip/button surface
               nested inside the section. dropdown is the floating menu. */
            --v8-surface-section:   #FFFFFF;
            --v8-surface-control:   #F4F6F8;
            --v8-surface-dropdown:  #FFFFFF;
            /* Borders: soft = component edges (alpha-low). strong = active
               or emphasis edges. */
            --v8-border-soft:       rgba(15, 23, 42, 0.10);
            --v8-border-strong:     rgba(15, 23, 42, 0.20);
            /* Text */
            --v8-text-primary:      #1a1a1a;
            --v8-text-secondary:    #4a4a4a;
            --v8-text-muted:        #6b6b6b;
            --v8-text-disabled:     #a0a0a0;
            /* Accents (role-meaningful, constant across themes) */
            --v8-accent-x:          var(--tac-blue);
            --v8-accent-segment:    var(--tac-gold);
            /* Gold TEXT ink — the raw gold is unreadable on light surfaces
               (~1.9:1), so gold text uses a darker amber in light mode. Fills,
               swatches, and borders keep --v8-accent-segment. */
            --v8-accent-segment-ink: #9a5c00;   /* release QA F-05 (2026-10-18): ≥ 5.1:1 on every light surface (#a86400 read 4.5 on white, 4.3 on #f8f9fa) */
            /* States */
            --v8-chip-active-bg:    var(--tac-blue);
            --v8-chip-active-text:  #FFFFFF;
            --v8-pill-engaged-bg:     rgba(254, 171, 64, 0.12);
            --v8-pill-engaged-border: rgba(254, 171, 64, 0.55);
            --v8-control-hover:     rgba(0, 0, 0, 0.04);
            /* Shadows for dropdowns */
            --v8-shadow-dropdown:   0 8px 20px rgba(0, 0, 0, 0.10);
        }

        /* ── Dark Theme ─────────────────────────────────────────── */
        [data-theme="dark"] {
            color-scheme: dark;
            --tac-blue: #4DA6FF;
            /* Gold unchanged — hits contrast against dark bg already */
            --positive: #2ecc5a;
            --negative: #e85a42;
            --gray-light: #555555;
            --gray-pale: #2A2A2A;
            --bg: #141414;
            --card: #1E1E1E;
            --border: #333333;
            --text: #E8E8E8;
            --text-muted: #999999;
            --chart-grid: #333333;
            --chart-tick: #999999;
            --chart-label: #CCCCCC;
            --chart-bar-border: rgba(0,0,0,0.4);
            --surface-hover: #2A2A2A;
            --surface-selected: #1a3a5c;
            --surface-dim: #1A1A1A;
            --surface-inset: #252525;
            --border-subtle: #2A2A2A;
            --tooltip-bg: rgba(30, 30, 30, 0.95);
            --tooltip-text: #E8E8E8;
            --tooltip-border: rgba(255,255,255,0.1);
            --tooltip-tier-bg: rgba(255,255,255,0.06);
            --tooltip-muted: rgba(255,255,255,0.7);
            --tooltip-shadow: 0 4px 16px rgba(0,0,0,0.35);
            --tooltip-shadow-frozen: 0 4px 20px rgba(0,0,0,0.4);
            --tooltip-ring-bg: rgba(254, 171, 64, 0.08);
            --tooltip-ink-gold: var(--tac-gold);
            --tooltip-ink-accent: var(--tac-blue);
            --link-ink: var(--tac-blue);
            --warning-bg: #2A2200;
            --warning-text: #F9A825;
            --warning-note-bg: #2A2200;
            --warning-note-text: #F9A825;
            --export-bg: #1E1E1E;
            --export-title: #E8E8E8;
            --export-subtitle: #999999;
            --export-legend-text: #CCCCCC;
            --shadow-sm: 0 1px 3px rgba(0,0,0,0.3);
            --shadow-md: 0 1px 3px rgba(0,0,0,0.4);
            --shadow-lg: 0 20px 60px rgba(0,0,0,0.6);

            /* xk: V8 bluer dark — the signature V8 default */
            --v8-surface-section:   #161c24;
            --v8-surface-control:   #0d1117;
            --v8-surface-dropdown:  #161b22;
            --v8-border-soft:       rgba(255, 255, 255, 0.06);
            --v8-border-strong:     rgba(255, 255, 255, 0.10);
            --v8-text-primary:      #eeeeee;
            --v8-text-secondary:    #c3c3c3;
            --v8-text-muted:        #959595;
            --v8-text-disabled:     #5c5c5c;
            --v8-pill-engaged-bg:     rgba(254, 171, 64, 0.06);
            --v8-pill-engaged-border: rgba(254, 171, 64, 0.30);
            --v8-accent-segment-ink:  var(--tac-gold);
            --v8-control-hover:     rgba(255, 255, 255, 0.04);
            --v8-shadow-dropdown:   0 8px 20px rgba(0, 0, 0, 0.55);
        }

        /* ── Dusk Theme — V7 dark gray flavor poured through V8 components.
           Same V8 layout, typography, and accent meanings (gold / blue);
           surfaces use V7's gray ramp (#1E1E1E / #141414) and borders go
           solid mid-gray instead of alpha-white. xk (2026-05-28). */
        [data-theme="dusk"] {
            color-scheme: dark;
            --tac-blue: #4DA6FF;
            --positive: #2ecc5a;
            --negative: #e85a42;
            --gray-light: #555555;
            --gray-pale: #2A2A2A;
            --bg: #141414;
            --card: #1E1E1E;
            --border: #333333;
            --text: #E8E8E8;
            --text-muted: #999999;
            --chart-grid: #333333;
            --chart-tick: #999999;
            --chart-label: #CCCCCC;
            --chart-bar-border: rgba(0,0,0,0.4);
            --surface-hover: #2A2A2A;
            --surface-selected: #1a3a5c;
            --surface-dim: #1A1A1A;
            --surface-inset: #252525;
            --border-subtle: #2A2A2A;
            --tooltip-bg: rgba(30, 30, 30, 0.95);
            --tooltip-text: #E8E8E8;
            --tooltip-border: rgba(255,255,255,0.1);
            --tooltip-tier-bg: rgba(255,255,255,0.06);
            --tooltip-muted: rgba(255,255,255,0.7);
            --tooltip-shadow: 0 4px 16px rgba(0,0,0,0.35);
            --tooltip-shadow-frozen: 0 4px 20px rgba(0,0,0,0.4);
            --tooltip-ring-bg: rgba(254, 171, 64, 0.08);
            --tooltip-ink-gold: var(--tac-gold);
            --tooltip-ink-accent: var(--tac-blue);
            --link-ink: var(--tac-blue);
            --warning-bg: #2A2200;
            --warning-text: #F9A825;
            --warning-note-bg: #2A2200;
            --warning-note-text: #F9A825;
            --export-bg: #1E1E1E;
            --export-title: #E8E8E8;
            --export-subtitle: #999999;
            --export-legend-text: #CCCCCC;
            --shadow-sm: 0 1px 3px rgba(0,0,0,0.3);
            --shadow-md: 0 1px 3px rgba(0,0,0,0.4);
            --shadow-lg: 0 20px 60px rgba(0,0,0,0.6);

            /* V8 tokens — V7 gray flavored. Surfaces use V7's #1E1E1E/#141414
               card/page ramp; borders go solid #333 instead of alpha-white;
               text uses V7's slightly cooler tonality. Accents stay vivid. */
            --v8-surface-section:   #1E1E1E;
            --v8-surface-control:   #141414;
            --v8-surface-dropdown:  #1E1E1E;
            --v8-border-soft:       #2A2A2A;
            --v8-border-strong:     #333333;
            --v8-text-primary:      #E8E8E8;
            --v8-text-secondary:    #CCCCCC;
            --v8-text-muted:        #999999;
            --v8-text-disabled:     #555555;
            --v8-pill-engaged-bg:     rgba(254, 171, 64, 0.08);
            --v8-pill-engaged-border: rgba(254, 171, 64, 0.35);
            --v8-accent-segment-ink:  var(--tac-gold);
            --v8-control-hover:     rgba(255, 255, 255, 0.05);
            --v8-shadow-dropdown:   0 8px 20px rgba(0, 0, 0, 0.55);
        }
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body {
            font-family: var(--font-body);
            background: var(--bg);
            color: var(--text);
            /* 100dvh (dynamic viewport height) accounts for mobile browser
               chrome (address bar showing/hiding) so the page doesn't
               initially render taller than the visible area. Falls back to
               100vh on browsers without dvh support. */
            min-height: 100vh;
            min-height: 100dvh;
            /* Safe-area insets: respect iOS notches and home indicators.
               max() ensures we never go below our design padding. */
            padding: var(--space-5);
            padding-left: max(1.5rem, env(safe-area-inset-left));
            padding-right: max(1.5rem, env(safe-area-inset-right));
            padding-bottom: max(1.5rem, env(safe-area-inset-bottom));
        }
        /* ══════════════════════════════════════════════════════════════════
           Page header — editorial masthead with split layout.
           Left: gold-bulleted eyebrow + title.
           Right: year range as prominent numeric with "Coverage" caption.
           All colors use theme variables so dark mode adapts automatically.
           ══════════════════════════════════════════════════════════════════ */
        .header {
            display: flex;
            justify-content: space-between;
            align-items: flex-end;
            gap: var(--space-6);
            /* 14px = the space above the headline ticker, matched to the
               scoreboard → chart gap (.v8-tallies margin-bottom). */
            margin-bottom: 14px;
            padding-bottom: var(--space-4);
            border-bottom: 1px solid var(--border);
        }
        .header-left {
            min-width: 0;  /* allow flex child to shrink */
            flex: 1;
        }
        .header-eyebrow {
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 700;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--text-muted);
            display: inline-flex;
            align-items: center;
            gap: var(--space-2);
            margin-bottom: var(--space-3);
            line-height: 1;
        }
        .header-eyebrow .eyebrow-sep {
            color: var(--gray-light);
            font-weight: 400;
            margin: 0 var(--space-2);
        }
        /* Brand word+logo mark replaces the gold dot + "The Air Current" text
           (same source images as the chart branding; light for light themes,
           white for dark/dusk). "/ Aviation Data" is enlarged to sit at the
           wordmark's cap height. */
        .header-eyebrow .eyebrow-logo {
            display: inline-flex;
            align-items: center;
        }
        .header-eyebrow .eyebrow-logo img {
            height: 19px;
            width: auto;
        }
        /* Display is owned by the theme toggle only — do NOT set display on the
           img rule above, or its higher specificity (…img) would defeat the
           .logo-dark{display:none} default and show both marks in light theme. */
        .header-eyebrow .logo-light { display: block; }
        .header-eyebrow .logo-dark { display: none; }
        [data-theme="dark"] .header-eyebrow .logo-light,
        [data-theme="dusk"] .header-eyebrow .logo-light { display: none; }
        [data-theme="dark"] .header-eyebrow .logo-dark,
        [data-theme="dusk"] .header-eyebrow .logo-dark { display: block; }
        .header-eyebrow .eyebrow-sep,
        .header-eyebrow .eyebrow-aviation {
            font-size: 15px;
        }
        .header h1 {
            font-family: var(--font-ui);
            font-size: var(--text-3xl);
            font-weight: 700;
            margin: 0;
            color: var(--text);
            letter-spacing: -0.016em;
            line-height: 1.1;
        }

        /* ── Live headline ticker — The Air Current RSS ─────────────────────
           Sits below the header rule, above the stats grid. Rotating headline
           (single line, ellipsis on overflow) links to its article; gold
           Subscribe button pinned right. Revealed by JS once the feed loads. */
        .tac-ticker {
            display: flex;
            align-items: center;
            gap: var(--space-4);
            /* 14px below (top gap comes from .header margin-bottom) = the
               scoreboard → chart gap, so the ticker sits in matching rhythm. */
            margin: 0 0 14px;
            padding: var(--space-3) var(--space-4);
            /* The V8 section surface — the same tokens the chart container
               paints with in V8 mode (xk/xm precedent above the .chart-container
               rule): white in light, V7 gray #1E1E1E in dusk, the bluer #161c24
               in dark. Jon 2026-10-09: the strip must follow the page's body
               surface in the bluer theme, where --card stays V7 gray. Radius and
               elevation follow the scoreboard cards. (Was --surface-dim with a
               smaller radius and no shadow — a different, dimmer tile.) */
            background: var(--v8-surface-section);
            border: 1px solid var(--v8-border-soft);
            border-radius: var(--radius-xl);
            box-shadow: var(--shadow-sm);
            min-width: 0;
            opacity: 0;
            transition: opacity 0.4s ease;
        }
        .tac-ticker.tac-ticker-in { opacity: 1; }
        .tac-ticker[hidden] { display: none; }

        .tac-ticker-brand {
            display: inline-flex;
            align-items: center;
            gap: var(--space-2);
            flex-shrink: 0;
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 700;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            color: var(--text-muted);
            text-decoration: none;
            transition: color 0.15s ease;
        }
        .tac-ticker-brand:hover { color: var(--text); }
        .tac-ticker-live {
            width: 7px;
            height: 7px;
            border-radius: 50%;
            background: var(--tac-gold);
            flex-shrink: 0;
            animation: tac-ticker-pulse 2.4s ease-out infinite;
        }
        @keyframes tac-ticker-pulse {
            0%   { box-shadow: 0 0 0 0 rgba(254,171,64,0.55); }
            70%  { box-shadow: 0 0 0 6px rgba(254,171,64,0); }
            100% { box-shadow: 0 0 0 0 rgba(254,171,64,0); }
        }

        .tac-ticker-headline {
            flex: 1 1 auto;
            min-width: 0;
            font-family: var(--font-ui);
            font-size: var(--text-base);
            font-weight: 600;
            color: var(--text);
            text-decoration: none;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            transition: opacity 0.3s ease, color 0.15s ease;
        }
        .tac-ticker-headline:hover { color: var(--tac-blue); }
        .tac-ticker-headline.tac-fade { opacity: 0; }

        .tac-subscribe-btn {
            flex-shrink: 0;
            font-family: var(--font-ui);
            font-size: var(--text-sm);
            font-weight: 700;
            letter-spacing: 0.02em;
            color: #1a1206;                 /* dark ink on gold — AA contrast */
            background: var(--tac-gold);
            padding: var(--pad-button);
            border-radius: var(--radius-md);
            text-decoration: none;
            white-space: nowrap;
            transition: filter 0.15s ease, transform 0.05s ease;
        }
        .tac-subscribe-btn:hover { filter: brightness(1.06); }
        .tac-subscribe-btn:active { transform: translateY(1px); }

        @media (max-width: 520px) {
            .tac-ticker { gap: var(--space-3); padding: var(--space-2) var(--space-3); }
            .tac-ticker-brand-txt { display: none; }   /* keep the pulse dot, drop the word */
            .tac-ticker-headline { font-size: var(--text-sm); }
            .tac-subscribe-btn { font-size: var(--text-xs); padding: var(--pad-tab); }
        }
        @media (prefers-reduced-motion: reduce) {
            .tac-ticker-live { animation: none; }
            .tac-ticker, .tac-ticker-headline { transition: none; }
        }

        /* Theme toggle */
        /* Wave D Build 19 (xj, 2026-05-27): 3-state segmented theme control.
           Light · Legacy · Dark. Active segment fills with TAC blue; inactive
           segments are transparent with muted icon. Sized to fit the same
           fixed top-right slot the single button occupied; ~108px wide so
           three 34px segments + container padding fit. */
        .theme-toggle {
            position: fixed;
            top: 1rem;
            right: 1.5rem;
            z-index: 500;
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            padding: 2px;
            display: inline-flex;
            align-items: center;
            gap: 1px;
            box-shadow: var(--shadow-sm);
            transition: border-color 0.2s, background 0.2s;
        }
        .theme-toggle:hover {
            border-color: var(--tac-blue);
        }
        .theme-toggle .theme-opt {
            width: 30px;
            height: 28px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background: transparent;
            border: none;
            border-radius: calc(var(--radius-xl) - 4px);
            cursor: pointer;
            font-size: 14px;
            line-height: 1;
            color: var(--text-muted);
            opacity: 0.55;
            transition: background 150ms, opacity 150ms, color 150ms;
            padding: 0;
        }
        .theme-toggle .theme-opt:hover {
            opacity: 0.85;
        }
        .theme-toggle .theme-opt.active {
            background: var(--tac-blue);
            opacity: 1;
            color: white;
            /* The emoji glyphs render in their own colors regardless of
               `color:`, so the active fill behind them is what carries the
               selection signal. */
        }
        .theme-toggle .theme-opt:focus-visible {
            outline: 2px solid var(--tac-blue);
            outline-offset: 2px;
        }

        /* Wave D Build 22 (xm, 2026-05-28): Logo swap must fire for BOTH
           dark moon modes (V8 bluer dark + V7 gray dusk). Pre-xm only
           [data-theme="dark"] flipped to the white-text logo; dusk fell
           back to the default black-text logo on a dark surface, which
           rendered as invisible. Both moon states now use logo-dark
           (the white-text TAC mark). */
        .chart-branding .logo-dark { display: none; }
        [data-theme="dark"] .chart-branding .logo-light,
        [data-theme="dusk"] .chart-branding .logo-light { display: none; }
        [data-theme="dark"] .chart-branding .logo-dark,
        [data-theme="dusk"] .chart-branding .logo-dark { display: inline-block; }
        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-4);
            margin-bottom: var(--space-5);
            align-items: center;
            justify-content: center;
        }
        .control-group {
            display: flex;
            align-items: center;
            gap: var(--space-2);
        }
        .control-group label {
            color: var(--text-muted);
            font-size: var(--text-sm);
            font-family: var(--font-ui);
        }
        .control-group-row {
            display: flex;
            align-items: center;
            gap: var(--space-2);
        }
        /* ── Control Tier System ─────────────────────────────────── */
        /* Tier 1 "Compact": chips, tabs, toggle btns, action btns   */
        /*   height ~28px — padding 0.3rem 0.6rem — font 0.75rem     */
        /* Tier 2 "Standard": primary selects, text inputs            */
        /*   height ~32px — padding 0.4rem 0.75rem — font 0.85rem    */
        /* All interactive controls use Archivo for visual unity      */

        select, input[type="range"] {
            background: var(--card);
            border: 1px solid var(--border);
            color: var(--text);
            padding: var(--space-2) var(--space-3);
            border-radius: var(--radius-lg);
            font-size: var(--text-base);
            font-family: var(--font-ui);
        }
        select:focus, input:focus { outline: none; border-color: var(--tac-blue); }
        /* Compact select variant for secondary rows */
        select.select-sm {
            padding: var(--space-1) var(--space-3);
            font-size: var(--text-sm);
            border-radius: var(--radius-md);
        }
        input[type="text"], input[type="search"] {
            background: var(--card);
            border: 1px solid var(--border);
            color: var(--text);
            padding: var(--space-2) var(--space-3);
            border-radius: var(--radius-lg);
            font-size: var(--text-base);
            font-family: var(--font-ui);
            /* Strip Safari's default search-input styling (rounded, gradient, no border)
               so type="search" inputs match type="text" appearance. The native clear-X
               that shows when the field has content remains visible. */
            -webkit-appearance: none;
            appearance: none;
        }
        input[type="text"]:focus, input[type="search"]:focus { outline: none; border-color: var(--tac-blue); }
        /* Hide WebKit's results decoration but keep the clear button visible */
        input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
        /* Hide native search clear-X — we use our own custom .customer-search-clear
           button so the visual treatment is consistent across all input types
           and browsers. WebKit/Safari/Chrome all render slightly different X
           icons natively, which would clash with our design language. */
        input[type="search"]::-webkit-search-cancel-button {
            -webkit-appearance: none;
            appearance: none;
        }
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
            gap: var(--space-4);
            margin-bottom: var(--space-5);
        }
        .stat-card {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            padding: var(--space-4);
            text-align: center;
            box-shadow: var(--shadow-sm);
        }
        .stat-card .value {
            font-size: var(--text-2xl);
            font-weight: 700;
            margin-bottom: var(--space-1);
            color: var(--text);
        }
        .stat-card .label {
            font-family: var(--font-ui);
            color: var(--text-muted);
            font-size: var(--text-sm);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        .chart-container {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-2xl);
            padding: var(--space-5);
            margin-bottom: var(--space-5);
            box-shadow: var(--shadow-md);
            position: relative;
        }
        /* The chart container reserves space at the top for the view-tabs
           that visually overlap it (positioned absolute, bottom: calc(100%-1px)).
           Originally used :has(.view-tabs) — switched to unconditional margin
           since every chart-container in this app does contain view-tabs, and
           this avoids :has() compatibility gaps on older Safari < 15.4 and
           Firefox < 121. The redundant rule below targets browsers that DO
           support :has() and is harmless elsewhere. */
        .chart-container {
            margin-top: var(--space-6);
        }
        .chart-container:has(.view-tabs) {
            margin-top: var(--space-6);
        }
        .chart-header {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: var(--space-1);
            margin-bottom: var(--space-3);
            padding-bottom: var(--space-3);
            border-bottom: 1px solid var(--border);
        }
        /* V8.1 #4: subhead is its own line below the title group; its edit/reset
           pencils sit at the END of the line (hover-revealed, like the title's). */
        .chart-subhead-row {
            display: flex;
            align-items: center;
            gap: var(--space-1);
            min-width: 0;
        }
        .chart-subhead {
            font-size: 0.82rem;
            font-weight: 400;
            line-height: 1.4;
            color: var(--text-muted);
        }
        .chart-subhead-row .chart-title-btn {
            font-size: var(--text-sm);
            padding: 2px var(--space-1);
        }
        .chart-subhead-row:hover .chart-title-btn {
            opacity: 0.7;
        }
        .data-availability-note {
            margin-bottom: var(--space-3);
            padding: var(--space-2) var(--space-3);
            font-size: var(--text-sm);
            color: var(--text-muted);
            background: var(--bg);
            border-left: 2px solid var(--tac-gold);
            border-radius: var(--radius-xs);
            line-height: 1.4;
            font-style: italic;
        }
        .chart-header h2 {
            font-family: var(--font-ui);
            font-size: var(--text-3xl);
            font-weight: 600;
        }
        .chart-title-group {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            min-width: 0;
        }
        .chart-title-group h2 #chartTitle {
            cursor: default;
        }
        .chart-title-actions {
            display: flex;
            gap: var(--space-1);
            flex-shrink: 0;
        }
        .chart-title-btn {
            background: transparent;
            border: 1px solid transparent;
            color: var(--text-muted);
            font-size: var(--text-base);
            cursor: pointer;
            padding: var(--space-1) var(--space-2);
            border-radius: var(--radius-md);
            line-height: 1;
            opacity: 0.35;
            transition: opacity 0.15s, background 0.15s, border-color 0.15s;
        }
        .chart-title-group:hover .chart-title-btn,
        .chart-title-btn.visible {
            opacity: 0.7;
        }
        .chart-title-btn:hover {
            opacity: 1;
            background: var(--surface-inset);
            border-color: var(--border);
            color: var(--text);
        }
        .chart-title-reset {
            color: var(--tac-blue);
        }
        /* V8.1 #4: tiny text labels on the title/subhead action buttons — "sub"
           distinguishes the subhead pencil; "reset" names the restore-default
           buttons. Scope words gold (=scope), overlay ref italic. */
        .chart-title-btn .csb-lbl {
            font-size: 0.62em;
            font-weight: 700;
            letter-spacing: 0.04em;
            margin-left: 2px;
            vertical-align: 0.1em;
            opacity: 0.85;
        }
        /* A reset with an active override is a real affordance, not hover chrome —
           keep it clearly legible until clicked. */
        .chart-title-reset.visible {
            opacity: 0.85;
        }
        #periodTotal .subhead-scope { color: var(--tac-gold); }
        #periodTotal .subhead-ref { color: var(--text-muted); font-style: italic; }
        /* Controls Row Layout */
        .controls-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: var(--space-4);
            padding: var(--space-3) 0;
            flex-wrap: wrap;
        }
        .controls-row-secondary {
            background: var(--gray-pale);
            margin: 0 -1.5rem;
            padding: var(--space-2) var(--space-5);
            border-top: 1px solid var(--border);
        }
        .controls-row-label {
            font-size: var(--text-sm);
            font-weight: 600;
            font-family: var(--font-ui);
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.3px;
            margin-right: var(--space-3);
        }
        .controls-section {
            display: flex;
            align-items: flex-end;
            gap: var(--space-4);
            flex-wrap: wrap;
        }
        .controls-actions {
            align-items: center;
            gap: var(--space-2);
        }
        .view-tabs {
            position: absolute;
            bottom: calc(100% - 1px);
            left: 1.5rem;
            right: 1.5rem;
            display: flex;
            gap: 0;
            background: transparent;
            padding: 0;
            border-radius: 0;
            z-index: 2;
            /* Chart-view-toggle sits at the LEFT (Manufacturers/Customers).
               The chart-type tabs (Stacked toggle + Area/Bars/Lines/Share %/
               Compare) cluster to the RIGHT, separated by a flex spacer so
               the two groups visually + spatially distinguish their roles. */
            justify-content: flex-start;
            align-items: flex-end;
        }
        .view-tabs .chart-view-toggle {
            /* No special positioning — first child, naturally left-aligned. */
        }
        .view-tabs .view-tabs-spacer {
            flex: 1 1 auto;
            min-width: 1.5rem;
        }
        .view-tab, .chart-view-tab {
            font-family: var(--font-ui);
            padding: var(--space-2) var(--space-3);
            border: 1px solid var(--border);
            border-bottom: none;
            background: var(--card);
            color: var(--text-muted);
            cursor: pointer;
            border-radius: 8px 8px 0 0;
            font-size: var(--text-sm);
            font-weight: 500;
            transition: color 0.15s, background 0.15s;
            margin-left: -1px;
            position: relative;
        }
        .view-tab:first-child, .chart-view-tab:first-child {
            margin-left: 0;
        }
        .view-tab:hover, .chart-view-tab:hover {
            color: var(--text);
            background: var(--surface-inset);
        }
        .view-tab.active, .chart-view-tab.active {
            color: var(--text);
            font-weight: 600;
            background: var(--card);
            z-index: 1;
            box-shadow: none;
        }
        /* ── Bar layout sub-toggle (shown only when Bars view is active) ───
           A pair of pill buttons that switches between stacked vertical bars
           and side-by-side grouped bars. Universal across all Group By
           breakdowns. Sits to the LEFT of the main 5 tabs so the main tab
           positions don't shift when this toggle appears/disappears. */
        .bar-layout-toggle {
            display: none;  /* hidden by default; .visible class toggles in JS */
            align-items: center;
            gap: var(--space-1);
            margin-right: var(--space-2);
            padding-right: var(--space-2);
        }
        .bar-layout-toggle.visible {
            display: inline-flex;
        }
        .bar-layout-divider {
            width: 1px;
            height: 1.1rem;
            background: var(--border);
            margin-left: var(--space-2);
        }
        /* ── Chart View toggle (Manufacturers / Customers) ─────────────────
           Top-level dichotomy at the left of the chart-tab row, separated from
           the Bars/Stacked/Lines tabs by a vertical divider. Always visible —
           unlike bar-layout-toggle which only appears in Bars view. Tabs
           themselves use the existing .view-tab styling so they look identical
           to the chart-type tabs (per design spec — same pill style, opposite
           position). The .chart-view-tab class is reserved for future style
           differentiation if we want to bump prominence later. */
        .chart-view-toggle {
            display: inline-flex;
            align-items: center;
            gap: var(--space-1);
            margin-right: var(--space-2);
            padding-right: var(--space-2);
        }
        .chart-view-divider {
            /* Visually unused now — the flex spacer between chart-view-toggle
               and the chart-type tabs provides the separation. Keeping the
               element in markup so we can re-enable later if needed. */
            display: none;
        }
        .bar-layout-btn {
            font-family: var(--font-ui);
            padding: var(--space-1) var(--space-3);
            border: 1px solid var(--border);
            background: var(--card);
            color: var(--text-muted);
            cursor: pointer;
            border-radius: var(--radius-md);
            font-size: var(--text-xs);
            font-weight: 500;
            transition: color 0.15s, background 0.15s, border-color 0.15s;
            min-height: 28px;
        }
        .bar-layout-btn:hover {
            color: var(--text);
            background: var(--surface-inset);
        }
        .bar-layout-btn.active {
            color: #ffffff;
            background: var(--tac-blue);
            border-color: var(--tac-blue);
            font-weight: 600;
        }
        .chart-wrap { position: relative; height: 520px; cursor: pointer; }
        .chart-branding {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: var(--space-2) 0;
            flex-wrap: wrap;
            gap: var(--space-2);
        }
        .chart-branding a {
            display: flex;
            align-items: center;
            opacity: 0.7;
            transition: opacity 0.2s;
        }
        .chart-branding a:hover {
            opacity: 1;
        }
        .chart-branding img {
            width: 210px;
            height: auto;
            display: block;
        }

        /* External chart tooltip */
        .chart-tooltip {
            position: absolute;
            background: var(--tooltip-bg);
            border: 1px solid var(--tooltip-border);
            box-shadow: var(--tooltip-shadow);
            border-radius: var(--radius-lg);
            color: var(--tooltip-text);
            font-size: var(--text-base);
            padding: 0;
            pointer-events: none;
            transform: translate(-50%, -100%);
            transition: opacity 0.15s ease;
            z-index: 100;
            min-width: 180px;
            max-width: 300px;
            margin-top: -10px;
        }
        .chart-tooltip.frozen {
            pointer-events: auto;
            box-shadow: var(--tooltip-shadow-frozen);
        }

        /* ───── Measurement tool (drag across bars to see % change) ───── */
        /* Subtle translucent gold shade spanning the measured region. Sits
           below everything else so chart bars remain fully readable. */
        .measurement-region {
            position: absolute;
            background: rgba(254, 171, 64, 0.07);
            border-left: 1px dashed rgba(254, 171, 64, 0.35);
            border-right: 1px dashed rgba(254, 171, 64, 0.35);
            pointer-events: none;
            z-index: 6;
        }
        /* Endpoint highlights — short gold caps at the top of each endpoint
           bar, visually integrated with the bracket stems. */
        .measurement-endpoint {
            position: absolute;
            background: rgba(254, 171, 64, 0.22);
            border: 2px solid var(--tac-gold);
            border-radius: var(--radius-xs);
            pointer-events: none;
            z-index: 8;
            box-sizing: border-box;
        }
        /* Two-tap measure: the lone armed anchor pulses to invite the second tap. */
        .measurement-endpoint.measurement-primed {
            background: rgba(254, 171, 64, 0.32);
            z-index: 9;
            animation: mp-primed-pulse 1.1s ease-in-out infinite;
        }
        @keyframes mp-primed-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
        @media (prefers-reduced-motion: reduce) { .measurement-endpoint.measurement-primed { animation: none; } }
        /* "Measuring from <label> — tap another bar [Cancel]" pill over the chart. */
        .mp-prime-hint {
            position: absolute;
            top: 8px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 12;
            display: inline-flex;
            align-items: center;
            gap: 10px;
            padding: 6px 8px 6px 14px;
            background: rgba(20, 24, 31, 0.94);
            border: 1px solid var(--tac-gold);
            border-radius: 2px;
            color: #fff;
            font-family: 'Archivo', system-ui, sans-serif;
            font-size: 12px;
            white-space: nowrap;
            box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
            pointer-events: auto;
            max-width: calc(100% - 24px);
        }
        .mp-prime-hint b { color: var(--tac-gold); font-weight: 700; }
        .mp-prime-cancel {
            background: rgba(255, 255, 255, 0.14);
            border: none;
            color: #fff;
            font-family: 'Archivo', system-ui, sans-serif;
            font-size: 11px;
            font-weight: 600;
            padding: 3px 11px;
            border-radius: 2px;
            cursor: pointer;
        }
        .mp-prime-cancel:hover { background: rgba(255, 255, 255, 0.24); }
        /* Touch: grow the pill's Cancel to a finger-friendly target. */
        @media (pointer: coarse) {
            .mp-prime-cancel { min-height: 38px; padding: 0 16px; }
        }
        /* Leveled bracket — horizontal cap plus two vertical stems dropping
           to each endpoint. Built from three absolutely-positioned rectangles
           rather than SVG since the chart wrap is already DOM-positioned. */
        .measurement-bracket-cap {
            position: absolute;
            height: 2px;
            background: var(--tac-gold);
            pointer-events: none;
            z-index: 9;
        }
        .measurement-bracket-stem {
            position: absolute;
            width: 2px;
            background: var(--tac-gold);
            pointer-events: none;
            z-index: 9;
        }
        /* Floating panel showing the measurement values. Positioned above
           the midpoint of the bracket cap. */
        .measurement-panel {
            position: absolute;
            background: var(--card);
            border: 1px solid var(--tac-gold);
            border-radius: var(--radius-md);
            padding: var(--space-2) var(--space-3);
            font-family: var(--font-ui);
            font-size: var(--text-base);
            line-height: 1.35;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            pointer-events: auto;
            z-index: 12;
            white-space: nowrap;
            transform: translate(-50%, -100%);
            margin-top: -8px;  /* gap between panel and bracket cap */
        }
        .measurement-panel .mp-endpoints {
            color: var(--text-muted);
            font-size: var(--text-sm);
            text-transform: uppercase;
            letter-spacing: 0.3px;
            margin-bottom: var(--space-1);
        }
        .measurement-panel .mp-delta {
            font-weight: 700;
            color: var(--text);
        }
        .measurement-panel .mp-delta.positive { color: var(--positive); }
        .measurement-panel .mp-delta.negative { color: var(--negative); }
        /* Wave D Build 18 (xd): inclusive range-total row — sum of every bar
           across the measured span. Divider above separates the cumulative
           figure from the endpoint comparison above it. */
        .measurement-panel .mp-range-total {
            margin-top: var(--space-1);
            padding-top: var(--space-1);
            border-top: 1px solid var(--border-subtle, rgba(128,128,128,0.25));
            font-size: var(--text-sm);
        }
        .measurement-panel .mp-rt-label {
            color: var(--text-muted);
        }
        .measurement-panel .mp-rt-value {
            font-weight: 700;
            color: var(--text);
        }
        .measurement-panel .mp-close {
            position: absolute;
            top: 2px;
            right: 4px;
            background: transparent;
            border: none;
            color: var(--text-muted);
            cursor: pointer;
            font-size: var(--text-md);
            line-height: 1;
            padding: 2px var(--space-1);
            border-radius: var(--radius-xs);
        }
        .measurement-panel .mp-close:hover {
            color: var(--text);
            background: var(--gray-pale);
        }
        /* When in measurement mode, subtly indicate we're measuring */
        .chart-wrap.measuring { cursor: ew-resize; }
        .tooltip-content {
            padding: 0;
        }
        .tooltip-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: var(--space-3) var(--space-3);
            font-weight: 700;
            font-size: var(--text-md);
            border-bottom: 1px solid var(--tooltip-border);
            background: var(--tooltip-tier-bg);
            border-radius: 6px 6px 0 0;
        }
        .tooltip-close {
            background: none;
            border: none;
            color: var(--tooltip-muted);
            font-size: var(--text-lg);
            cursor: pointer;
            padding: 0;
            margin-left: var(--space-2);
            line-height: 1;
        }
        .tooltip-close:hover {
            color: var(--tooltip-text);
        }
        .tooltip-body {
            padding: var(--space-2) 0;
            max-height: 350px;
            overflow-y: auto;
        }
        /* Three-tier tooltip structure */
        .tooltip-tier {
            display: flex;
            align-items: center;
            padding: var(--space-1) var(--space-3);
            gap: var(--space-2);
        }
        .tooltip-tier.tier-1 {
            background: var(--tooltip-tier-bg);
            font-weight: 700;
            font-size: var(--text-base);
            padding: var(--space-2) var(--space-3);
            border-bottom: 1px solid var(--tooltip-border);
        }
        .tooltip-tier.tier-2 {
            font-weight: 600;
            padding: var(--space-2) var(--space-3);
            margin-top: var(--space-1);
        }
        .tooltip-tier.tier-3 {
            padding-left: var(--space-5);
            font-size: var(--text-sm);
            color: var(--tooltip-muted);
        }
        .tooltip-tier.tier-3.clicked {
            background: var(--tooltip-tier-bg);
            border-left: 2px solid var(--tac-blue);
            padding-left: calc(1.5rem - 2px);
        }
        /* Build 20260508zg: cell-aware hover for customer-as-segment cells.
           Compact list on hover; when frozen (click) it scrolls through every
           customer in the bar. .chart-tooltip.frozen already enables pointer
           events, so the scroll + close are reachable only when pinned. */
        .chart-tooltip .v8x-tt-list {
            display: flex;
            flex-direction: column;
            padding: 4px 0;
        }
        .chart-tooltip .v8x-tt-list.frozen {
            max-height: 300px;
            overflow-y: auto;
        }
        .chart-tooltip .v8x-tt-row {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 3px 12px;
            font-size: var(--text-sm);
        }
        .chart-tooltip .v8x-tt-name {
            flex: 1;
            min-width: 0;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        /* Build 20260508zi: size the customer hover to its content, capped at the
           97th-percentile operator-name width (set inline via _custTooltipMaxWidth).
           Short lists shrink narrow; the longest 3% ellipsize at the cap. */
        .chart-tooltip.v8x-cust-tt {
            width: fit-content;
            min-width: 200px;
            /* Build 20260508zr: side-anchored (positioned beside the bar via
               _positionV8Tooltip with explicit top-left), so drop the base
               center-above transform + negative margin. */
            transform: none;
            margin-top: 0;
        }
        .chart-tooltip .v8x-tt-val {
            font-weight: 600;
            font-variant-numeric: tabular-nums;
        }
        .chart-tooltip .v8x-tt-pct {
            width: 36px;
            text-align: right;
            color: var(--tooltip-muted);
            font-variant-numeric: tabular-nums;
        }
        /* Build 20260508zh: mockup-form header, dim chip, hovered-row ring, footer */
        .chart-tooltip .v8x-tt-head { align-items: flex-start; }
        .chart-tooltip .v8x-tt-htext { flex: 1; min-width: 0; }
        .chart-tooltip .v8x-tt-title {
            font-size: var(--text-lg);
            font-weight: 700;
            line-height: 1.2;
        }
        .chart-tooltip .v8x-tt-sub {
            font-size: var(--text-sm);
            font-weight: 400;
            color: var(--tooltip-muted);
            margin-top: 3px;
        }
        .chart-tooltip .v8x-tt-row.ring {
            outline: 1.5px solid var(--tac-gold);
            outline-offset: -1px;
            border-radius: 2px;
            background: var(--tooltip-ring-bg);
        }
        .chart-tooltip .v8x-tt-rest { color: var(--tooltip-muted); }
        .chart-tooltip .v8x-tt-foot {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 12px;
            padding: 8px 12px;
            border-top: 1px solid var(--tooltip-border);
            background: var(--tooltip-tier-bg);
            border-radius: 0 0 6px 6px;
            font-size: var(--text-xs);
        }
        .chart-tooltip .v8x-tt-undis { color: var(--tooltip-muted); }
        .chart-tooltip .v8x-tt-undis .ti { color: var(--tooltip-ink-gold); }
        /* Economic-overlay reference line in the next-gen hover — context only
           (never in the drilldown). Dashed chip mirrors the Historical Data swatch. */
        .chart-tooltip .v8x-tt-econ {
            display: flex;
            align-items: center;
            gap: 7px;
            padding: 6px 12px;
            border-top: 1px dashed var(--tooltip-border);
            font-size: var(--text-xs);
            color: var(--tooltip-muted);
        }
        .chart-tooltip .v8x-tt-econ-chip {
            width: 16px;
            height: 3px;
            border-radius: 2px;
            flex-shrink: 0;
            background-image: repeating-linear-gradient(90deg, currentColor 0 5px, transparent 5px 8px);
        }
        .chart-tooltip .v8x-tt-econ-name { font-weight: 600; }
        .chart-tooltip .v8x-tt-econ-val {
            margin-left: auto;
            font-variant-numeric: tabular-nums;
            color: var(--tooltip-text);
            font-weight: 600;
        }
        /* Crack spread row: the computed gap, emphasized below the two series rows. */
        .chart-tooltip .v8x-tt-econ-spread { border-top-style: solid; }
        .chart-tooltip .v8x-tt-econ-spread .v8x-tt-econ-name,
        .chart-tooltip .v8x-tt-econ-spread .v8x-tt-econ-val { color: var(--tooltip-text); }
        .chart-tooltip .v8x-tt-econ-spread .v8x-tt-econ-chip {
            background-image: none;
            background: currentColor;
            height: 8px;
            width: 8px;
            border-radius: 2px;
        }
        .chart-tooltip .v8x-tt-drill {
            color: var(--tooltip-ink-accent);
            white-space: nowrap;
            cursor: pointer;
        }
        /* Two-tap measure: the CTAs group on the right (wrap on narrow mobile tooltips);
           "Measure from here" is gold to echo the measurement bracket. */
        .chart-tooltip .v8x-tt-ctas {
            display: inline-flex;
            align-items: center;
            gap: 12px;
            flex-wrap: wrap;
            justify-content: flex-end;
        }
        .chart-tooltip .v8x-tt-measure {
            color: var(--tooltip-ink-gold);
            white-space: nowrap;
            cursor: pointer;
            font-weight: 600;
        }
        .chart-tooltip .v8x-tt-measure:hover { filter: brightness(1.12); }
        /* Touch: the frozen-tooltip CTAs are the only tap targets on mobile, so grow
           them to the ~44px finger-target guideline (desktop mouse stays compact).
           Tighter footer padding + gap keeps both CTAs on one line at 375px. */
        @media (pointer: coarse) {
            .chart-tooltip .v8x-tt-foot { padding: 2px 10px; }
            .chart-tooltip .v8x-tt-ctas { gap: 4px; }
            .chart-tooltip .v8x-tt-measure,
            .chart-tooltip .v8x-tt-drill {
                display: inline-flex;
                align-items: center;
                min-height: 44px;
                padding: 0 8px;
            }
        }
        /* Build 20260508zu: in-tooltip relocation controls (left/center/right).
           CSS-drawn mini "dock position" indicators — a framed box with a bar
           pinned to the chosen side. Interactive only when the tooltip is frozen. */
        .chart-tooltip .v8x-tt-dock {
            display: inline-flex;
            gap: 3px;
            align-items: center;
            margin-left: 8px;
        }
        .chart-tooltip .v8x-tt-dock-btn {
            width: 20px;
            height: 14px;
            padding: 0;
            box-sizing: border-box;
            border: 1px solid var(--tooltip-border);
            border-radius: 2px;
            background: transparent;
            cursor: pointer;
            position: relative;
        }
        .chart-tooltip .v8x-tt-dock-btn::after {
            content: '';
            position: absolute;
            top: 2px;
            bottom: 2px;
            width: 4px;
            border-radius: 1px;
            background: var(--tooltip-muted);
        }
        .chart-tooltip .v8x-tt-dock-btn[data-dock="left"]::after { left: 2px; }
        .chart-tooltip .v8x-tt-dock-btn[data-dock="center"]::after { left: 50%; transform: translateX(-50%); }
        .chart-tooltip .v8x-tt-dock-btn[data-dock="right"]::after { right: 2px; }
        .chart-tooltip .v8x-tt-dock-btn:hover { border-color: var(--tac-blue); }
        .chart-tooltip .v8x-tt-dock-btn.active { border-color: var(--tac-blue); }
        .chart-tooltip .v8x-tt-dock-btn.active::after { background: var(--tac-blue); }
        .tier-label {
            flex: 1;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .tier-value {
            font-weight: 600;
            margin-left: auto;
            font-variant-numeric: tabular-nums;
        }
        .tooltip-color {
            width: 10px;
            height: 10px;
            border-radius: var(--radius-xs);
            flex-shrink: 0;
        }
        /* Build 20260508ye: recolor swatch inside the persistent tooltip
           (time:country). Combines .tooltip-color sizing with the global
           button.legend-color-btn chrome (chrome reset + hover ring + badge
           anchor). box-sizing keeps the 10px box exact against UA button
           styles; clickable only while the tooltip is .frozen. */
        button.tooltip-color.legend-color-btn {
            box-sizing: border-box;
            display: inline-block;
        }
        .tooltip-footer {
            padding: var(--space-2) var(--space-3);
            border-top: 1px solid var(--tooltip-border);
            background: var(--tooltip-tier-bg);
            border-radius: 0 0 6px 6px;
        }
        .tooltip-explore-btn {
            width: 100%;
            background: var(--tac-blue);
            color: white;
            border: none;
            padding: var(--space-2) var(--space-3);
            border-radius: var(--radius-md);
            font-size: var(--text-base);
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s, filter 0.15s;
        }
        .tooltip-explore-btn:hover {
            filter: brightness(0.85);
        }

        /* Dual-handle year range slider */
        .year-range-container {
            display: flex;
            align-items: center;
            gap: var(--space-4);
            padding: var(--space-3) var(--space-4);
            background: var(--bg);
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            margin-top: var(--space-3);
        }
        .year-range-label {
            font-size: var(--text-sm);
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            white-space: nowrap;
        }
        .year-range-slider {
            flex: 1;
            position: relative;
            height: 24px;
            -webkit-user-select: none;
            user-select: none;
        }
        .year-range-track {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            left: 0;
            right: 0;
            height: 6px;
            background: var(--gray-pale);
            border-radius: var(--radius-sm);
        }
        .year-range-selected {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            height: 6px;
            background: var(--tac-blue);
            border-radius: var(--radius-sm);
            cursor: grab;
            z-index: 1;
        }
        .year-range-selected::before {
            content: '';
            position: absolute;
            top: -10px;
            bottom: -10px;
            left: 0;
            right: 0;
        }
        .year-range-selected.dragging {
            cursor: grabbing;
        }
        .year-range-thumb {
            position: absolute;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 18px;
            height: 18px;
            background: var(--card);
            border: 2px solid var(--tac-blue);
            border-radius: 50%;
            cursor: pointer;
            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
            /* Only transition box-shadow. Transform must be instant —
               any transform transition fights drag motion and causes
               visible wobble/flicker when hover/drag states change. */
            transition: box-shadow 0.1s;
            z-index: 10;
        }
        /* Hover only applies when NOT dragging. Prevents hover/drag state
           collisions where the thumb's scale would oscillate as the cursor
           briefly leaves the (moving) thumb's hit area during fast drags. */
        .year-range-thumb:not(.dragging):hover {
            transform: translate(-50%, -50%) scale(1.1);
            box-shadow: 0 2px 6px rgba(0,0,0,0.25);
        }
        .year-range-thumb.dragging {
            transform: translate(-50%, -50%) scale(1.15);
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
        }
        /* While ANY thumb is being dragged, the sibling thumb ignores pointer
           events so its hover state can't flicker underneath. */
        .year-range-slider.any-dragging .year-range-thumb:not(.dragging) {
            pointer-events: none;
        }

        /* Single-year mode — only the max thumb is visible and active.
           Min thumb and selected-track are hidden; the single visible thumb
           represents the selected year. Much cleaner than the old single-
           year-via-overlapping-thumbs model. */
        .year-range-slider.single-mode #yearThumbMin,
        .year-range-slider.single-mode #yearRangeSelected {
            display: none;
        }
        /* In single mode, hide the separator, max select, and the wrapper
           that contains the max select (otherwise the wrapper's ::after
           chevron remains visible even though the select is hidden).
           Originally used :has(#yearRangeMaxDisplay) — switched to a direct
           ID on the wrapper for broader browser compat. */
        .year-range-values.single-mode #yearRangeSeparator,
        .year-range-values.single-mode #yearRangeMaxDisplay,
        .year-range-values.single-mode #yearRangeMaxWrap {
            display: none;
        }

        /* Mode toggle — segmented control to switch between Range and Single */
        .year-range-mode-toggle {
            display: inline-flex;
            border: 1px solid var(--border);
            border-radius: var(--radius-md);
            overflow: hidden;
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            white-space: nowrap;
        }
        .year-mode-btn {
            padding: var(--space-1) var(--space-3);
            background: transparent;
            color: var(--text-muted);
            border: none;
            cursor: pointer;
            transition: background 0.12s, color 0.12s;
            font: inherit;
        }
        .year-mode-btn:hover:not(.active) {
            color: var(--text);
            background: var(--gray-pale);
        }
        .year-mode-btn.active {
            background: var(--tac-blue);
            color: white;
        }
        .year-mode-btn + .year-mode-btn {
            border-left: 1px solid var(--border);
        }
        .year-range-values {
            display: flex;
            gap: var(--space-1);
            align-items: center;
            font-family: var(--font-ui);
            font-size: var(--text-base);
            font-weight: 600;
            color: var(--tac-blue);
            white-space: nowrap;
        }
        .year-range-values > span:not(.year-select-wrap) {
            min-width: 3ch;
            text-align: center;
        }
        /* Year picker — native <select> styled as interactive text.
           Single-click/tap opens the native year picker: wheel on iOS,
           dropdown on Android, dropdown on desktop. Small chevron on the
           wrapper hints at interactivity without taking much space. */
        .year-select-wrap {
            position: relative;
            display: inline-flex;
            align-items: center;
            padding: var(--space-1) var(--space-3) var(--space-1) var(--space-1);
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: background 0.12s, box-shadow 0.12s;
        }
        .year-select-wrap:hover {
            background: var(--gray-pale);
        }
        .year-select-wrap:focus-within {
            background: var(--gray-pale);
            box-shadow: 0 0 0 2px var(--tac-blue);
        }
        /* The wrapper's :focus-within box-shadow IS the year picker's focus ring.
           Suppress the <select>'s own :focus-visible outline (the generic
           #v8-ui select:focus-visible rule) so the two don't stack into a doubled
           box on click. Higher specificity to beat that id-scoped rule. (Jon 2026-07-13) */
        #v8-ui .year-range-values select:focus,
        #v8-ui .year-range-values select:focus-visible {
            outline: none;
        }
        .year-select-wrap::after {
            /* Chevron indicating dropdown affordance */
            content: '';
            position: absolute;
            right: 0.3rem;
            top: 50%;
            width: 0;
            height: 0;
            border-left: 3.5px solid transparent;
            border-right: 3.5px solid transparent;
            border-top: 4px solid var(--tac-blue);
            transform: translateY(-50%);
            pointer-events: none;
            opacity: 0.7;
        }
        .year-range-values select {
            /* Strip native appearance so the <select> looks like text */
            appearance: none;
            -webkit-appearance: none;
            -moz-appearance: none;
            background: transparent;
            border: none;
            padding: 0;
            margin: 0;
            font: inherit;
            color: inherit;
            cursor: pointer;
            min-width: 3ch;
            text-align: center;
            text-align-last: center;  /* Safari/Chrome — centers selected option */
            outline: none;
        }
        .year-range-values select::-ms-expand {
            display: none;  /* IE/Edge legacy */
        }

        .reset-zoom-btn {
            font-family: var(--font-ui);
            background: var(--gray-pale);
            color: var(--text);
            border: none;
            padding: var(--space-1) var(--space-3);
            border-radius: var(--radius-md);
            font-size: var(--text-sm);
            cursor: pointer;
            margin-left: var(--space-2);
            display: none;
        }
        .reset-zoom-btn:hover { background: var(--gray-light); }
        .reset-zoom-btn.visible { display: inline-block; }
        .export-btn {
            font-family: var(--font-ui);
            background: var(--tac-blue);
            color: white;
            border: none;
            padding: var(--space-1) var(--space-3);
            border-radius: var(--radius-md);
            font-size: var(--text-sm);
            cursor: pointer;
            margin-left: var(--space-2);
            font-weight: 500;
        }
        .export-btn:hover { filter: brightness(0.9); }
        .toggle-switch {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            cursor: pointer;
            margin-left: var(--space-2);
        }
        .toggle-switch input {
            display: none;
        }
        .toggle-slider {
            width: 36px;
            height: 20px;
            background: var(--gray-pale);
            border-radius: 6px;
            position: relative;
            transition: background 0.2s;
        }
        .toggle-slider::after {
            content: '';
            position: absolute;
            top: 2px;
            left: 2px;
            width: 16px;
            height: 16px;
            background: white;
            border-radius: 50%;
            transition: transform 0.2s;
            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        }
        .toggle-switch input:checked + .toggle-slider {
            background: var(--tac-blue);
        }
        .toggle-switch input:checked + .toggle-slider::after {
            transform: translateX(16px);
        }
        .toggle-label {
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            color: var(--text-muted);
            font-weight: 500;
        }
        .table-container {
            overflow-x: auto;
            max-height: 500px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            font-size: var(--text-base);
        }
        th, td {
            padding: var(--space-3) var(--space-3);
            text-align: left;
            border-bottom: 1px solid var(--border);
        }
        th {
            font-family: var(--font-ui);
            background: var(--bg);
            position: -webkit-sticky;
            position: sticky;
            top: 0;
            color: var(--text-muted);
            font-weight: 600;
            text-transform: uppercase;
            font-size: var(--text-xs);
            letter-spacing: 0.5px;
        }
        tr:hover { background: rgba(30, 144, 255, 0.06); }
        .mfr-badge {
            display: inline-block;
            padding: var(--space-1) var(--space-2);
            border-radius: var(--radius-md);
            font-size: var(--text-xs);
            font-weight: 600;
            color: #ffffff;
        }
        .footer {
            text-align: center;
            padding-top: var(--space-5);
            border-top: 1px solid var(--border);
            color: var(--text-muted);
            font-size: var(--text-base);
        }
        .update-instructions {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            padding: var(--space-4);
            margin-top: var(--space-4);
            font-size: var(--text-base);
        }
        .update-instructions summary {
            cursor: pointer;
            color: var(--tac-blue);
            font-weight: 500;
        }
        .update-instructions pre {
            background: var(--bg);
            padding: var(--space-3);
            border-radius: var(--radius-md);
            overflow-x: auto;
            margin-top: var(--space-2);
            font-size: var(--text-sm);
            border: 1px solid var(--border);
        }
        /* ── WELCOME SCREEN (2026-10-09, Jon) — the first-load popup: masthead · title · subhead · welcome
           text · sources + "Explore the data" · the coverage matrix · partial-year line. ONE measure: the
           matrix's 660px right edge bounds every block, the button included. Theme tokens throughout. ── */
        .welcome-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0, 0, 0, 0.55);
            backdrop-filter: blur(2px);
            z-index: 9100;
            display: flex;
            align-items: flex-start;
            justify-content: center;
            overflow-y: auto;
            padding: max(24px, 4vh) 16px 40px;
        }
        .welcome-overlay[hidden] { display: none; }
        body.welcome-open { overflow: hidden; }
        .welcome-card {
            position: relative;
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            box-shadow: var(--shadow-lg);
            padding: clamp(20px, 3vw, 36px);
            width: min(100%, 760px);
            font-family: var(--font-ui);
            color: var(--text);
            text-align: left;
        }
        .welcome-card > * { max-width: 660px; }
        .welcome-close {
            position: absolute; top: 12px; right: 12px; width: 32px; height: 32px;
            border: 0; border-radius: 50%; background: transparent; color: var(--text-muted);
            font-family: var(--font-ui); font-size: 18px; line-height: 1; cursor: pointer;
            display: inline-flex; align-items: center; justify-content: center; max-width: none;
        }
        .welcome-close:hover { color: var(--text); background: var(--bg); }
        .welcome-close:focus-visible { outline: 2px solid var(--tac-gold); outline-offset: 2px; color: var(--text); }
        .welcome-masthead { margin-bottom: var(--space-3); }
        .welcome-title {
            font-family: var(--font-ui); font-size: var(--text-3xl); font-weight: 700;
            margin: 0 0 var(--space-2); color: var(--text); letter-spacing: -0.016em; line-height: 1.1;
        }
        .welcome-lede { font-family: 'Source Serif 4', Georgia, serif; font-size: 17px; line-height: 1.4; color: var(--text-muted); margin: 0 0 var(--space-3); }
        .welcome-lede span { color: var(--text); font-weight: 600; }
        .welcome-text p { margin: 0 0 10px; font-size: 14.5px; line-height: 1.55; color: var(--text); }
        .welcome-text a { color: var(--tac-blue); text-decoration: underline; text-underline-offset: 2px; }
        .welcome-text a:hover { color: var(--text); }
        .welcome-sources-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; margin-top: 12px; }
        .welcome-sources { margin: 0 !important; font-size: var(--text-base) !important; color: var(--text-muted) !important; }
        .welcome-sources b { color: var(--text); font-weight: 600; }
        .welcome-btn {
            font-family: var(--font-ui); font-weight: 600; font-size: 14px; color: #fff; background: var(--tac-blue);
            border: 0; border-radius: var(--radius-md); padding: 10px 18px; cursor: pointer;
        }
        .welcome-btn:hover { filter: brightness(1.08); }
        .welcome-btn:focus-visible { outline: 3px solid var(--tac-gold); outline-offset: 2px; }
        .welcome-h2 { font-family: var(--font-ui); font-size: var(--text-xs); letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted); font-weight: 600; margin: 22px 0 8px; }
        .welcome-legend { display: flex; flex-wrap: wrap; gap: 10px 20px; font-size: var(--text-sm); color: var(--text-muted); margin: 0 0 10px; }
        .welcome-legend span { display: inline-flex; align-items: center; gap: 7px; }
        .wl-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; border: 2px solid var(--tac-blue); background: var(--tac-blue); flex: none; vertical-align: -1px; }
        .wl-dot.part { background: linear-gradient(90deg, var(--tac-gold) 50%, transparent 50%); border-color: var(--tac-gold); }
        .wl-dot.none { background: transparent; border-color: var(--gray-light); }
        .welcome-matrix { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg); max-width: 660px; }
        .welcome-matrix table { border-collapse: collapse; width: 100%; font-size: 12.5px; }
        .welcome-matrix th, .welcome-matrix td { padding: 6px 9px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
        .welcome-matrix thead th { font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); font-weight: 600; }
        .welcome-matrix th.c, .welcome-matrix td.c { text-align: center; }
        .welcome-matrix tbody tr:last-child td { border-bottom: 0; }
        .welcome-matrix td.mfr { font-weight: 600; white-space: nowrap; color: var(--text); }
        .welcome-matrix td.mfr .sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 7px; vertical-align: -1px; }
        .welcome-matrix td.years { font-family: var(--font-ui); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text); }
        .welcome-matrix td.c small { display: block; font-size: 10.5px; line-height: 1.2; color: var(--text-muted); margin: 2px auto 0; max-width: 9em; }
        .welcome-foot { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--border); font-size: var(--text-sm); color: var(--text-muted); }
        .footer .welcome-open { color: var(--tac-blue); text-decoration: none; }
        .footer .welcome-open:hover { text-decoration: underline; }
        @media (max-width: 560px) { .welcome-title { font-size: var(--text-2xl); } .welcome-text p { font-size: 14px; } }
        @media (prefers-reduced-motion: no-preference) { .welcome-btn { transition: filter .15s; } }
        /* Known Issues (2026-10-09, Jon): the scope-and-limits cards from the welcome-screen prototype —
           one per manufacturer, left-justified inside the centred footer, three-up when there is room. */
        .update-instructions .known-issues {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
            gap: var(--space-2);
            margin: var(--space-4) 0 0;
            text-align: left;
        }
        .update-instructions .known-issues article {
            background: var(--bg);
            border: 1px solid var(--border);
            border-radius: var(--radius-md);
            padding: var(--space-3);
            min-width: 0;
        }
        .update-instructions .known-issues h3 {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            margin: 0 0 var(--space-1);
            font-family: var(--font-ui);
            font-size: var(--text-base);
            font-weight: 600;
            color: var(--text);
        }
        .update-instructions .known-issues h3 .sw { width: 10px; height: 10px; border-radius: 2px; flex: none; }
        .update-instructions .known-issues h3 .yrs { margin-left: auto; font-family: var(--font-ui); font-weight: 400; font-size: var(--text-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
        .update-instructions .known-issues p {
            margin: 0 0 var(--space-1);
            font-size: var(--text-sm);
            line-height: 1.45;
            color: var(--text);
        }
        .update-instructions .known-issues p:last-child { margin-bottom: 0; }
        .update-instructions .known-issues p.lim { color: var(--text-muted); }
        .update-instructions .known-issues p.lim b { color: var(--tac-gold); font-weight: 600; }
        .update-instructions .known-issues-future {
            margin: var(--space-3) 0 0;
            text-align: left;
            font-size: var(--text-sm);
            line-height: 1.45;
            color: var(--text-muted);
            font-style: italic;
        }
        /* Chart legend for export */
        .chart-legend {
            display: flex;
            flex-wrap: wrap;
            /* Legend always left-justified as a block. Overrides all other
               alignment guidance — flat and grouped layouts treat the legend
               as a single left-aligned content block. */
            justify-content: flex-start;
            gap: var(--space-4);
            padding: var(--space-2) var(--space-4);
            margin-bottom: var(--space-2);
            background: var(--card);
        }
        .chart-legend:empty {
            display: none;
        }
        /* Wave D Build 15 (ws): Interactive Legend Phase 1 styling.
           .legend-clickable    — pointer cursor + subtle hover affordance for
                                  rows that the delegated click handler will
                                  honor. Compare-view and customer color-picker
                                  rows don't carry the class, so they stay
                                  display-only as before.
           .user-hidden         — user clicked this legend row. Visually
                                  distinct from .inactive (which is data-driven
                                  "this segment has zero records given the
                                  current filters"). Both can apply; the strike-
                                  through is the clearest signal. */
        .chart-legend .legend-item.legend-clickable {
            cursor: pointer;
            user-select: none;
            border-radius: 2px;
            padding: 1px 3px;
            margin: -1px -3px;
            transition: background-color 80ms;
        }
        .chart-legend .legend-item.legend-clickable:hover {
            background-color: rgba(255,255,255,0.06);
        }
        .chart-legend .legend-item.user-hidden {
            opacity: 0.45;
            text-decoration: line-through;
            text-decoration-thickness: 1px;
        }
        .chart-legend .legend-item.user-hidden .legend-color {
            opacity: 0.6;
        }
        /* Wave D Build 17 (xb, 2026-05-26): group headers are clickable for
           cascade toggle (single-click) and cascade isolate (double-click).
           When every child under a header is user-hidden, the header itself
           gets a strikethrough + dimmed treatment to mirror the .user-hidden
           styling on item rows — visually consistent and self-explanatory. */
        .chart-legend .legend-mfr-header.legend-clickable,
        .chart-legend .legend-family-label.legend-clickable {
            cursor: pointer;
            user-select: none;
            border-radius: 2px;
            padding: 1px 4px;
            margin: -1px -4px;
            transition: background-color 80ms, filter 80ms;
        }
        .chart-legend .legend-mfr-header.legend-clickable:hover,
        .chart-legend .legend-family-label.legend-clickable:hover {
            background-color: rgba(255,255,255,0.06);
        }
        .chart-legend .legend-mfr-header.all-children-hidden,
        .chart-legend .legend-family-label.all-children-hidden {
            opacity: 0.45;
            text-decoration: line-through;
            text-decoration-thickness: 1px;
        }
        .chart-legend.legend-grouped {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2) var(--space-5);
            justify-content: flex-start;
        }
        .legend-mfr-column {
            display: flex;
            flex-direction: column;
            gap: var(--space-1);
        }
        .legend-mfr-header {
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.3px;
            color: var(--text-muted);
            padding-bottom: var(--space-1);
            border-bottom: 2px solid var(--border);
            margin-bottom: var(--space-1);
        }
        .legend-family-group {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-1) var(--space-3);
            margin-bottom: var(--space-1);
        }
        .legend-family-label {
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 600;
            color: var(--text-muted);
            width: 100%;
        }
        .legend-subcols {
            display: flex;
            gap: var(--space-3);
        }
        .legend-subcol {
            display: flex;
            flex-direction: column;
            gap: var(--space-1);
        }
        .legend-item {
            display: inline-flex;
            align-items: center;
            gap: var(--space-2);
            font-size: var(--text-sm);
            font-weight: 500;
            color: var(--text);
        }
        .legend-color {
            width: 14px;
            height: 14px;
            border-radius: var(--radius-sm);
            flex-shrink: 0;
        }
        /* Build 20260508xq: recolor affordance. The swatch becomes a button on
           recolorable leaf rows. Reset native button chrome so it looks like
           the old swatch, then add an interactive hover ring + a custom-set
           badge. Position relative so the badge can sit at the corner. */
        button.legend-color-btn {
            padding: 0;
            border: none;
            cursor: pointer;
            position: relative;
            transition: box-shadow 120ms ease, transform 120ms ease;
            -webkit-appearance: none;
            appearance: none;
        }
        button.legend-color-btn:hover {
            box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
            transform: scale(1.12);
        }
        button.legend-color-btn:focus-visible {
            outline: 2px solid var(--v8-accent-x, #1870ff);
            outline-offset: 2px;
        }
        .legend-color-badge {
            position: absolute;
            top: -3px;
            right: -3px;
            width: 6px;
            height: 6px;
            border-radius: 50%;
            background: var(--v8-accent-segment, #feab40);
            border: 1px solid var(--v8-surface-section, #161b22);
            pointer-events: none;
        }
        .legend-item.inactive {
            opacity: 0.4;
        }
        /* Item toggle panel */
        .item-toggles {
            background: var(--bg);
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            padding: var(--space-3);
            margin-bottom: var(--space-3);
        }
        .toggle-container {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
        }
        .category-quick-select {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            padding-bottom: var(--space-3);
            margin-bottom: var(--space-3);
            border-bottom: 1px solid var(--border);
            flex-wrap: wrap;
        }
        .category-qs-label {
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.3px;
            margin-right: var(--space-1);
        }
        .category-qs-btn {
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 500;
            padding: var(--space-1) var(--space-3);
            border: 1px solid var(--border);
            border-radius: var(--radius-md);
            background: var(--card);
            color: var(--text-muted);
            cursor: pointer;
            transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s, filter 0.15s;
        }
        .category-qs-btn:hover {
            border-color: var(--tac-blue);
            color: var(--tac-blue);
        }
        .category-qs-btn.active {
            background: var(--tac-blue);
            color: white;
            border-color: var(--tac-blue);
        }
        .toggle-chip {
            display: inline-flex;
            align-items: center;
            gap: var(--space-2);
            padding: var(--space-1) var(--space-3);
            border-radius: var(--radius-md);
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            cursor: pointer;
            border: 1px solid var(--border);
            background: var(--card);
            color: var(--text);
            transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s, filter 0.15s;
            -webkit-user-select: none;
            user-select: none;
        }
        .toggle-chip:hover {
            background: var(--surface-hover);
            border-color: var(--gray-light);
        }
        .toggle-chip.inactive {
            background: var(--surface-inset);
            color: var(--text-muted);
            border-color: var(--border);
        }
        .toggle-chip .chip-color {
            width: 12px;
            height: 12px;
            border-radius: var(--radius-xs);
            flex-shrink: 0;
        }
        /* Build 20260508yc: the left color square is now the interactive color
           control (single indicator per chip). Reset native button chrome,
           add a hover ring, and position relative so the custom badge sits at
           the corner. */
        button.chip-color-btn {
            padding: 0;
            border: none;
            cursor: pointer;
            position: relative;
            transition: transform 0.12s, box-shadow 0.12s;
            -webkit-appearance: none;
            appearance: none;
        }
        button.chip-color-btn:hover {
            transform: scale(1.15);
            box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18);
        }
        button.chip-color-btn:focus-visible {
            outline: 2px solid var(--tac-blue);
            outline-offset: 2px;
        }
        .toggle-chip.inactive .chip-color {
            opacity: 0.4;
        }
        /* ── Empty-chip-row note (Customer View) ────────────────────────
           Inline message shown in the segmentation chip row when no
           records match the customer-scoped + active-chip filters.
           Replaces the chips with an italic muted note. */
        .empty-chip-note {
            font-style: italic;
            color: var(--text-muted);
            padding: var(--space-2) var(--space-3);
            font-size: var(--text-base);
        }
        /* ── Filter-hidden chip ────────────────────────────────────────
           Applied to the static manufacturer chip strip in #mfrChips when
           the customer-bar filter combination would produce zero matching
           records for that manufacturer. Distinct from `.inactive` (which
           represents the user's chip-toggle state — preserved across
           hide/show via this class). When .filter-hidden is removed, the
           chip's prior active/inactive state is restored automatically. */
        .toggle-chip.filter-hidden {
            display: none;
        }
        /* ── Customer legend chips (Group By = Customer) ────────────────
           Two-dot color toggle UX: chip body shows current color + name,
           with primary/secondary/muted dots aligned to the right. Dots
           appear on hover (desktop) or always (mobile). Active dot is
           outlined with a ring. Muted state subdues the whole chip. */
        .toggle-chip.customer-chip {
            gap: var(--space-2);
            padding-right: var(--space-2);
            cursor: pointer; /* whole chip toggles hidden state; dots/wheel stopPropagation */
        }
        .toggle-chip.customer-chip .customer-chip-name {
            flex: 1;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 12rem;
        }
        .toggle-chip.customer-chip.muted {
            opacity: 0.55;
        }
        .toggle-chip.customer-chip.muted .customer-chip-name {
            color: var(--text-muted);
        }
        /* Phase 1.5 Session 4 (by): Hidden state — chip's bar is suppressed
           in the chart. More pronounced than .muted (which only dims color).
           Strikethrough on the name reinforces the "off" semantic. */
        .toggle-chip.customer-chip.inactive {
            opacity: 0.4;
        }
        .toggle-chip.customer-chip.inactive .chip-color {
            filter: grayscale(1);
        }
        .toggle-chip.customer-chip.inactive .customer-chip-name {
            text-decoration: line-through;
            text-decoration-color: rgba(255,255,255,0.4);
            color: var(--text-muted);
        }
        .toggle-chip.customer-chip.inactive:hover {
            opacity: 0.6;
        }
        /* Build 20260508xw: single swatch-dot button — the unified color
           affordance. Unlike the legacy hover-revealed dot cluster, this is
           ALWAYS visible (it IS the primary control now), so it overrides the
           parent's opacity:0. Mirrors the interactive legend's color button. */
        .customer-color-badge {
            position: absolute;
            top: -3px;
            right: -3px;
            width: 6px;
            height: 6px;
            border-radius: 50%;
            background: var(--tac-gold, #feab40);
            border: 1px solid var(--card, #161b22);
            pointer-events: none;
        }
        /* ───────────────────────────────────────────────────────────────
           Custom color picker popover
           ─────────────────────────────────────────────────────────────── */
        .customer-color-picker {
            position: absolute;
            z-index: 1000;
            width: 280px;
            background: var(--card);
            color: var(--text);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18),
                        0 4px 12px rgba(0, 0, 0, 0.08);
            font-family: var(--font-ui);
            opacity: 0;
            transform: translateY(-4px);
            transition: opacity 0.15s ease-out, transform 0.15s ease-out;
            pointer-events: none;
        }
        [data-theme="dark"] .customer-color-picker {
            box-shadow: 0 12px 36px rgba(0, 0, 0, 0.5),
                        0 4px 12px rgba(0, 0, 0, 0.3);
        }
        .customer-color-picker.visible {
            opacity: 1;
            transform: translateY(0);
            pointer-events: auto;
        }
        /* Mobile: center on screen instead of anchoring to a dot */
        .customer-color-picker.ccp-centered {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) scale(0.96);
        }
        .customer-color-picker.ccp-centered.visible {
            transform: translate(-50%, -50%) scale(1);
        }
        .customer-color-picker.ccp-centered .ccp-arrow {
            display: none;  /* no caret when centered */
        }
        /* Caret pointing UP at the trigger dot (default position) */
        .ccp-arrow {
            position: absolute;
            top: -7px;
            left: 50%;
            width: 12px;
            height: 12px;
            background: var(--card);
            border-left: 1px solid var(--border);
            border-top: 1px solid var(--border);
            transform: translateX(-50%) rotate(45deg);
        }
        /* If the popover is positioned ABOVE the trigger, the caret should
           point DOWN — flip the borders and move to the bottom. */
        .customer-color-picker.ccp-above .ccp-arrow {
            top: auto;
            bottom: -7px;
            border: none;
            border-right: 1px solid var(--border);
            border-bottom: 1px solid var(--border);
        }
        /* Header */
        .ccp-header {
            padding: var(--space-3) var(--space-4) var(--space-2);
            border-bottom: 1px solid var(--border);
        }
        .ccp-title {
            display: block;
            font-weight: 700;
            font-size: var(--text-base);
            letter-spacing: 0.02em;
        }
        .ccp-subtitle {
            display: block;
            font-size: var(--text-sm);
            color: var(--text-muted);
            margin-top: var(--space-1);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        /* Body */
        .ccp-body {
            padding: var(--space-3) var(--space-4);
        }
        .ccp-row {
            display: flex;
            align-items: center;
            gap: var(--space-3);
            margin-bottom: var(--space-3);
        }
        .ccp-row:last-child {
            margin-bottom: 0;
        }
        /* Swatch label — clickable area that opens the native picker */
        .ccp-swatch-label {
            display: flex;
            align-items: center;
            gap: var(--space-3);
            flex: 1;
            cursor: pointer;
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            padding: var(--space-2) var(--space-2);
            transition: border-color 0.12s, background 0.12s;
            min-height: 40px;
        }
        .ccp-swatch-label:hover {
            border-color: var(--tac-blue);
            background: var(--surface-inset);
        }
        .ccp-swatch-preview {
            width: 28px;
            height: 28px;
            border-radius: var(--radius-md);
            border: 1px solid rgba(0, 0, 0, 0.15);
            flex-shrink: 0;
            transition: background 0.1s;
        }
        [data-theme="dark"] .ccp-swatch-preview {
            border-color: rgba(255, 255, 255, 0.2);
        }
        .ccp-swatch-text {
            font-size: var(--text-sm);
            color: var(--text-muted);
        }
        /* The native <input type="color"> is invisible but still receives
           clicks routed from the label. We don't display:none because
           Safari requires the input to be in the layout to open. */
        .ccp-native-input {
            position: absolute;
            opacity: 0;
            width: 1px;
            height: 1px;
            pointer-events: none;
        }
        /* Hex row */
        .ccp-hex-row {
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            padding: 0;
            overflow: hidden;
            min-height: 36px;
            transition: border-color 0.12s;
        }
        .ccp-hex-row:focus-within {
            border-color: var(--tac-blue);
        }
        .ccp-hex-prefix {
            padding: 0 var(--space-2) 0 var(--space-3);
            color: var(--text-muted);
            font-family: var(--font-mono);
            font-weight: 600;
            font-size: var(--text-base);
            border-right: 1px solid var(--border);
            line-height: 36px;
            background: var(--surface-inset);
        }
        .ccp-hex-input {
            flex: 1;
            border: none;
            outline: none;
            padding: 0 var(--space-3);
            font-family: var(--font-mono);
            font-size: var(--text-base);
            text-transform: uppercase;
            letter-spacing: 0.06em;
            background: transparent;
            color: var(--text);
            min-height: 36px;
            min-width: 0;  /* allow flex shrink */
        }
        .ccp-hex-input.ccp-invalid {
            background: rgba(220, 38, 38, 0.1);
            box-shadow: inset 0 0 0 1px #DC2626;
        }
        /* Build 20260508xv: house-color chip row */
        .ccp-defaultchip-row {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            flex-wrap: wrap;
        }
        .ccp-defaultchip {
            width: 20px;
            height: 20px;
            flex: none;
            padding: 0;
            border: 1px solid var(--border);
            border-radius: 50%;
            cursor: pointer;
            transition: transform 0.12s, box-shadow 0.12s;
            -webkit-appearance: none;
            appearance: none;
        }
        .ccp-defaultchip:hover {
            transform: scale(1.12);
            box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
        }
        .ccp-defaultchip:focus-visible {
            outline: 2px solid var(--tac-blue);
            outline-offset: 2px;
        }
        .ccp-defaultchip-label {
            font-size: var(--text-xs);
            color: var(--text-muted);
            letter-spacing: 0.01em;
            /* Separate one chip+label pair from the next (e.g. Primary | Secondary) */
            margin-right: var(--space-3);
        }
        .ccp-defaultchip-label:last-child {
            margin-right: 0;
        }
        /* Build 20260508xz: muted option row (customer mode) */
        .ccp-muted-row {
            padding-top: var(--space-1);
        }
        .ccp-muted-btn {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            background: none;
            border: 1px solid var(--border);
            border-radius: var(--radius-md, 6px);
            color: var(--text-muted);
            font-size: var(--text-sm);
            padding: 5px 11px;
            cursor: pointer;
            transition: border-color 0.12s, color 0.12s;
        }
        .ccp-muted-btn:hover {
            border-color: var(--border-strong, var(--text-muted));
            color: var(--text);
        }
        .ccp-muted-btn.active {
            border-color: var(--tac-gold, #feab40);
            color: var(--tac-gold, #feab40);
        }
        .ccp-muted-dot {
            width: 11px;
            height: 11px;
            border-radius: 50%;
            background: #6b7280;
            flex: none;
        }
        /* Build 20260508xs: group-anchored shade preset swatches */
        .ccp-presets {
            display: flex;
            gap: var(--space-2);
        }
        .ccp-preset {
            flex: 1;
            height: 26px;
            padding: 0;
            border: 1px solid var(--border);
            border-radius: var(--radius-md, 6px);
            cursor: pointer;
            position: relative;
            transition: transform 0.12s, box-shadow 0.12s;
            -webkit-appearance: none;
            appearance: none;
        }
        .ccp-preset:hover {
            transform: translateY(-1px);
            box-shadow: 0 0 0 2px var(--tac-blue);
        }
        .ccp-preset.selected {
            box-shadow: 0 0 0 2px var(--tac-blue), inset 0 0 0 2px var(--card, #fff);
        }
        .ccp-preset:focus-visible {
            outline: 2px solid var(--tac-blue);
            outline-offset: 2px;
        }
        /* Action row */
        .ccp-actions {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: var(--space-3) var(--space-4) var(--space-3);
            border-top: 1px solid var(--border);
            gap: var(--space-2);
        }
        .ccp-actions-right {
            display: flex;
            gap: var(--space-2);
        }
        .ccp-btn {
            font-family: var(--font-ui);
            font-size: var(--text-sm);
            padding: var(--space-2) var(--space-4);
            border-radius: var(--radius-md);
            border: 1px solid var(--border);
            background: var(--card);
            color: var(--text);
            cursor: pointer;
            min-height: 34px;
            transition: background 0.12s, border-color 0.12s, color 0.12s;
        }
        .ccp-btn:hover {
            background: var(--surface-inset);
        }
        .ccp-btn-reset {
            color: var(--text-muted);
            font-size: var(--text-sm);
        }
        .ccp-btn-reset:hover {
            color: #DC2626;
            border-color: #DC2626;
        }
        .ccp-btn-apply {
            background: var(--tac-blue);
            color: #ffffff;
            border-color: var(--tac-blue);
            font-weight: 600;
        }
        .ccp-btn-apply:hover {
            background: #1870ff;
            border-color: #1870ff;
        }
        /* ───────────────────────────────────────────────────────────────
           Mobile picker: full-width with bottom safe-area inset, larger
           tap targets, no caret. The .ccp-centered class handles the
           positioning already; this section just tunes sizes for touch.
           ─────────────────────────────────────────────────────────────── */
        @media (max-width: 480px) {
            .customer-color-picker {
                width: min(320px, calc(100vw - 1.5rem));
            }
            .ccp-swatch-label {
                min-height: 48px;
            }
            .ccp-swatch-preview {
                width: 32px;
                height: 32px;
            }
            .ccp-hex-row {
                min-height: 44px;
            }
            .ccp-hex-input,
            .ccp-hex-prefix {
                min-height: 44px;
                line-height: 44px;
                font-size: var(--text-md);
            }
            .ccp-btn {
                min-height: 40px;
                padding: var(--space-2) var(--space-4);
                font-size: var(--text-base);
            }
            .ccp-btn-reset {
                font-size: var(--text-sm);
            }
        }
        /* Group expand/collapse toggle on legend chip */
        .customer-chip-group-toggle {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 14px;
            height: 14px;
            font-size: var(--text-2xs);
            color: var(--text-muted);
            cursor: pointer;
            border-radius: var(--radius-xs);
            margin-left: var(--space-1);
            -webkit-user-select: none;
            user-select: none;
            transition: color 0.12s, background 0.12s;
        }
        .customer-chip-group-toggle:hover {
            background: var(--surface-hover);
            color: var(--text);
        }
        /* Sub-brand visual indent — small left border accent so chips that
           belong to an expanded parent group read as a cluster. */
        .toggle-chip.customer-chip.customer-chip-subbrand {
            margin-left: var(--space-2);
            border-left: 2px solid var(--border);
            padding-left: var(--space-2);
        }
        /* Mobile: always show dots since there's no hover */
        @media (max-width: 768px) {
        }
        /* Color collision warning indicator */
        .customer-legend-collision-warn {
            display: inline-flex;
            align-items: center;
            padding: var(--space-1) var(--space-2);
            border-radius: var(--radius-md);
            font-size: var(--text-xs);
            font-family: var(--font-ui);
            color: #856404;
            background: #FFF8E1;
            border: 1px solid #FFE082;
            cursor: help;
            margin-left: var(--space-2);
            -webkit-user-select: none;
            user-select: none;
        }
        .customer-legend-collision-warn:hover {
            background: #FFECB3;
        }
        .customer-legend-collision-warn.expanded {
            background: #FFE082;
        }
        /* Build 20260508yb: quiet inline collision detail (replaces alert()) */
        .customer-legend-collision-detail {
            flex-basis: 100%;
            margin-top: var(--space-2);
            padding: var(--space-2) var(--space-3);
            border: 1px solid var(--border);
            border-radius: var(--radius-md);
            background: var(--surface-inset, rgba(0,0,0,0.03));
            font-size: var(--text-xs);
            color: var(--text-muted);
            line-height: 1.45;
        }
        .cl-collision-title {
            font-weight: 600;
            color: var(--text);
            margin-bottom: var(--space-1);
        }
        .cl-collision-list {
            margin: 0 0 var(--space-1);
            padding-left: 1.1em;
        }
        .cl-collision-tip {
            opacity: 0.85;
        }

        /* ── Customer View X-axis controls (v7.26.0) ───────────────────
           Inline control row sitting between the main filter bar and the
           customer chip strip. Three controls: top-N slider, X-axis sort,
           cluster groups toggle. Visible only when Group By = Customer
           (display managed by JS via show/hide on #customerXAxisControls).
        */
        .customer-xaxis-controls {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: var(--space-3);
            padding: var(--space-2) var(--space-4);
            margin: var(--space-2) 0 var(--space-3);
            background: var(--card);
            border: 0.5px solid var(--border);
            border-radius: var(--radius-lg);
            font-family: var(--font-ui);
        }
        .cxc-control {
            display: flex;
            align-items: center;
            gap: var(--space-2);
        }
        /* Disabled state for controls that only meaningfully apply in
           by-customer mode. When in time-series mode, these grey out so
           the user sees they exist but understands they're inactive. */
        .cxc-bycustomer-only.disabled,
        .cxc-bycustomer-only.disabled .cxc-label,
        .cxc-bycustomer-only.disabled .cxc-topn-value,
        .cxc-bycustomer-only.disabled .cxc-slider-bound {
            opacity: 0.45;
            pointer-events: none;
        }
        .cxc-bycustomer-only.disabled .cxc-slider {
            cursor: not-allowed;
        }
        .cxc-divider {
            width: 0.5px;
            height: 20px;
            background: var(--border);
        }
        .cxc-divider.cxc-bycustomer-only.disabled {
            opacity: 0.45;
        }
        /* Mode toggle — two-pill segmented control. Same visual vocabulary
           as the sort selector for consistency. */
        .cxc-mode-group {
            display: flex;
            gap: 1px;
            background: var(--border);
            padding: 1px;
            border-radius: var(--radius-md);
        }
        .cxc-mode-btn {
            display: inline-flex;
            align-items: center;
            padding: var(--space-1) var(--space-3);
            background: var(--card);
            color: var(--text-muted);
            border: none;
            border-radius: var(--radius-sm);
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 500;
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
        }
        .cxc-mode-btn:hover {
            background: var(--bg);
            color: var(--text);
        }
        .cxc-mode-btn.active {
            background: var(--tac-blue);
            color: #ffffff;
        }
        /* Labels toggle (Name / ICAO / Logo) — same pill vocabulary. */
        .cxc-label-group {
            display: flex;
            gap: 1px;
            background: var(--border);
            padding: 1px;
            border-radius: var(--radius-md);
        }
        .cxc-label-btn {
            display: inline-flex;
            align-items: center;
            padding: var(--space-1) var(--space-3);
            background: var(--card);
            color: var(--text-muted);
            border: none;
            border-radius: var(--radius-sm);
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 500;
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
        }
        .cxc-label-btn:hover {
            background: var(--bg);
            color: var(--text);
        }
        .cxc-label-btn.active {
            background: var(--tac-blue);
            color: #ffffff;
        }
        .cxc-label {
            font-size: var(--text-xs);
            color: var(--text-muted);
            font-weight: 500;
            letter-spacing: 0.04em;
            white-space: nowrap;
        }
        .cxc-label-suffix {
            margin-right: var(--space-2);
        }
        .cxc-topn-value {
            font-family: var(--font-mono);
            font-size: var(--text-base);
            font-weight: 600;
            color: var(--text);
            min-width: 22px;
            text-align: center;
            padding: 0 var(--space-1);
        }
        .cxc-slider {
            -webkit-appearance: none;
            appearance: none;
            width: 160px;
            height: 4px;
            background: var(--border);
            border-radius: var(--radius-xs);
            outline: none;
            cursor: pointer;
            margin: 0 var(--space-2);
        }
        .cxc-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 14px;
            height: 14px;
            background: var(--tac-blue);
            border-radius: 50%;
            cursor: pointer;
            border: 2px solid var(--card);
            box-shadow: 0 0 0 1px var(--tac-blue);
            transition: transform 0.15s ease;
        }
        .cxc-slider::-webkit-slider-thumb:hover {
            transform: scale(1.15);
        }
        .cxc-slider::-moz-range-thumb {
            width: 14px;
            height: 14px;
            background: var(--tac-blue);
            border-radius: 50%;
            cursor: pointer;
            border: 2px solid var(--card);
            box-shadow: 0 0 0 1px var(--tac-blue);
        }
        .cxc-slider-bound {
            font-family: var(--font-mono);
            font-size: var(--text-2xs);
            color: var(--text-muted);
            min-width: 14px;
        }
        .cxc-sort-group {
            display: flex;
            gap: 1px;
            background: var(--border);
            padding: 1px;
            border-radius: var(--radius-md);
        }
        .cxc-sort-btn {
            display: inline-flex;
            align-items: center;
            gap: 3px;
            padding: var(--space-1) var(--space-3);
            background: var(--card);
            color: var(--text-muted);
            border: none;
            border-radius: var(--radius-sm);
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 500;
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
        }
        .cxc-sort-btn:hover {
            background: var(--bg);
            color: var(--text);
        }
        .cxc-sort-btn.active {
            background: var(--tac-blue);
            color: #ffffff;
        }
        .cxc-toggle {
            margin-left: var(--space-1);
        }
        /* Slider in a "max-reached" state — visually signals the cap to the user */
        .cxc-slider.at-cap::-webkit-slider-thumb {
            background: var(--tac-gold);
            box-shadow: 0 0 0 1px var(--tac-gold);
        }
        .cxc-slider.at-cap::-moz-range-thumb {
            background: var(--tac-gold);
            box-shadow: 0 0 0 1px var(--tac-gold);
        }

        /* ── Generic confirm dialog (v7.26.0) ──────────────────────────
           Used for top-N <-> manual mode switches. Modal-style, centered.
           Driven by showConfirmDialog() helper in app.js. */
        .confirm-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9000;
            backdrop-filter: blur(2px);
        }
        .confirm-dialog {
            background: var(--card);
            border: 0.5px solid var(--border);
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow-lg);
            padding: var(--space-5);
            max-width: 420px;
            width: 90%;
            font-family: var(--font-ui);
        }
        .confirm-title {
            font-size: var(--text-lg);
            font-weight: 600;
            color: var(--text);
            margin: 0 0 var(--space-2);
        }
        .confirm-body {
            font-size: var(--text-sm);
            color: var(--text-muted);
            line-height: 1.5;
            margin: 0 0 var(--space-4);
        }
        .confirm-actions {
            display: flex;
            justify-content: flex-end;
            gap: var(--space-2);
        }
        .confirm-btn {
            padding: var(--space-2) var(--space-4);
            font-family: var(--font-ui);
            font-size: var(--text-sm);
            font-weight: 500;
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
            border: 0.5px solid transparent;
        }
        .confirm-btn-cancel {
            background: transparent;
            color: var(--text-muted);
            border-color: var(--border);
        }
        .confirm-btn-cancel:hover {
            background: var(--bg);
            color: var(--text);
        }
        .confirm-btn-primary {
            background: var(--tac-blue);
            color: #ffffff;
        }
        .confirm-btn-primary:hover {
            opacity: 0.9;
        }

        /* Customer-mode advisory notes (above chart) */
        .customer-mode-notes {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
            margin: var(--space-2) 0 var(--space-3);
            padding: var(--space-2) var(--space-3);
            background: var(--surface-inset, #F8F9FA);
            border-left: 3px solid var(--tac-blue);
            border-radius: 0 4px 4px 0;
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            line-height: 1.4;
        }
        .customer-mode-notes .cust-note {
            color: var(--text-muted);
        }
        .customer-mode-notes .cust-note-default {
            color: var(--text);
            font-weight: 500;
        }
        .customer-mode-notes .cust-note-excluded {
            color: var(--text-muted);
        }
        .customer-mode-notes .cust-note-tip {
            color: #6c5500;
            background: #FFF8E1;
            padding: var(--space-1) var(--space-2);
            border-radius: var(--radius-sm);
        }
        /* Customer cap toast — non-blocking notification when user adds a
           customer beyond the hard cap (will be in "Other" bucket). */
        .customer-cap-toast {
            position: fixed;
            bottom: 1.5rem;
            left: 50%;
            transform: translateX(-50%) translateY(2rem);
            max-width: min(460px, calc(100vw - 2rem));
            padding: var(--space-3) var(--space-4);
            background: #292929;
            color: #ffffff;
            border-radius: var(--radius-lg);
            font-family: var(--font-ui);
            font-size: var(--text-base);
            line-height: 1.45;
            box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.2s, transform 0.2s;
            z-index: 9999;
        }
        .customer-cap-toast.visible {
            opacity: 1;
            transform: translateX(-50%) translateY(0);
            pointer-events: auto;
        }
        .customer-cap-toast strong {
            color: #FFD54F;
        }
        /* ── Customer empty-state overlay ────────────────────────────────
           Shown over the chart canvas when Group By = Customer and no
           customer is selected. Prompts the user to pick a customer or
           load top 5 as a fallback.
           IMPORTANT: pointer-events default to none so the overlay never
           swallows hover/click events meant for the chart underneath. We
           explicitly re-enable pointer-events when the .visible class is
           added (i.e., when the overlay is actually showing). */
        .customer-empty-state {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            inset: 0;  /* shorthand for browsers that support it (Safari 14.1+) */
            background: rgba(255, 255, 255, 0.92);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 50;
            border-radius: var(--radius-md);
            backdrop-filter: blur(2px);
            -webkit-backdrop-filter: blur(2px);
            animation: emptyStateFadeIn 0.25s ease-out;
            pointer-events: none;
        }
        .customer-empty-state.visible {
            pointer-events: auto;
        }
        /* The CTA button needs pointer-events even if the overlay is in a
           transitional state — make sure interactive children always work. */
        .customer-empty-state .customer-empty-cta {
            pointer-events: auto;
        }
        [data-theme="dark"] .customer-empty-state {
            background: rgba(20, 20, 20, 0.92);
        }
        @keyframes emptyStateFadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
        .customer-empty-state-content {
            text-align: center;
            max-width: 28rem;
            padding: var(--space-6) var(--space-5);
            font-family: var(--font-ui);
        }
        .customer-empty-arrow {
            width: 64px;
            height: 96px;
            margin: 0 auto var(--space-4);
            color: #feab40;
            display: block;
            animation: arrowBob 1.6s ease-in-out infinite;
            transform-origin: center;
        }
        @keyframes arrowBob {
            0%, 100% { transform: translateY(0); }
            50%      { transform: translateY(-10px); }
        }
        .customer-empty-title {
            font-size: var(--text-2xl);
            font-weight: 700;
            margin: 0 0 var(--space-2);
            color: var(--text);
        }
        .customer-empty-subtitle {
            font-size: var(--text-md);
            color: var(--text-muted);
            line-height: 1.5;
            margin: 0 0 var(--space-5);
        }
        .customer-empty-cta {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: var(--space-3) var(--space-5);
            font-family: var(--font-ui);
            font-size: var(--text-base);
            font-weight: 500;
            color: #ffffff;
            background: var(--tac-blue);
            border: none;
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: background 0.15s, transform 0.15s;
            min-height: 36px;
        }
        .customer-empty-cta:hover {
            background: #1870ff;
            transform: translateY(-1px);
        }
        .customer-empty-cta:active {
            transform: translateY(0);
        }
        /* Build 20260508ym: time:customer holding screen — guided launcher on
           the t:c cold-start overlay. "Show all" primary button + Region /
           Country single-pick dropdowns that mirror to the scope menu. */
        .customer-holding {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--space-3);
            margin-top: var(--space-4);
        }
        .customer-holding .holding-btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: var(--space-3) var(--space-6);
            font-family: var(--font-ui);
            font-size: var(--text-base);
            font-weight: 500;
            color: #ffffff;
            background: var(--tac-blue);
            border: none;
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: background 0.15s, transform 0.15s;
            min-height: 36px;
        }
        .customer-holding .holding-btn:hover {
            background: #1870ff;
            transform: translateY(-1px);
        }
        .customer-holding .holding-btn:active { transform: translateY(0); }
        .customer-holding .holding-or {
            font-size: var(--text-sm);
            color: var(--text-muted);
        }
        .customer-holding .holding-selects {
            display: flex;
            gap: var(--space-3);
            flex-wrap: wrap;
            justify-content: center;
        }
        .customer-holding .holding-select {
            font-family: var(--font-ui);
            font-size: var(--text-base);
            padding: var(--space-2) var(--space-3);
            min-height: 36px;
            min-width: 150px;
            color: var(--text-primary);
            background: var(--bg);
            border: 1px solid var(--border);
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: border-color 0.15s;
        }
        .customer-holding .holding-select:hover { border-color: var(--tac-blue); }
        .customer-holding .holding-select:focus {
            outline: none;
            border-color: var(--tac-blue);
        }
        /* Glow effect on customer search input when empty state is active —
           visually directs attention to the search field. */
        .customer-search-input.glow-attention {
            animation: searchGlow 1.6s ease-in-out infinite;
            border-color: var(--tac-blue) !important;
        }
        @keyframes searchGlow {
            0%, 100% {
                box-shadow: 0 0 0 0 rgba(30, 144, 255, 0.4);
            }
            50% {
                box-shadow: 0 0 0 6px rgba(30, 144, 255, 0);
            }
        }

        /* Phase 1.5 Session 4 (bx): V8-themed empty-state overlay.
           V7's overlay defaults to white background; V8 needs dark to sit
           correctly over the V8 chart frame. Typography also shifts to
           Archivo (title) + Source Serif italic (subtitle) to match the
           rest of V8's editorial voice. Cold-start is suppressed in V8 per
           Phase 1.5 spec — this overlay only fires for filtered-to-zero. */
        body.v8-ui-enabled .customer-empty-state {
            background: rgba(13, 17, 23, 0.94);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
        }
        body.v8-ui-enabled .customer-empty-title {
            font-family: 'Archivo', system-ui, sans-serif;
            font-weight: 700;
            font-size: 22px;
            color: #eeeeee;
            letter-spacing: -0.01em;
            margin-bottom: 12px;
        }
        body.v8-ui-enabled .customer-empty-subtitle {
            font-family: 'Source Serif 4', Georgia, serif;
            font-style: italic;
            font-weight: 400;
            font-size: 14.5px;
            line-height: 1.55;
            color: #959595;
            max-width: 28rem;
            margin: 0 auto 20px;
        }
        body.v8-ui-enabled .customer-empty-cta {
            font-family: 'Archivo', system-ui, sans-serif;
            font-weight: 600;
            font-size: 13px;
            padding: 10px 20px;
            border-radius: 6px;
            background: var(--tac-blue);
            color: white;
            min-height: 0;
            transition: background 150ms;
        }
        body.v8-ui-enabled .customer-empty-cta:hover {
            background: #2580ff;
            transform: none;
        }
        /* Grouped toggle sections */
        .toggle-group {
            margin-bottom: var(--space-2);
        }
        .toggle-group:last-child {
            margin-bottom: 0;
        }
        .toggle-group-header {
            font-size: var(--text-sm);
            font-weight: 600;
            font-family: var(--font-ui);
            color: var(--text-muted);
            margin-bottom: var(--space-2);
            padding: var(--space-1) var(--space-3);
            border-bottom: 1px solid var(--border);
            display: flex;
            align-items: center;
            gap: var(--space-2);
            cursor: pointer;
            border-radius: var(--radius-md);
            transition: background 0.15s;
        }
        .toggle-group-header:hover {
            background: var(--surface-inset);
        }
        .toggle-group-header .mfr-color {
            width: 12px;
            height: 12px;
            border-radius: var(--radius-xs);
        }
        .toggle-group-header .toggle-hint {
            font-size: var(--text-2xs);
            color: var(--text-muted);
            margin-left: auto;
        }
        .toggle-group-items {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
        }
        .toggle-family-row {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
            width: 100%;
            padding: var(--space-1) 0;
            border-bottom: 1px dashed var(--border);
        }
        .toggle-family-row:last-child {
            border-bottom: none;
            padding-bottom: 0;
        }
        .toggle-family-row:first-child {
            padding-top: 0;
        }
        /* Inline variant toggle button */
        .variant-toggle-btn-inline {
            padding: var(--space-1) var(--space-3);
            font-size: var(--text-sm);
            font-weight: 600;
            font-family: var(--font-ui);
            color: var(--text);
            background: var(--surface-selected);
            border: 1px solid var(--tac-blue);
            border-radius: var(--radius-md);
            cursor: pointer;
            transition: background 0.15s, box-shadow 0.15s;
            margin-left: var(--space-2);
            white-space: nowrap;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }
        .variant-toggle-btn-inline:hover {
            background: var(--surface-hover);
            box-shadow: 0 2px 5px rgba(0,0,0,0.15);
        }
        .variant-toggle-btn-inline.back {
            background: var(--surface-inset);
            border-color: var(--gray-light);
            color: var(--text-muted);
        }
        .variant-toggle-btn-inline.back:hover {
            background: var(--gray-pale);
        }
        .variant-toggle-btn-inline.split-active {
            background: var(--tac-blue);
            border-color: var(--tac-blue);
            color: white;
        }
        .variant-toggle-btn-inline.split-active:hover {
            opacity: 0.85;
        }
        @keyframes btnPulse {
            0% { box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.4); }
            70% { box-shadow: 0 0 0 8px rgba(25, 118, 210, 0); }
            100% { box-shadow: 0 0 0 0 rgba(25, 118, 210, 0); }
        }
        .variant-toggle-btn-inline.pulse {
            animation: btnPulse 1s ease-out;
        }
        /* Collapsible toggle groups */
        .toggle-group.collapsed .toggle-group-items {
            display: none;
        }
        .toggle-group.collapsed .toggle-group-header {
            opacity: 0.6;
            border-bottom: none;
        }
        .toggle-group-header .collapse-icon {
            font-size: var(--text-2xs);
            transition: transform 0.2s;
            color: var(--text-muted);
            margin-right: var(--space-1);
        }
        .toggle-group.collapsed .collapse-icon {
            transform: rotate(-90deg);
        }

        .data-note-icon {
            font-size: var(--text-md);
        }
        .data-note-text {
            white-space: nowrap;
        }
        @media (max-width: 900px) {
        }
        @media (max-width: 800px) {
        }
        .click-hint {
            font-size: var(--text-xs);
            color: var(--text-muted);
            font-style: italic;
        }

        /* Customer Filter Bar */
        .customer-filter-bar {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius-xl);
            padding: var(--space-4);
            margin-bottom: 0;
            box-shadow: var(--shadow-sm);
        }
        .customer-filter-bar.hidden {
            display: none;
        }
        .filter-bar-header {
            display: flex;
            align-items: center;
            gap: var(--space-4);
            margin-bottom: var(--space-3);
            flex-wrap: wrap;
        }
        .filter-bar-header h3 {
            font-family: var(--font-ui);
            font-size: var(--text-md);
            font-weight: 600;
            color: var(--text);
            margin: 0;
        }
        /* (.filter-mode-tabs / .filter-mode-tab retired 2026-10-18, customer roles B3′ — the hidden V7 mode tabs are gone) */
        .filter-bar-toggle {
            margin-left: auto;
            font-size: var(--text-sm);
            color: var(--tac-blue);
            cursor: pointer;
            text-decoration: none;
        }
        .filter-bar-toggle:hover {
            text-decoration: underline;
        }
        .filter-row {
            display: flex;
            gap: var(--space-4);
            flex-wrap: wrap;
            align-items: flex-start;
        }
        .filter-group {
            display: flex;
            flex-direction: column;
            gap: var(--space-2);
        }
        .filter-group label {
            font-size: var(--text-sm);
            font-weight: 600;
            font-family: var(--font-ui);
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        .customer-search-container {
            position: relative;
            width: 280px;
        }
        .customer-search-input {
            width: 100%;
            padding: var(--space-2) var(--space-3);
            padding-right: var(--space-6);
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            font-size: var(--text-base);
            font-family: var(--font-ui);
            background: var(--card);
            color: var(--text);
        }
        .customer-search-input:focus {
            outline: none;
            border-color: var(--tac-blue);
            box-shadow: 0 0 0 3px rgba(30, 144, 255, 0.1);
        }
        .customer-search-clear {
            position: absolute;
            right: 0.5rem;
            top: 50%;
            transform: translateY(-50%);
            background: none;
            border: none;
            color: var(--text-muted);
            cursor: pointer;
            font-size: var(--text-md);
            padding: var(--space-1);
            line-height: 1;
            display: none;
        }
        .customer-search-clear.visible {
            display: block;
        }
        .customer-autocomplete {
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            background: var(--card);
            border: 1px solid var(--border);
            border-top: none;
            border-radius: 0 0 6px 6px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            max-height: 300px;
            overflow-y: auto;
            z-index: 100;
            display: none;
        }
        .customer-autocomplete.visible {
            display: block;
        }
        .airline-logo {
            width: 22px;
            height: 22px;
            object-fit: contain;
            border-radius: var(--radius-sm);
            flex-shrink: 0;
        }
        .airline-logo-sm {
            width: 16px;
            height: 16px;
            object-fit: contain;
            border-radius: var(--radius-xs);
            flex-shrink: 0;
        }
        .autocomplete-item-left {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            min-width: 0;
            overflow: hidden;
        }
        .autocomplete-item-left .name-text {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .logo-placeholder {
            width: 22px;
            height: 22px;
            flex-shrink: 0;
        }
        .logo-placeholder-sm {
            width: 16px;
            height: 16px;
            flex-shrink: 0;
        }
        .autocomplete-item {
            padding: var(--space-2) var(--space-3);
            cursor: pointer;
            font-size: var(--text-base);
            border-bottom: 1px solid var(--border-subtle);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .autocomplete-item:last-child {
            border-bottom: none;
        }
        .autocomplete-item:hover {
            background: var(--surface-hover);
        }
        .autocomplete-item.highlighted {
            background: var(--surface-hover);
            outline: 2px solid var(--tac-blue);
            outline-offset: -2px;
        }
        .autocomplete-item.selected {
            background: var(--surface-selected);
            position: relative;
        }
        .autocomplete-item.selected::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 3px;
            background: var(--tac-blue);
            border-radius: 0 2px 2px 0;
        }
        .autocomplete-item.excluded-item {
            opacity: 0.6;
            position: relative;
        }
        .autocomplete-item.excluded-item::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 3px;
            background: #F44336;
            border-radius: 0 2px 2px 0;
        }
        .autocomplete-item.excluded-item .name-text {
            text-decoration: line-through;
        }
        .autocomplete-item-right {
            display: flex;
            align-items: center;
            gap: var(--space-2);
        }
        .ac-exclude-btn {
            width: 18px;
            height: 18px;
            border-radius: 50%;
            border: 1px solid #F44336;
            background: transparent;
            color: #F44336;
            font-size: var(--text-sm);
            font-weight: 700;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0;
            line-height: 1;
            opacity: 0.4;
            transition: opacity 0.15s, background 0.15s;
            flex-shrink: 0;
        }
        .autocomplete-item:hover .ac-exclude-btn {
            opacity: 0.7;
        }
        .ac-exclude-btn:hover {
            opacity: 1;
            background: #F44336;
            color: white;
        }
        .autocomplete-item .count {
            font-size: var(--text-sm);
            color: var(--text-muted);
        }
        .autocomplete-item .group-indicator {
            font-size: var(--text-xs);
            color: var(--tac-blue);
            margin-left: var(--space-2);
        }
        .autocomplete-hint {
            padding: var(--space-1) var(--space-3);
            font-size: var(--text-xs);
            color: var(--text-muted);
            background: var(--surface-dim);
            border-top: 1px solid var(--border);
            text-align: center;
        }
        .selected-filters {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
            min-height: 28px;
        }
        /* ══════════════════════════════════════════════════════════════════
           Active filter chips — unified modern style.
           All chip variants use the same base structure: tinted background,
           colored border, normal text weight. Differentiated by accent color:
             default (customer/operator) → blue
             .region                      → purple
             .country                     → blue (with blue ISO pill)
             .buyer-country               → gold (with gold ISO pill)
             .excluded                    → red (with strikethrough content)
           ══════════════════════════════════════════════════════════════════ */
        .filter-chip {
            display: inline-flex;
            align-items: center;
            gap: var(--space-2);
            padding: var(--space-1) var(--space-2);
            background: rgba(30, 144, 255, 0.08);
            border: 1px solid rgba(30, 144, 255, 0.32);
            color: var(--text);
            border-radius: var(--radius-lg);
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            font-weight: 500;
            line-height: 1.3;
            max-width: 100%;
        }
        .filter-chip.region {
            background: rgba(106, 27, 154, 0.08);
            border-color: rgba(106, 27, 154, 0.35);
        }
        .filter-chip.excluded {
            background: rgba(243, 88, 65, 0.12);
            border-color: rgba(243, 88, 65, 0.45);
            color: #d85a48;
        }
        .filter-chip.excluded s {
            text-decoration: line-through;
        }
        /* Build 20260508yy: accessible exclude toggle button + persistent ⊘ glyph
           (mirrors the V8 chip). The × remains the separate remove control. */
        .filter-chip .chip-toggle {
            display: inline-flex;
            align-items: center;
            gap: 5px;
            background: none;
            border: none;
            margin: 0;
            padding: 2px 2px 2px 0;
            font: inherit;
            color: inherit;
            cursor: pointer;
            border-radius: 2px;
        }
        .filter-chip .chip-ex-glyph {
            width: 11px;
            height: 11px;
            flex: 0 0 auto;
            opacity: 0.45;
            transition: opacity 0.12s;
        }
        .filter-chip .chip-toggle:hover .chip-ex-glyph,
        .filter-chip .chip-toggle:focus-visible .chip-ex-glyph {
            opacity: 0.9;
        }
        .filter-chip.excluded .chip-ex-glyph {
            opacity: 1;
        }
        .filter-chip .chip-toggle:focus-visible {
            outline: 2px solid var(--tac-blue, #1870ff);
            outline-offset: 1px;
        }
        .filter-chip .remove-chip {
            cursor: pointer;
            opacity: 0.55;
            font-size: var(--text-md);
            line-height: 1;
            padding: 0 var(--space-1);
            margin-left: var(--space-1);
            color: inherit;
            transition: opacity 0.1s;
        }
        .filter-chip .remove-chip:hover {
            opacity: 1;
        }
        .clear-all-filters {
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            color: var(--text-muted);
            cursor: pointer;
            padding: var(--space-1) var(--space-3);
            border: 1px dashed var(--border);
            border-radius: var(--radius-lg);
            background: transparent;
        }
        .clear-all-filters:hover {
            border-color: var(--text-muted);
            color: var(--text);
        }

        /* Expandable group filter chips — same visual skin as base chip,
           but with collapsible vertical structure */
        .group-chip.filter-chip,
        .filter-chip.group-chip {
            flex-direction: column;
            padding: 0;
            align-items: stretch;
            overflow: hidden;
        }
        .group-chip.has-exclusions {
            border-style: dashed;
        }
        .group-chip-header {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            padding: var(--space-1) var(--space-2);
            cursor: pointer;
            color: var(--text);
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            font-weight: 500;
        }
        .group-chip-header:hover {
            background: rgba(30, 144, 255, 0.12);
        }
        .expand-icon {
            font-size: var(--text-2xs);
            color: var(--text-muted);
            transition: transform 0.15s;
        }
        .member-count {
            color: var(--text-muted);
            font-size: var(--text-xs);
            margin-left: auto;
            margin-right: var(--space-1);
        }
        .group-members {
            display: none;
            flex-direction: column;
            background: rgba(30, 144, 255, 0.05);
            border-top: 1px solid rgba(30, 144, 255, 0.18);
            padding: var(--space-1);
            gap: var(--space-1);
        }
        .group-members.expanded {
            display: flex;
        }
        .member-toggle {
            display: flex;
            align-items: center;
            gap: var(--space-1);
            padding: var(--space-1) var(--space-2);
            border-radius: var(--radius-sm);
            cursor: pointer;
            font-size: var(--text-xs);
            color: var(--text-muted);
            transition: background 0.1s, color 0.1s;
        }
        .member-toggle:hover {
            background: rgba(30, 144, 255, 0.15);
            color: var(--text);
        }
        .member-toggle.included {
            color: var(--text);
        }
        .member-toggle.excluded {
            opacity: 0.55;
            text-decoration: line-through;
        }
        .member-toggle input[type="checkbox"] {
            width: 12px;
            height: 12px;
            margin: 0;
            accent-color: var(--tac-blue);
        }
        .member-name {
            flex: 1;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .member-total {
            color: var(--text-muted);
            font-size: var(--text-xs);
        }

        .region-chips {
            display: flex;
            flex-wrap: wrap;
            gap: var(--space-2);
        }
        .region-chip {
            display: inline-flex;
            align-items: center;
            gap: var(--space-1);
            padding: var(--space-1) var(--space-3);
            border-radius: var(--radius-md);
            font-size: var(--text-sm);
            font-family: var(--font-ui);
            cursor: pointer;
            border: 1px solid var(--border);
            background: var(--card);
            transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s, filter 0.15s;
        }
        .region-chip:hover {
            border-color: var(--gray-light);
        }
        .region-chip.active {
            background: #6A1B9A;
            color: white;
            border-color: #6A1B9A;
        }
        .region-chip .region-color {
            width: 8px;
            height: 8px;
            border-radius: var(--radius-xs);
        }
        .filter-summary {
            font-size: var(--text-base);
            color: var(--text-muted);
            padding: var(--space-2) 0;
            border-top: 1px solid var(--border);
            margin-top: var(--space-3);
        }
        .filter-summary strong {
            color: var(--text);
        }
        .data-coverage-note {
            font-size: var(--text-xs);
            color: var(--warning-text);
            background: var(--warning-bg);
            padding: var(--space-2) var(--space-3);
            border-radius: var(--radius-md);
            margin-top: var(--space-2);
        }

        /* ── Responsive: Tablet (≤1024px) ────────────────────────── */
        @media (max-width: 1024px) {
            .controls-section {
                gap: var(--space-3);
            }
            .controls-actions {
                gap: var(--space-2);
            }
            .legend-grouped {
                gap: var(--space-2) var(--space-5);
            }
        }

        /* ── Responsive: Small Tablet / Large Phone (≤768px) ───── */
        @media (max-width: 768px) {
            body {
                padding: var(--space-3);
                padding-left: max(0.75rem, env(safe-area-inset-left));
                padding-right: max(0.75rem, env(safe-area-inset-right));
                padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
            }
            .chart-container {
                padding: var(--space-4);
                border-radius: var(--radius-xl);
            }
            .view-tabs {
                right: 0.5rem;
            }
            .view-tab {
                padding: var(--space-2) var(--space-2);
                font-size: var(--text-xs);
            }
            .header {
                gap: var(--space-5);
                margin-bottom: 14px;   /* match the scoreboard → chart gap around the ticker */
            }
            .header h1 { font-size: var(--text-2xl); }
            .chart-header h2 {
                font-size: var(--text-xl);
            }
            .chart-header {
                padding-bottom: var(--space-2);
                margin-bottom: var(--space-2);
            }
            .controls-row {
                gap: var(--space-2);
                padding: var(--space-2) 0;
            }
            .controls-section {
                flex-direction: column;
                align-items: flex-start;
                gap: var(--space-2);
                width: 100%;
            }
            .controls-actions {
                flex-wrap: wrap;
                width: 100%;
            }
            .stats-grid {
                grid-template-columns: repeat(3, 1fr);
                gap: var(--space-2);
            }
            .stat-card { padding: var(--space-3); }
            .stat-value { font-size: var(--text-2xl); }
            .filter-row {
                flex-direction: column;
                gap: var(--space-2);
            }
            .filter-bar-header {
                flex-wrap: wrap;
                gap: var(--space-2);
            }
            .customer-filter-bar {
                padding: var(--space-3);
            }
            .chart-wrap { height: 400px; }
            .year-range-container {
                flex-wrap: wrap;
            }
            /* Shorten "Year Range:" label to "Years:" on narrower screens
               to reclaim horizontal space for the slider + selects. The
               original label text is set via CSS so no markup change. */
            .year-range-label {
                font-size: 0; /* hide the HTML text node */
            }
            .year-range-label::before {
                content: 'Years:';
                font-size: var(--text-sm);
                font-weight: 600;
                color: var(--text-muted);
                text-transform: uppercase;
                letter-spacing: 0.5px;
            }
            /* Larger touch targets for year range thumbs */
            .year-range-thumb {
                width: 28px;
                height: 28px;
            }
            /* Compare controls stack vertically */
            .controls-row-secondary .controls-section {
                flex-direction: row;
                flex-wrap: wrap;
                gap: var(--space-2);
            }
            /* Grouped legend on tablet */
            .chart-legend.legend-grouped {
                gap: var(--space-2) var(--space-4);
            }
            .legend-family-label {
                font-size: var(--text-2xs);
            }
            .legend-item {
                font-size: var(--text-xs);
            }
            .legend-color {
                width: 10px;
                height: 10px;
            }
            /* Chart branding */
            .chart-branding img {
                width: 160px;
            }
            .click-hint {
                font-size: var(--text-xs);
            }
            /* Autocomplete touch improvements */
            .autocomplete-item {
                padding: var(--space-2) var(--space-3);
            }
            .ac-exclude-btn {
                width: 22px;
                height: 22px;
                opacity: 0.5;
            }
            /* ── Bar layout sub-toggle on tablet ───────────────────────
               Slightly smaller than desktop but still comfortable. */
            .bar-layout-btn {
                padding: var(--space-2) var(--space-3);
                font-size: var(--text-xs);
                min-height: 32px;
            }
            /* ── Customer empty-state overlay on tablet ────────────────
               Slightly smaller than desktop but larger than phone. */
            .customer-empty-arrow {
                width: 56px;
                height: 80px;
            }
            .customer-empty-title {
                font-size: var(--text-xl);
            }
        }

        /* ── Responsive: Phone (≤480px) ──────────────────────────── */
        @media (max-width: 480px) {
            body {
                padding: var(--space-2);
                padding-left: max(0.5rem, env(safe-area-inset-left));
                padding-right: max(0.5rem, env(safe-area-inset-right));
                padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
            }
            .header {
                flex-direction: column;
                align-items: flex-start;
                gap: var(--space-4);
                margin-bottom: 14px;   /* match the scoreboard → chart gap around the ticker */
                padding-bottom: var(--space-4);
            }
            .header h1 { font-size: var(--text-xl); }
            .chart-container {
                padding: var(--space-3);
                border-radius: var(--radius-lg);
            }
            /* Mobile chart-container margin — unconditional + :has() pair
               for browsers that support :has() (the rule is a no-op on
               browsers that don't, since the unconditional applies first). */
            .chart-container {
                margin-top: var(--space-6);
            }
            .chart-container:has(.view-tabs) {
                margin-top: var(--space-6);
            }
            .view-tabs {
                right: 0.25rem;
            }
            .view-tab {
                padding: var(--space-2) var(--space-3);  /* boosted from 0.3rem 0.4rem for ≥36px touch height */
                font-size: var(--text-2xs);
                border-radius: 6px 6px 0 0;
                min-height: 36px;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .chart-header h2 {
                font-size: var(--text-lg);
            }
            .chart-title-btn {
                font-size: var(--text-sm);
                padding: var(--space-1) var(--space-1);
            }
            .stats-grid {
                grid-template-columns: repeat(2, 1fr);
            }
            .stat-card {
                padding: var(--space-2);
            }
            .stat-card .value {
                font-size: var(--text-lg);
            }
            .stat-card .label {
                font-size: var(--text-2xs);
            }
            .toggle-container {
                gap: var(--space-1);
            }
            .toggle-chip {
                font-size: var(--text-xs);
                padding: var(--space-2) var(--space-3);  /* boosted from 0.25/0.45 */
                min-height: 36px;
                display: inline-flex;
                align-items: center;
            }
            .autocomplete-item {
                /* Boost touch height for fingers — keep visual density via
                   padding-only growth (no font-size change) */
                padding: var(--space-4) var(--space-4);  /* boosted from 0.65rem */
                min-height: 44px;
            }
            .region-chip {
                font-size: var(--text-xs);
                padding: var(--space-2) var(--space-2);  /* boosted from 0.2/0.4 */
                min-height: 32px;
                display: inline-flex;
                align-items: center;
            }
            .category-qs-btn {
                font-size: var(--text-2xs);
                padding: var(--space-2) var(--space-2);  /* boosted from 0.2/0.4 */
                min-height: 32px;
                display: inline-flex;
                align-items: center;
            }
            .filter-chip {
                /* Keep dense visually but ensure removable × is finger-tappable */
                padding: var(--space-2) var(--space-3);
                min-height: 32px;
            }
            .filter-chip .remove-chip {
                /* Larger hit area for the × dismiss control */
                padding: var(--space-1) var(--space-2);
                min-width: 24px;
                min-height: 24px;
                display: inline-flex;
                align-items: center;
                justify-content: center;
            }
            .chart-wrap { height: 300px; }
            .controls-row-secondary {
                padding: var(--space-2) var(--space-3);
            }
            .export-btn, .reset-zoom-btn {
                font-size: var(--text-xs);
                padding: var(--space-2) var(--space-3);  /* boosted from 0.25/0.45 for touch */
                min-height: 36px;
            }
            .region-chip {
                font-size: var(--text-xs);
                padding: var(--space-1) var(--space-2);
            }
            .category-qs-btn {
                font-size: var(--text-2xs);
                padding: var(--space-1) var(--space-2);
            }
            .category-qs-label {
                font-size: var(--text-2xs);
            }
            /* Year range picker — on phone widths the slider is too cramped
               for reliable touch dragging of the thumbs on a narrow track,
               so we hide both the track/thumbs and the "Years:" label.
               The dropdown <select>s remain as the primary year-picker UI;
               iOS/Android render their native wheel/dropdown pickers for
               an excellent small-screen experience. Desktop + tablet still
               show the slider. */
            /* Build zzzr (2026-07-02): keep the whole year row on ONE line on
               phones — the two year pickers + Range/Single toggle + presets
               caret. Previously the caret (and, at ≤360px, the toggle) wrapped
               to a second line. The trims below (tighter gaps, dash reserve,
               select-wrap + toggle padding, no caret margin) fit it on a single
               centered row down to ~360px; below that it wraps gracefully. */
            .year-range-container {
                padding: var(--space-2) var(--space-3);
                gap: 6px;
                justify-content: center;
            }
            .year-range-container .year-range-label,
            .year-range-container .year-range-slider {
                display: none;
            }
            /* Make year-select dropdowns more prominent since they're now the primary year UI */
            .year-range-values {
                font-size: var(--text-md);
                gap: var(--space-1);
            }
            /* Dash separator: drop the base 3ch reserve down to the glyph width */
            .year-range-values > span:not(.year-select-wrap) {
                min-width: 1ch;
            }
            .year-select-wrap {
                padding: var(--space-1) var(--space-3) var(--space-1) 6px;
                background: var(--card);
                border: 1px solid var(--border);
            }
            /* Range/Single toggle: trim horizontal padding (label width is the
               same; keeps the row single-line without shrinking tap height) */
            .year-range-mode-toggle .year-mode-btn {
                padding-left: 9px;
                padding-right: 9px;
            }
            /* Presets caret sits inline via the container gap, not its own margin */
            .v8-presets-wrap {
                margin-left: 0;
            }
            /* Year range thumbs — no longer visible at ≤480px,
               so the enlarged-thumb rules from the 768px block are moot here.
               Keeping this empty selector as documentation. */
            /* Grouped legend compact on phone */
            .chart-legend.legend-grouped {
                gap: var(--space-2) var(--space-3);
            }
            .legend-mfr-header {
                font-size: var(--text-2xs);
            }
            .legend-family-label {
                font-size: var(--text-2xs);
            }
            .legend-item {
                font-size: var(--text-2xs);
            }
            .legend-color {
                width: 8px;
                height: 8px;
            }
            /* Compare controls compact */
            .controls-row-secondary select {
                font-size: var(--text-xs);
                padding: var(--space-1) var(--space-2);
            }
            .controls-row-label {
                font-size: var(--text-xs);
            }
            /* Chart branding */
            .chart-branding {
                flex-direction: column;
                align-items: flex-start;
                gap: var(--space-2);
            }
            .chart-branding img {
                width: 130px;
            }
            .click-hint {
                font-size: var(--text-2xs);
            }
            /* Customer filter bar compact */
            .customer-filter-bar {
                padding: var(--space-2);
            }
            .filter-bar-header h3 {
                font-size: var(--text-base);
            }
            .customer-search-input {
                font-size: var(--text-sm);
            }
            /* Footer */
            .footer {
                font-size: var(--text-sm);
            }
            /* Table responsive */
            .table-container {
                overflow-x: auto;
                -webkit-overflow-scrolling: touch;
            }
            .table-container table {
                font-size: var(--text-xs);
            }
            /* Time Scale select compact */
            select.select-sm {
                font-size: var(--text-xs);
                padding: var(--space-1) var(--space-2);
            }
            /* Exclude button larger for touch */
            .ac-exclude-btn {
                width: 24px;
                height: 24px;
                font-size: var(--text-md);
                opacity: 0.6;
            }
            /* Autocomplete items taller for touch */
            .autocomplete-item {
                padding: var(--space-3) var(--space-3);
            }
            /* Filter chips compact */
            .filter-chip {
                font-size: var(--text-xs);
                padding: var(--space-1) var(--space-2);
            }
            /* ── Bar layout sub-toggle (Stacked / Side-by-Side) on phone ─
               Sits to the left of the main 5 tabs. On narrow widths the
               whole .view-tabs strip wraps if needed; the sub-toggle
               buttons get touch-friendly heights and slightly smaller
               type without losing legibility. */
            .bar-layout-toggle {
                gap: var(--space-1);
                margin-right: var(--space-1);
                padding-right: var(--space-1);
            }
            .bar-layout-btn {
                padding: var(--space-2) var(--space-2);
                font-size: var(--text-2xs);
                min-height: 32px;
                border-radius: var(--radius-md);
            }
            /* Mobile: the chart-view-toggle (Manufacturers / Customers) gets
               the same compact treatment as the bar-layout sub-toggle —
               smaller gap, slightly tighter type. The shared .view-tab
               styling already handles padding/font, so we only adjust the
               container spacing here. The Customers/Manufacturers labels
               stay readable since they're short words. */
            .chart-view-toggle {
                gap: var(--space-1);
                margin-right: var(--space-1);
                padding-right: var(--space-1);
            }
            .chart-view-divider {
                /* Hide divider on mobile when the strip wraps — same
                   reasoning as the bar-layout divider rule below. */
                display: none;
            }
            /* Allow the view-tabs strip to wrap if all the content can't
               fit on a single line — happens on very narrow phones when
               Bars view exposes the sub-toggle alongside 5 tabs. The
               wrapping keeps everything reachable without horizontal
               scroll, and the chart-container's :has(.view-tabs) margin
               accommodates a 2-row strip. */
            .view-tabs {
                flex-wrap: wrap;
                row-gap: var(--space-1);
                justify-content: flex-end;
            }
            /* When sub-toggle wraps to its own line, give it a tiny gap
               so the divider doesn't visually merge with the next row. */
            .bar-layout-divider {
                display: none;  /* divider would be confusing when wrapped */
            }
            /* ── Customer legend chips on phone ─────────────────────────
               Brand-colored chips with the 3-dot color toggle. On mobile
               we keep dots always visible (per Decision 3), boost touch
               heights, and ensure chips wrap nicely. */
            .customer-chip {
                padding: var(--space-2) var(--space-3);
                font-size: var(--text-xs);
                min-height: 36px;
            }
            .customer-chip-group-toggle {
                width: 18px;
                height: 18px;
                min-width: 18px;
                font-size: var(--text-xs);
                /* Touch-friendly outer hit area */
                padding: var(--space-1);
                margin: -4px 0;
                box-sizing: content-box;
            }
            /* ── Customer empty-state overlay on phone ──────────────────
               The arrow is large by default; scale it down for narrow
               screens where the chart-wrap height is also smaller. */
            .customer-empty-state-content {
                padding: var(--space-4) var(--space-3);
                max-width: 88%;
            }
            .customer-empty-arrow {
                width: 44px;
                height: 64px;
                margin-bottom: var(--space-3);
            }
            .customer-empty-title {
                font-size: var(--text-lg);
            }
            .customer-empty-subtitle {
                font-size: var(--text-sm);
                line-height: 1.4;
                margin-bottom: var(--space-4);
            }
            .customer-empty-cta {
                font-size: var(--text-sm);
                padding: var(--space-2) var(--space-4);
                min-height: 40px;
            }
            /* ── Customer mode notes panel on phone ─────────────────────
               Notes can wrap to multiple lines; keep them readable. */
            .customer-mode-notes {
                font-size: var(--text-xs);
                line-height: 1.4;
            }
            /* ── Customer cap toast on phone ───────────────────────────
               Position above the chart-wrap rather than absolute center
               so it doesn't compete with the chart canvas for attention. */
            .customer-cap-toast {
                font-size: var(--text-sm);
                padding: var(--space-3) var(--space-4);
                max-width: 92%;
                left: 4%;
                right: 4%;
                transform: none;
            }
        }
        /* ═══════════════════════════════════════════════════════════════
           Country Filter UI (parallel to customer-search-container)
           ═══════════════════════════════════════════════════════════════ */
        .country-search-container {
            position: relative;
            width: 280px;
        }
        .country-search-input {
            width: 100%;
            padding: var(--space-2) var(--space-3);
            padding-right: var(--space-6);
            border: 1px solid var(--border);
            border-radius: var(--radius-lg);
            font-size: var(--text-base);
            font-family: var(--font-ui);
            background: var(--card);
            color: var(--text);
        }
        .country-search-input:focus {
            outline: none;
            border-color: var(--tac-blue);
            box-shadow: 0 0 0 3px rgba(30, 144, 255, 0.1);
        }
        .country-search-clear {
            position: absolute;
            right: 0.5rem;
            top: 50%;
            transform: translateY(-50%);
            background: none;
            border: none;
            color: var(--text-muted);
            cursor: pointer;
            font-size: var(--text-md);
            padding: var(--space-1);
            line-height: 1;
            display: none;
        }
        .country-search-clear.visible {
            display: block;
        }
        .country-autocomplete {
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            background: var(--card);
            border: 1px solid var(--border);
            border-top: none;
            border-radius: 0 0 6px 6px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            max-height: 300px;
            overflow-y: auto;
            z-index: 100;
            display: none;
        }
        .country-autocomplete.visible {
            display: block;
        }
        .country-autocomplete .autocomplete-item {
            display: flex;
            align-items: center;
            gap: var(--space-2);
            padding: var(--space-2) var(--space-3);
            cursor: pointer;
            font-size: var(--text-base);
            border-bottom: 1px solid var(--border);
        }
        .country-autocomplete .autocomplete-item:last-child {
            border-bottom: none;
        }
        .country-autocomplete .autocomplete-item:hover {
            background: var(--hover);
        }
        .country-autocomplete .country-iso {
            display: inline-block;
            min-width: 1.75rem;
            padding: var(--space-1) var(--space-2);
            background: var(--tac-blue);
            color: #ffffff;
            border-radius: var(--radius-sm);
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 700;
            text-align: center;
        }
        .country-autocomplete .country-name {
            flex: 1;
            color: var(--text);
        }
        .country-autocomplete .autocomplete-empty {
            padding: var(--space-3) var(--space-3);
            color: var(--text-muted);
            font-size: var(--text-base);
            font-style: italic;
        }

        /* Country filter chip — accent matches default chip (blue tint),
           with a distinct ISO pill and role tag for visual scanning */
        .filter-chip.country {
            background: rgba(30, 144, 255, 0.08);
            border-color: rgba(30, 144, 255, 0.32);
        }
        .filter-chip.country .country-iso {
            display: inline-block;
            min-width: 1.6rem;
            /* Sub-token tight padding — 2px is below --space-1 (4px) by
               design. Used only here and on .chip-role-tag for micro-badges
               where the chip's role is to be near-flush against its text. */
            padding: 2px var(--space-1);
            margin-right: var(--space-1);
            background: var(--tac-blue);
            color: #ffffff;
            border-radius: var(--radius-sm);
            font-family: var(--font-ui);
            font-size: var(--text-xs);
            font-weight: 700;
            text-align: center;
        }
        /* Country flag — replaces .country-iso badge in chips and dropdowns.
           Renders the Unicode flag emoji as a glyph; no background, just
           inherent emoji color. Build dn: inline-flex with center alignment
           handles the emoji-ascender quirk that vertical-align can't fix. */
        .filter-chip.country .country-flag,
        .filter-chip.buyer-country .country-flag {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            margin-right: var(--space-1);
            font-size: 1.1em;
            line-height: 1;
            height: 1em;
        }

        /* ═══════════════════════════════════════════════════════════════
           Buyer Country Filter UI (parallel to country-search, with distinct styling)
           ═══════════════════════════════════════════════════════════════ */
        .country-label-sub {
            font-weight: 400;
            color: var(--text-muted);
            font-size: var(--text-sm);
            font-style: italic;
        }
        .buyer-country-toggle {
            display: inline-block;
            margin-top: var(--space-2);
            font-size: var(--text-sm);
            color: var(--tac-blue);
            cursor: pointer;
            text-decoration: none;
            -webkit-user-select: none;
            user-select: none;
        }
        .buyer-country-toggle:hover {
            text-decoration: underline;
        }
        .buyer-country-wrap {
            display: none;
            margin-top: var(--space-2);
        }
        .buyer-country-wrap.expanded {
            display: block;
        }
        .buyer-country-label {
            display: block;
            margin-bottom: var(--space-2);
        }
        /* Buyer autocomplete — give the ISO pill a different accent so users see
           they're filtering buyer country vs operator country */
        .buyer-country-search-container .country-autocomplete .country-iso,
        .country-iso.buyer {
            background: var(--tac-gold, #feab40);
            color: #1a1a1a;
        }
        /* Buyer-country filter chip — gold accent to distinguish from
           operator-country chip (same shape/size as the unified chip base) */
        .filter-chip.buyer-country {
            background: rgba(254, 171, 64, 0.1);
            border-color: rgba(254, 171, 64, 0.45);
        }
        .filter-chip.buyer-country .country-iso {
            background: var(--tac-gold, #feab40);
            color: #1a1a1a;
        }
        /* Role tag — tiny badge inside chip telling user "operator" vs "buyer" */
        .chip-role-tag {
            display: inline-block;
            margin-left: var(--space-1);
            /* Sub-token tight padding — see .country-iso comment above */
            padding: 2px var(--space-1);
            background: rgba(0, 0, 0, 0.15);
            color: var(--text-muted);
            border-radius: var(--radius-sm);
            font-size: var(--text-2xs);
            font-weight: 600;
            text-transform: lowercase;
            letter-spacing: 0.02em;
        }
        .filter-chip.country .chip-role-tag {
            background: rgba(30, 144, 255, 0.18);
            color: var(--tac-blue);
        }
        .filter-chip.buyer-country .chip-role-tag {
            background: rgba(254, 171, 64, 0.28);
            color: #8a5a00;
        }

        /* Filter composition note — explains two-filter semantic (operator AND buyer) */
        .filter-composition-note {
            font-size: var(--text-sm);
            color: var(--text);
            padding: var(--space-1) var(--space-2);
            border-left: 2px solid var(--tac-gold, #feab40);
            line-height: 1.4;
        }
        .filter-composition-note strong {
            color: var(--tac-blue);
            font-weight: 600;
        }

/* ═════════════════════════════════════════════════════════════════════
   V8.0 PHASE 1 — Unified control-bar UI
   Activated when body.v8-ui-enabled is set (via ?v8=1 or localStorage).
   All V8 styles scoped under #v8-ui to prevent any V7 class collisions.
   ───────────────────────────────────────────────────────────────────── */

/* Hide V8 UI by default; show only when feature flag is on */
#v8-ui { display: none; }
body.v8-ui-enabled #v8-ui { display: block; }

/* Beta indicator strip — present whenever V8 is active so editors
   know they're in preview UI alongside V7 controls (Phase 1 has both
   visible; later phases hide V7 controls). */

/* Control bar panel */
#v8-ui .control-bar {
    background: var(--v8-surface-section);
    border: 1px solid var(--v8-border-soft);
    border-left: 2px solid var(--v8-accent-x);
    border-radius: 6px;
    padding: 22px 24px;
    position: relative;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.03), 0 1px 3px rgba(0,0,0,0.2);
    margin-bottom: 14px;
    font-family: 'Archivo', system-ui, sans-serif;
}

#v8-ui .primary-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 32px;
    /* Wave D Build 15.h (wz, 2026-05-25): top-align labels. At wide widths
       both selectors are similar height so this is visually equivalent to
       align-items:end; at medium widths (720–1200px) where the X-axis
       chip-strip grows to two tiers, top-aligning keeps the "X-AXIS" and
       "SEGMENT BY" labels on the same Y so the right column doesn't look
       orphaned. */
    align-items: start;
}

#v8-ui .selector { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* Build zzzp (2026-07-02): make the X-axis selector a size-query container so
   the chip strip decides to stack (two tiers) from its OWN available width, not
   a viewport guess. This is the DURABLE fix for the recurring "Variant spills
   out of the strip" bug: the row can only overflow when the strip is narrower
   than the 8 chips' combined min-content (~592px), and that depends on the
   column width (grid, card padding, page margins) — not the viewport. Keying
   the stack off the container width removes the viewport-math fragility that
   caused the wy/wz regressions. See the @container rule below. */
#v8-ui .selector.x-axis { container-type: inline-size; container-name: xaxis; }
#v8-ui .selector-label {
    display: flex; align-items: center; gap: 8px;
    font-weight: 600; font-size: 10px;
    letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--v8-text-muted);
}
#v8-ui .selector-label .dot {
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--v8-accent-x);
}
#v8-ui .selector.segment-by .selector-label .dot { background: var(--v8-accent-segment); }

/* X-axis two-tier chip strip */
#v8-ui .chip-strip {
    display: flex; align-items: stretch; gap: 4px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-soft);
    border-radius: 6px;
    padding: 4px;
    width: 100%;
    /* Build zzzo (2026-07-02): cap the strip so it reads as a cohesive
       segmented control instead of over-stretching on wide/external displays.
       Without this, flex:1 chips grow to ~144px each at 2560px and the short
       labels (Mfr/Cat) float in a sea of dead space. The cap is inert below
       ~1350px viewport (column < cap ⇒ width:100% wins), so the ≤1440px
       layout is unchanged; left-aligned in its column like the other control
       clusters (Scope filters, chart-type strip). */
    max-width: 720px;
}
#v8-ui .chip-strip-tier { display: flex; gap: 4px; flex: 1; min-width: 0; }
/* Wave D Build 10 (wg, 2026-05-24): both tiers now have 4 chips each
   (Time/Customer/Mfr/Cat above the divider, Region/Country/Family/Variant
   below). Setting both tier flexes to 1 produces equal-width chips across
   both rows. Region moved down from primary because it pairs naturally
   with Country as the "geo" half of the drill tier; the new top row reads
   cleanly as the who/what/when dims. */
#v8-ui .chip-strip-tier.primary { flex: 1; }
#v8-ui .chip-strip-tier.secondary { flex: 1; }
#v8-ui .chip-strip-divider {
    width: 1px; background: var(--v8-border-strong);
    margin: 4px 8px; flex-shrink: 0;
}

#v8-ui .chip {
    flex: 1;
    padding: 8px 14px;
    font-family: inherit;
    font-weight: 500; font-size: 13px;
    /* Wave D Build 9 (wf, 2026-05-24): bumped from var(--v8-text-secondary) to var(--v8-text-primary) for
       brighter resting state. With the secondary-tier dim removed (we) all
       8 x-axis chips now share this color; the brighter base reads more
       confidently as an actionable control. Hover bumped to white. */
    color: var(--v8-text-primary);
    background: none;
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms, box-shadow 150ms;
    text-align: center;
    white-space: nowrap;
    position: relative;
}
#v8-ui .chip:hover { background: rgba(255,255,255,0.04); color: #ffffff; }
#v8-ui .chip.active {
    background: var(--v8-accent-x);
    color: white;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 2px rgba(0,0,0,0.3);
}
/* Wave D Build 8 (build we, 2026-05-24): the secondary-tier dim styling
   was a vestige from when country/family/variant weren't yet activated as
   x-axis dims. As of Wave D Build 7 (wd), all three have shipped cells:
   country has 5 (co:tot, co:m, co:cat, co:f, co:v), family has 4 (f:tot,
   f:v, f:r, f:co), variant has 3 (v:tot, v:r, v:co). Removing the size,
   padding, and color overrides — all 8 x-axis chips now render at visual
   parity. The tier layout (.primary / .secondary divs) remains as a
   structural grouping (Time/Customer/Mfr/Cat/Region as "core" dims,
   Country/Family/Variant as "drill" dims), separated by the divider, but
   no longer visually demoted. */

/* Pulse animation when high-cardinality X is activated */
@keyframes v8-chip-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(254,171,64,0.45); }
    50%  { box-shadow: 0 0 0 6px rgba(254,171,64,0); }
    100% { box-shadow: 0 0 0 0 rgba(254,171,64,0); }
}
#v8-ui .chip.pulse-once { animation: v8-chip-pulse 900ms cubic-bezier(0.32,0.72,0,1) 100ms 1; }

/* Segment-By dropdown */
#v8-ui .dropdown { position: relative; width: 100%; }
#v8-ui .dropdown-trigger {
    width: 100%;
    display: flex; justify-content: space-between; align-items: center;
    padding: 10px 14px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 6px;
    font-family: inherit;
    font-weight: 500; font-size: 14px;
    color: var(--v8-text-primary);
    cursor: pointer;
    transition: border-color 150ms, background 150ms;
}
#v8-ui .dropdown-trigger:hover {
    border-color: rgba(255,255,255,0.16);
    background: var(--v8-control-hover);
}
#v8-ui .dropdown-trigger.open { border-color: var(--v8-accent-x); }
#v8-ui .dropdown-trigger .chevron {
    width: 14px; height: 14px;
    color: var(--v8-text-muted);
    transition: transform 200ms;
}
#v8-ui .dropdown-trigger.open .chevron { transform: rotate(180deg); color: var(--v8-text-primary); }

#v8-ui .dropdown-menu {
    position: absolute; top: calc(100% + 4px);
    left: 0; right: 0;
    background: var(--v8-surface-dropdown);
    border: 1px solid var(--v8-border-strong);
    border-radius: 6px;
    padding: 4px;
    list-style: none; margin: 0;
    z-index: 100;
    opacity: 0; transform: translateY(-4px);
    pointer-events: none;
    transition: opacity 150ms, transform 150ms;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}
#v8-ui .dropdown-menu.open { opacity: 1; transform: translateY(0); pointer-events: auto; }
#v8-ui .dropdown-item {
    display: flex; justify-content: space-between; align-items: center;
    padding: 9px 12px;
    font-family: inherit; font-size: 13px;
    color: var(--v8-text-secondary);
    background: none; border: none;
    border-radius: 2px;
    width: 100%; text-align: left;
    cursor: pointer;
    transition: background 150ms, color 150ms;
}
#v8-ui .dropdown-item:hover { background: rgba(255,255,255,0.05); color: var(--v8-text-primary); }
#v8-ui .dropdown-item.selected { color: var(--v8-accent-x); background: rgba(24,144,255,0.08); }
#v8-ui .dropdown-item.disabled {
    color: var(--v8-text-disabled); cursor: not-allowed; pointer-events: none;
}
#v8-ui .dropdown-item .item-tag {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px; color: var(--v8-text-disabled);
    padding: 2px 6px;
    background: var(--v8-surface-control);
    border-radius: 2px;
    border: 1px solid var(--v8-border-soft);
}

/* Auto-caption */
#v8-ui .auto-caption {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px dashed var(--v8-border-soft);
    font-family: 'Source Serif 4', Georgia, serif;
    font-style: italic;
    font-size: 13px;
    color: var(--v8-text-muted);
    line-height: 1.5;
    transition: opacity 200ms;
}
#v8-ui .auto-caption strong {
    color: var(--v8-text-primary); font-style: normal;
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 500;
}
#v8-ui .v8-new-tag {
    color: var(--v8-accent-segment); font-style: normal;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px; letter-spacing: 0.05em;
    padding-left: 6px;
}
#v8-ui .v8-phase2-tag {
    color: #f35841; font-style: normal;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px; letter-spacing: 0.05em;
    padding-left: 6px;
}
#v8-ui .v8-legibility-tip {
    color: var(--v8-text-disabled); font-size: 12px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-style: normal;
    display: block; margin-top: 4px;
}

/* "Pick up where you left off" prompt */
#v8-resume-prompt[hidden] { display: none; }
#v8-resume-prompt {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.4);
    backdrop-filter: blur(4px);
    z-index: 9999;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    animation: v8-fade-in 200ms ease-out;
}
@keyframes v8-fade-in { from { opacity: 0; } to { opacity: 1; } }
.v8-resume-card {
    background: #161c24;
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 6px;
    padding: 28px 32px;
    max-width: 520px; width: 100%;
    font-family: 'Archivo', system-ui, sans-serif;
    box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}
.v8-resume-title {
    font-family: 'Source Serif 4', Georgia, serif;
    font-size: 22px;
    font-weight: 400;
    color: #eeeeee;
    margin: 0 0 14px;
}
.v8-resume-summary {
    font-family: 'Source Serif 4', Georgia, serif;
    font-style: italic;
    font-size: 14px;
    color: #c3c3c3;
    line-height: 1.55;
    margin-bottom: 6px;
}
.v8-resume-summary strong { color: #eeeeee; font-style: normal; font-family: 'Archivo'; font-weight: 500; }
.v8-resume-filters {
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
    color: #959595;
    font-size: 13px;
    font-family: 'Source Serif 4', Georgia, serif;
}
.v8-resume-filters li {
    padding: 2px 0;
}
.v8-resume-filters li::before { content: '· '; color: #5c5c5c; }
.v8-resume-timestamp {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: #5c5c5c;
    margin: 16px 0 22px;
    letter-spacing: 0.05em;
}
.v8-resume-buttons { display: flex; justify-content: flex-end; gap: 10px; }
.v8-resume-btn {
    padding: 9px 18px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 13px;
    font-weight: 500;
    border-radius: 6px;
    cursor: pointer;
    border: 1px solid transparent;
    transition: all 150ms;
}
.v8-resume-btn.secondary {
    background: none;
    border-color: rgba(255,255,255,0.14);
    color: #c3c3c3;
}
.v8-resume-btn.secondary:hover { border-color: rgba(255,255,255,0.28); color: #eeeeee; }
.v8-resume-btn.primary {
    background: #1870ff;
    color: white;
    box-shadow: 0 1px 3px rgba(24,144,255,0.4);
}
.v8-resume-btn.primary:hover { background: #1565ec; }

/* Mobile */
@media (max-width: 720px) {
    /* Belt-and-suspenders body-level horizontal scroll lock — prevents any
       overflowing element anywhere from causing whole-page lateral drift. */
    html, body {
        overflow-x: hidden;
        max-width: 100vw;
    }

    /* Build 20260508yd: viewport containment for ALL dropdowns/popovers.
       Root cause of the iOS Safari "page shifts right and won't come back"
       bug: a dropdown anchored in a right-column control (min-width 240px,
       left:0) extends past the right viewport edge, making the layout
       horizontally scrollable; Safari then sticks the viewport shifted right.
       Fix: clamp every menu/panel to the viewport width and re-anchor the
       right-side ones so they open inward (toward the left) instead of
       overflowing off-screen. The body lock above is the safety net; this is
       the actual containment so nothing overflows in the first place. */
    #v8-ui .v8-pill-dropdown,
    #v8-ui .dropdown-menu {
        /* Never wider than the viewport minus a small gutter on each side. */
        max-width: calc(100vw - 16px);
        /* Re-anchor to the trigger's right edge so the panel grows leftward,
           keeping it on-screen for right-column controls. left:auto cancels
           the default left:0. */
        left: auto;
        right: 0;
        /* min-width could still exceed the clamp on very narrow phones; let
           the panel shrink to fit. */
        min-width: 0;
    }
    /* The v8-pill-dropdown panels carry their own min-width:240px; override it
       so the clamp can win on narrow screens. */
    #v8-ui .v8-pill-dropdown {
        width: max-content;
    }
    /* The custom color picker popover (customer + segment) must also stay in
       view; it already centers on very narrow phones via .ccp-centered, but
       cap its width as a guard for the tethered case too. */
    .customer-color-picker {
        max-width: calc(100vw - 16px);
    }

    #v8-ui .control-bar { padding: 18px 16px; }
    .v8-resume-card { padding: 20px; }

    /* Wave D Build 15.g (wy, 2026-05-25): iOS Safari auto-zooms to any
       focused input whose computed font-size is below 16px. At our base
       13px (--text-base) the page zooms in when the user taps the customer
       search / country search / table search inputs, breaking the "feels
       like an app" experience. Bump font-size to 16px on mobile only;
       desktop keeps the original 13px sizing untouched. */
    input[type="text"],
    input[type="search"],
    input[type="email"],
    input[type="number"],
    input[type="tel"],
    input[type="url"],
    select,
    textarea {
        font-size: 16px !important;
    }
}

/* X-axis chip strip — stack to two tiers (4+4) when the strip's own container
   is too narrow to hold all 8 chips + divider in one row. Build zzzp
   (2026-07-02): moved from a viewport @media (max-width:1200px) to a size
   @container query so the trigger tracks the strip's ACTUAL available width.
   The 8 chips' combined min-content is ~592px; we stack below 620px (≈28px
   safety margin) so "Variant" can never spill past the strip border — the bug
   the old viewport breakpoint missed in the ~1200–1340px range (row mode over
   a <592px column). The vertical divider rotates to a horizontal rule between
   the two stacked tiers. Row mode (≥620px container) keeps the vertical
   divider; on very wide displays the strip caps at max-width:720px above. */
@container xaxis (max-width: 620px) {
    #v8-ui .chip-strip {
        flex-direction: column;
        gap: 6px;
    }
    #v8-ui .chip-strip-tier {
        flex: 0 0 auto;
        flex-wrap: wrap;
    }
    #v8-ui .chip-strip-tier.primary,
    #v8-ui .chip-strip-tier.secondary { flex: 0 0 auto; }
    #v8-ui .chip-strip-divider {
        width: 100%;
        height: 1px;
        margin: 2px 0;
    }
    #v8-ui .chip { flex: 1 1 auto; min-width: max-content; }
}

@media (max-width: 720px) {
    /* Real mobile: stack the primary-row entirely (X-axis above Segment By).
       X-axis then spans full width; the @container rule above re-evaluates
       against that width and keeps the chip strip in its two-tier form. */
    #v8-ui .primary-row {
        grid-template-columns: 1fr;
        gap: 18px;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 2 — chart-type strip + utilities (in V8 control bar)
   ───────────────────────────────────────────────────────────────────── */

/* ──────────────────────────────────────────────────────────────────────
   V8 PHASE 1.5 SESSION 2 — Customer-view controls row.
   Inline below chip strip when X-axis = Customer. Drives V7 state via
   click/change dispatch on V7's hidden controls.
   ────────────────────────────────────────────────────────────────────── */

#v8-ui .v8-cust-row {
    margin-top: 14px;
    padding: 12px 14px;
    background: rgba(255,255,255,0.02);
    border: 1px solid var(--v8-border-soft);
    border-radius: 6px;
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
#v8-ui .v8-cust-divider {
    width: 1px;
    align-self: stretch;
    background: var(--v8-border-soft);   /* 2026-10-09: themed (was alpha-white, invisible in light) */
    margin: 0 2px;
}
#v8-ui .v8-cust-control {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;
}
/* Build zzzs (2026-07-02): mobile treatment for the Customer-view controls row
   (visible when X-axis = Customer). This was the one V8 control cluster with no
   phone tuning: the fixed 140px slider + the full-height vertical divider
   wrapped chaotically. Stack the controls in a column, turn the vertical
   divider into a horizontal rule, and let the slider span the row. */
@media (max-width: 720px) {
    #v8-ui .v8-cust-row { flex-direction: column; align-items: stretch; gap: 10px; }
    #v8-ui .v8-cust-divider { width: 100%; height: 1px; align-self: auto; margin: 2px 0; }
    #v8-ui .v8-cust-control { flex-wrap: wrap; }
    #v8-ui .v8-cust-slider { width: auto; flex: 1 1 auto; min-width: 0; }
}
#v8-ui .v8-cust-label {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #777777;
    white-space: nowrap;
}
#v8-ui .v8-cust-label-suffix { color: var(--v8-text-muted); text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 11px; }

/* Top-N slider */
#v8-ui .v8-cust-topn-value {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 14px;
    font-weight: 600;
    color: var(--tac-blue);
    min-width: 22px;
    text-align: right;
}
#v8-ui .v8-cust-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 140px;
    height: 6px;
    background: rgba(255,255,255,0.08);
    border-radius: 2px;
    cursor: pointer;
    margin: 0 4px;
}
/* Thumb — matches .year-range-thumb single-year style. 18×18 circle with
   V8 dark interior, 2px TAC blue border, drop shadow. Scales on hover/active
   like the year-range thumb so the two sliders feel like siblings. */
#v8-ui .v8-cust-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: #1a1f29;
    border: 2px solid var(--tac-blue);
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
    transition: transform 100ms, box-shadow 100ms;
}
#v8-ui .v8-cust-slider::-webkit-slider-thumb:hover {
    transform: scale(1.1);
    box-shadow: 0 2px 6px rgba(0,0,0,0.5);
}
#v8-ui .v8-cust-slider:active::-webkit-slider-thumb {
    transform: scale(1.15);
    box-shadow: 0 2px 8px rgba(0,0,0,0.55);
}
#v8-ui .v8-cust-slider::-moz-range-thumb {
    width: 18px; height: 18px;
    border-radius: 50%;
    background: #1a1f29;
    border: 2px solid var(--tac-blue);
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
    transition: transform 100ms, box-shadow 100ms;
}
#v8-ui .v8-cust-slider::-moz-range-thumb:hover {
    transform: scale(1.1);
    box-shadow: 0 2px 6px rgba(0,0,0,0.5);
}
#v8-ui .v8-cust-slider:active::-moz-range-thumb {
    transform: scale(1.15);
    box-shadow: 0 2px 8px rgba(0,0,0,0.55);
}
#v8-ui .v8-cust-slider::-moz-range-track {
    height: 6px;
    background: rgba(255,255,255,0.08);
    border-radius: 2px;
    border: none;
}
#v8-ui .v8-cust-slider-bound {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    color: var(--v8-text-disabled);
    min-width: 14px;
    text-align: center;
}

/* Segmented button groups (Sort, Labels) — matches chart-type-btn style */
#v8-ui .v8-cust-btn-group {
    display: flex;
    gap: 1px;
    background: var(--v8-border-soft);
    border-radius: 2px;
    padding: 1px;
}
#v8-ui .v8-cust-btn {
    padding: 5px 10px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 500;
    font-size: 11px;
    color: var(--v8-text-muted);
    background: var(--v8-surface-control);
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms;
    white-space: nowrap;
}
#v8-ui .v8-cust-btn:hover { color: var(--v8-text-primary); }
#v8-ui .v8-cust-btn.active {
    background: var(--tac-blue);
    color: white;
}
/* V8.1 #4: customer-axis labels auto-fell back to ICAO because names don't fit.
   ICAO reads as active-but-automatic (dashed inner ring); Name shows as the
   muted base choice that returns when the chart is wider. */
#v8-ui .v8-cust-btn.auto-active {
    background: var(--tac-blue);
    color: white;
    outline: 1px dashed rgba(255, 255, 255, 0.75);
    outline-offset: -3px;
}
#v8-ui .v8-cust-btn.auto-base {
    background: transparent;
    color: var(--v8-text-muted);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
}

/* Wave D Build 18 (xh): Time Scale granularity pill — segmented control
   inside the X-Axis selector, visible only when X = Time. Shares the
   v8-cust-btn aesthetic (dark segments, TAC-blue active fill). Hidden by
   default; renderV8Visuals() toggles display based on v8State.x === 't'. */
#v8-ui .v8-timescale {
    display: none;            /* shown by renderV8Visuals when X = Time */
    gap: 1px;
    background: var(--v8-border-soft);
    border-radius: 2px;
    padding: 1px;
    width: fit-content;
}
#v8-ui .v8-timescale.visible { display: flex; }
#v8-ui .v8-ts-btn {
    padding: 5px 11px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 500;
    font-size: 11px;
    color: var(--v8-text-muted);
    background: var(--v8-surface-control);
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms;
    white-space: nowrap;
}
#v8-ui .v8-ts-btn:hover { color: var(--v8-text-primary); }
#v8-ui .v8-ts-btn.active {
    background: var(--tac-blue);
    color: white;
}

/* Cumulative alignment sub-mode (Absolute / Relative) — mirrors the timescale
   pill; shown by renderV8Visuals only when the Cumulative chart-type is active.
   Lives under the chart-type strip in the X-axis column (flex-start, no stretch). */
#v8-ui .v8-cumulative-mode {
    display: none;
    gap: 1px;
    background: var(--v8-border-soft);
    border-radius: 2px;
    padding: 1px;
    width: fit-content;
    align-self: flex-start;
    margin-top: 8px;
}
#v8-ui .v8-cumulative-mode.visible { display: flex; }
#v8-ui .v8-cmode-btn {
    padding: 5px 11px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 500;
    font-size: 11px;
    color: var(--v8-text-muted);
    background: var(--v8-surface-control);
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms;
    white-space: nowrap;
}
#v8-ui .v8-cmode-btn:hover { color: var(--v8-text-primary); }
#v8-ui .v8-cmode-btn.active { background: var(--tac-blue); color: white; }
/* Cumulative options row: alignment radios (blue) on the left, then the Historical
   render toggles — Stacked area / Share % — as a separate group (gold when on, a
   different axis: line default → area/mix). They apply to Historical only, so they
   dim out under Head-to-head. */
#v8-ui .v8-cmode-group { display: inline-flex; gap: 1px; }
#v8-ui .v8-cum-render-group { margin-left: 7px; }
#v8-ui .v8-cum-render-btn.active { background: var(--tac-gold); color: #0d1117; }
#v8-ui .v8-cum-render-btn.disabled { opacity: 0.4; pointer-events: none; }
/* Dots toggle — a display option for the cumulative LINE renders. Active (dots
   shown) is the default; dims out when a non-line render (area/share) is active. */
#v8-ui .v8-cum-dots-group { margin-left: 7px; }
#v8-ui .v8-cum-dots-btn.active { background: var(--v8-surface-hover, rgba(255,255,255,0.12)); color: var(--v8-text-primary); }
#v8-ui .v8-cum-dots-btn.disabled { opacity: 0.4; pointer-events: none; }

/* Cluster groups toggle — V8-styled switch */
#v8-ui .v8-cust-toggle {
    position: relative;
    display: inline-block;
    width: 30px;
    height: 16px;
    cursor: pointer;
}
#v8-ui .v8-cust-toggle input { opacity: 0; width: 0; height: 0; }
#v8-ui .v8-cust-toggle-slider {
    position: absolute; inset: 0;
    /* 2026-10-09: themed track — the alpha-white track vanished on the light
       page, leaving the OFF toggle as a bare black knob (Jon's screenshot). */
    background: var(--v8-border-strong);
    border-radius: 6px;
    transition: background 150ms;
}
#v8-ui .v8-cust-toggle-slider::before {
    content: '';
    position: absolute;
    top: 2px; left: 2px;
    width: 12px; height: 12px;
    background: var(--v8-text-primary);
    border-radius: 50%;
    transition: transform 150ms;
}
#v8-ui .v8-cust-toggle input:checked + .v8-cust-toggle-slider { background: var(--tac-blue); }
#v8-ui .v8-cust-toggle input:checked + .v8-cust-toggle-slider::before { transform: translateX(14px); }

/* Hide V7's customerXAxisControls when V8 UI is active — V8's row supersedes
   it and drives the same state vars. Restored automatically when V8 is
   disabled (?v8=0). Will be fully sunset in Session 5. */
body.v8-ui-enabled #customerXAxisControls {
    display: none !important;
}

#v8-ui .chart-shape-row {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--v8-border-soft);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
/* EXPERIMENT (build zzzw): compact the View menu. The oversized Segment By
   dropdown (was ~775px, filling the whole right column) is capped, and the
   reorder script tucks the chart-type strip + utilities up under it — filling
   the ~105px of dead space in the right column instead of a full-width row
   below the caption, cutting the View menu's height. Inside the column the
   dashed divider/top spacing is dropped (the column's flex gap handles it). */
#v8-ui .selector.segment-by .dropdown { max-width: 320px; }
/* Chart-type strip now lives in the (flex-column) X-axis selector; stop it
   stretching to full column width, which left the strip's own segmented-control
   background trailing as a lighter bar fragment to the right of "Compare". */
#v8-ui .selector.x-axis .chart-type-strip { align-self: flex-start; }
/* Utilities (reset / volume-labels / export) pinned to the lower-right corner of
   the View menu. The reorder script moves them out of the old chart-shape row to
   be a direct child of the control-bar (which is already position:relative). */
#v8-ui .control-bar > .chart-utilities {
    position: absolute;
    right: 24px;
    bottom: 20px;
}
/* Reserve room on the caption's right so its text can't run under the corner
   utilities on long descriptors. */
#v8-ui .auto-caption { padding-right: 132px; }
/* 2026-10-09 (Jon: "resolve the overlap conflicts"): when a per-axis control row
   (#v8-cust-row on the customer axis / segment, #recordLevelXAxisControls on the
   country axis) is on screen it is the LAST row of the View menu, and the corner
   pin put the utilities on top of its toggles ("Cluster groups", "Historical
   names") at every width — on one line at 1280, on the wrapped line below that.
   app.js (_syncControlBarXRow) stamps .has-xrow on the control bar whenever either
   row is displayed; the utilities then leave the corner and take their own
   right-aligned line under the row, and the caption no longer reserves the
   corner. The corner pin stays for every other axis. */
#v8-ui .control-bar.has-xrow > .chart-utilities { position: static; justify-content: flex-end; margin-top: 10px; }
#v8-ui .control-bar.has-xrow .auto-caption { padding-right: 0; }

/* Build zzzzu (2026-07-05): the chart-type strip mirrors the X-axis chip-strip above
   it — a single bordered container with transparent chips that wrap CLEANLY (even 4px
   gaps, uniform background) instead of a segmented control whose shared background went
   ragged on a stubby wrapped row. Same container width + rounding, so the two controls
   read as one tidy stack in the left column. */
#v8-ui .chart-type-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    width: 100%;
    max-width: 720px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-soft);
    border-radius: 6px;
    padding: 4px;
}
#v8-ui .chart-type-btn {
    padding: 6px 12px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 500;
    font-size: 12px;
    color: var(--v8-text-muted);
    background: none;
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms, opacity 150ms;
    white-space: nowrap;
    position: relative;
}
#v8-ui .chart-type-btn:hover { background: rgba(255,255,255,0.04); color: var(--v8-text-primary); }
#v8-ui .chart-type-btn.active {
    background: var(--v8-accent-x);
    color: white;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 2px rgba(0,0,0,0.3);
}
#v8-ui .chart-type-btn.disabled {
    color: var(--v8-text-disabled);
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: auto; /* keep hoverable so tooltip fires */
}
#v8-ui .chart-type-btn.disabled:hover { color: var(--v8-text-disabled); }

/* Tooltip on disabled chart-type buttons */
#v8-ui .chart-type-tooltip {
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--v8-control-hover);
    color: var(--v8-text-secondary);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 11px;
    padding: 5px 9px;
    border-radius: 2px;
    border: 1px solid rgba(255,255,255,0.08);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 150ms;
    z-index: 40;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
#v8-ui .chart-type-tooltip::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-bottom-color: var(--v8-control-hover);
}
#v8-ui .chart-type-btn.disabled:hover .chart-type-tooltip { opacity: 1; }

/* Chart utilities (Reset / Vol Labels / Export) */
#v8-ui .chart-utilities {
    display: flex;
    gap: 6px;
    position: relative;   /* anchor for the copy-link toast */
}
/* Copy-link confirmation toast — floats just under the utility row */
#v8-ui .v8-copy-toast {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    background: var(--tac-blue);
    color: #fff;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 7px 12px;
    border-radius: 6px;
    white-space: nowrap;
    box-shadow: 0 6px 18px rgba(0,0,0,0.35);
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 180ms ease, transform 180ms ease;
    pointer-events: none;
    z-index: 60;
}
#v8-ui .v8-copy-toast[hidden] { display: none; }
#v8-ui .v8-copy-toast.show { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
    #v8-ui .v8-copy-toast { transition: none; }
}
#v8-ui .util-btn {
    width: 32px;
    height: 32px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--v8-text-muted);
    cursor: pointer;
    transition: border-color 150ms, color 150ms, background 150ms;
    position: relative;
}
#v8-ui .util-btn:hover {
    border-color: rgba(255,255,255,0.20);
    color: var(--v8-text-primary);
}
#v8-ui .util-btn.active {
    background: var(--v8-accent-x);
    border-color: var(--v8-accent-x);
    color: white;
}
#v8-ui .util-btn svg { width: 14px; height: 14px; }
#v8-ui .util-btn-tooltip {
    position: absolute;
    bottom: calc(100% + 6px);
    right: 0;
    background: var(--v8-control-hover);
    color: var(--v8-text-secondary);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 11px;
    padding: 4px 8px;
    border-radius: 2px;
    border: 1px solid rgba(255,255,255,0.08);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 150ms;
    z-index: 30;
}
#v8-ui .util-btn-tooltip kbd {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    color: var(--v8-text-disabled);
    margin-left: 4px;
}
#v8-ui .util-btn:hover .util-btn-tooltip { opacity: 1; }

#v8-ui .util-flash {
    position: absolute;
    inset: -4px;
    border-radius: 6px;
    border: 1px solid var(--v8-accent-x);
    pointer-events: none;
    opacity: 0;
}
#v8-ui .util-btn.flashing .util-flash {
    animation: v8-util-flash 600ms cubic-bezier(0.32,0.72,0,1);
}
@keyframes v8-util-flash {
    0%   { opacity: 0.9; transform: scale(0.96); }
    100% { opacity: 0;   transform: scale(1.10); }
}

/* Mobile — chart-type strip wraps; horizontal scroll caused touch drag
   conflicts where the strip could "float" off-screen. Wrap is more
   touch-friendly: all buttons always visible, no inner-scroll competing
   with page-scroll. */
@media (max-width: 720px) {
    #v8-ui .chart-shape-row {
        flex-direction: column;
        align-items: stretch;
    }
    #v8-ui .chart-type-strip {
        flex-wrap: wrap;
        width: 100%;
    }
    #v8-ui .chart-type-btn {
        flex: 1 1 auto;
        padding: 6px 8px;
        font-size: 11px;
        min-width: max-content;
    }
    #v8-ui .chart-utilities {
        justify-content: flex-end;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 3 — Tallies strip (4-stat dataset summary)
   ───────────────────────────────────────────────────────────────────── */

#v8-ui .v8-tallies {
    display: grid;
    /* Build zzzt (2026-07-03): min column 150→136 so all 11 tally cells fit on
       ONE row at a 13" MacBook Air full-screen width (~1620px grid content on the
       "More Space" scaling, where 11×150 overflowed and Bombardier wrapped). The
       per-attribute trims below (value 22→20, "deliveries" suffix 11→8, cell
       padding 18→10, label tracking 0.14→0.08) shrink the widest cell — TOTAL's
       "50,178 deliveries" — enough to fit the tighter column with ~15px to spare. */
    grid-template-columns: repeat(auto-fit, minmax(136px, 1fr));
    background: var(--v8-surface-section);
    border: 1px solid var(--v8-border-soft);
    border-radius: 6px;
    padding: 14px 4px;
    margin-bottom: 14px;
    column-gap: 0;
    row-gap: 6px;
}
#v8-ui .v8-tally {
    padding: 4px 10px;
    border-right: 1px solid var(--v8-border-soft);
    display: flex;
    flex-direction: column;
    gap: 5px;
    /* Subtle left border — OEM cells override this with their accent color */
    border-left: 2px solid transparent;
    margin-left: -2px;
}
#v8-ui .v8-tally:last-child { border-right: none; }
#v8-ui .v8-tally-value {
    font-family: 'Archivo', system-ui, sans-serif;
    font-variant-numeric: tabular-nums;
    font-size: 20px;
    font-weight: 600;
    color: var(--v8-text-primary);
    line-height: 1.05;
    letter-spacing: -0.015em;
}
#v8-ui .v8-tally-suffix {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 8px;
    font-weight: 400;
    color: var(--v8-text-muted);
    margin-left: 3px;
}
#v8-ui .v8-tally-label {
    font-family: 'Archivo', system-ui, sans-serif;
    font-weight: 600;
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--v8-text-muted);
}

/* OEM tally cell — colored left border + colored value text per MFR_COLORS */
#v8-ui .v8-tally.v8-tally-mfr {
    border-left-width: 2px;
    /* border-left-color set inline from MFR_COLORS[mfr].bg */
}

@media (max-width: 720px) {
    #v8-ui .v8-tallies {
        grid-template-columns: repeat(2, 1fr);
        row-gap: 0;
    }
    #v8-ui .v8-tally {
        padding: 8px 14px;
        border-right: none;
        border-bottom: 1px solid var(--v8-border-soft);
    }
    #v8-ui .v8-tally:nth-child(odd) { border-right: 1px solid var(--v8-border-soft); }
    /* Note: removed :nth-last-child(-n+2) { border-bottom: none } — that
       selector was correct at 4 cells but breaks at 11 cells where the
       last DOM-order pair may not be in the visual last row. Keeping
       border-bottom on all cells; the section's own bottom border
       absorbs the redundant 1px on the last row visually. */
    #v8-ui .v8-tally-value { font-size: 17px; }
    /* Build zzzs: nudge the 9px tally eyebrow up a hair for phone legibility */
    #v8-ui .v8-tally-label { font-size: 10px; }
}

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 4 — Filter section (SCOPE tier, mirror of V7 state)
   ───────────────────────────────────────────────────────────────────── */

#v8-ui .v8-filter-section {
    background: var(--v8-surface-section);
    border: 1px solid var(--v8-border-soft);
    border-left: 2px solid var(--v8-accent-segment);
    border-radius: 6px;
    padding: 16px 20px 18px;
    margin-bottom: 14px;
    position: relative;
    font-family: 'Archivo', system-ui, sans-serif;
}
#v8-ui .v8-filter-eyebrow {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--v8-accent-segment);
    text-transform: uppercase;
    margin-bottom: 12px;
    display: block;
}

/* ── HISTORICAL DATA section — economic overlay controls ─────────────────
   Third menu tier: View = blue, Scope = gold, Historical Data = Airbus red
   (#F4511E, the house Airbus bg from MFR_COLORS). Mirrors .v8-filter-section
   framing: same surface, 2px accent left border, eyebrow typography. */
#v8-ui {
    --v8-accent-histdata: #F4511E;
}
#v8-ui .v8-histdata-section {
    background: var(--v8-surface-section);
    border: 1px solid var(--v8-border-soft);
    border-left: 2px solid var(--v8-accent-histdata);
    border-radius: 6px;
    padding: 16px 20px 18px;
    margin-bottom: 14px;
    position: relative;
    font-family: 'Archivo', system-ui, sans-serif;
}
#v8-ui .v8-histdata-section[hidden] { display: none; }
#v8-ui .v8-histdata-eyebrow {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--v8-accent-histdata);
    text-transform: uppercase;
    margin-bottom: 12px;
    display: block;
}
#v8-ui .v8-histdata-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
}
#v8-ui .v8-histdata-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--v8-text-muted);
    text-transform: uppercase;
}
#v8-ui .v8-histdata-select {
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    color: var(--v8-text);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 13px;
    padding: 7px 10px;
    border-radius: 6px;
    min-width: 260px;
    cursor: pointer;
}
#v8-ui .v8-histdata-select:focus {
    outline: none;
    border-color: var(--v8-accent-histdata);
    box-shadow: 0 0 0 3px rgba(244, 81, 30, 0.18);
}
#v8-ui .v8-histdata-active {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
#v8-ui .v8-histdata-active[hidden] { display: none; }
#v8-ui .v8-histdata-swatch-wrap { position: relative; display: inline-flex; cursor: pointer; }
#v8-ui .v8-histdata-swatch {
    width: 22px;
    height: 14px;
    border-radius: 2px;
    border: 1px solid rgba(255,255,255,0.25);
    display: inline-block;
    /* dashed-line motif so the swatch reads as the overlay, not a bar segment */
    background-image: repeating-linear-gradient(90deg, currentColor 0 6px, transparent 6px 10px);
    color: var(--v8-accent-histdata);
}
#v8-ui .v8-histdata-swatch-wrap input[type="color"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}
#v8-ui .v8-histdata-meta {
    font-family: 'Courier New', ui-monospace, monospace;
    font-size: 11px;
    color: var(--v8-text-muted);
    white-space: nowrap;
}
#v8-ui .v8-histdata-clear {
    background: none;
    border: 1px solid var(--v8-border-strong);
    color: var(--v8-text-muted);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 600;
    padding: 5px 10px;
    border-radius: 2px;
    cursor: pointer;
    transition: color 150ms, border-color 150ms;
}
#v8-ui .v8-histdata-clear:hover { color: var(--v8-text); border-color: var(--v8-accent-histdata); }

/* ── Schedule overlay (build zzzzzzzy) ──────────────────────────────────────
   Second row of the Historical Data section; appears only when a Diio
   workbook has been dropped. The drop affordance lives on the chart wrap. */
#v8-ui .v8-sched-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--v8-border-soft);
}
#v8-ui .v8-sched-meta {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 10.5px;
    color: var(--v8-text-muted);
    letter-spacing: 0.02em;
}
#v8-ui .v8-sched-sub {
    font-size: 11px;
    font-weight: 600;
    color: var(--v8-text-muted);
    margin-left: 6px;
}
#v8-ui .v8-sched-select { min-width: 0; }
.chart-wrap.sched-drop-hot {
    outline: 2px dashed var(--tac-gold, #feab40);
    outline-offset: -6px;
}
.sched-drop-hint {
    position: absolute;
    left: 50%;
    top: 18px;
    transform: translateX(-50%);
    background: rgba(13, 17, 23, 0.92);
    color: #feab40;
    border: 1px solid #feab40;
    border-radius: 6px;
    padding: 7px 14px;
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    pointer-events: none;
    z-index: 60;
    white-space: nowrap;
}
@media (max-width: 720px) {
    .sched-drop-hint { white-space: normal; text-align: center; max-width: 88%; }
}
/* Crack spread toggle — offered only for the WTI ↔ jet fuel pair. Pill-framed so it
   reads as a distinct mode switch, accented in the section's Airbus red. */
#v8-ui .v8-histdata-crack {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px 4px 8px;
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    cursor: pointer;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--v8-text-muted);
    white-space: nowrap;
    transition: color 150ms, border-color 150ms, background 150ms;
}
#v8-ui .v8-histdata-crack[hidden] { display: none; }
#v8-ui .v8-histdata-crack:hover { color: var(--v8-text); border-color: var(--v8-accent-histdata); }
#v8-ui .v8-histdata-crack input { accent-color: var(--v8-accent-histdata); cursor: pointer; margin: 0; }
#v8-ui .v8-histdata-crack:has(input:checked) {
    color: var(--v8-text);
    border-color: var(--v8-accent-histdata);
    background: rgba(244, 81, 30, 0.10);
}
#v8-ui .v8-histdata-note {
    margin-top: 10px;
    font-size: 11.5px;
    color: var(--v8-text-muted);
    line-height: 1.5;
}
#v8-ui .v8-histdata-note[hidden] { display: none; }
/* "Dim deliveries" — the single opacity control, its own row below the series row. */
#v8-ui .v8-histdata-dim {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
}
#v8-ui .v8-histdata-dim[hidden] { display: none; }
#v8-ui .v8-histdata-dim-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--v8-text-muted);
    white-space: nowrap;
}
#v8-ui .v8-histdata-dim input[type="range"] {
    flex: 1;
    min-width: 90px;
    max-width: 200px;
    accent-color: var(--v8-accent-histdata);
    cursor: pointer;
}
#v8-ui .v8-histdata-dim-val {
    font-family: 'Courier New', ui-monospace, monospace;
    font-size: 11px;
    color: var(--v8-text-muted);
    min-width: 34px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
    #v8-ui .v8-histdata-select { min-width: 0; flex: 1 1 100%; }
}

/* Wave D Build 21 (xl, 2026-05-28): View eyebrow lives directly inside
   .control-bar (which IS the view section after xl — see notes on the
   control-bar rule above). Mirrors .v8-filter-eyebrow but in blue. The
   2px left-border accent runs the edge of .control-bar itself, just like
   SCOPE's gold left-border runs the edge of .v8-filter-section. */
#v8-ui .v8-view-eyebrow {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--v8-accent-x);
    text-transform: uppercase;
    margin-bottom: 12px;
    display: block;
}
#v8-ui .v8-filter-row {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}
#v8-ui .v8-filter-row + .v8-filter-row {
    margin-top: 8px;
}
/* (the switch's box rule retired 2026-10-18, customer roles B3′ — the tabs live in the customer row, styled by the
   R2 tab rules + the B3′ block at the end of this file) */
#v8-ui .v8-filter-mode-btn {
    padding: 6px 11px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--v8-text-muted);
    background: none;
    border: none;
    border-radius: 2px;
    cursor: pointer;
    transition: background 150ms, color 150ms;
}
#v8-ui .v8-filter-mode-btn.active { color: var(--v8-text-primary); }
/* (.v8-buyer-scope's toggle-era rules retired 2026-10-18, B3′ — the buyer-kind tabs are styled in the B3′ block at the end) */
#v8-ui .v8-filter-search {
    flex: 1;
    min-width: 200px;
    position: relative;
}
#v8-ui .v8-filter-search-input {
    width: 100%;
    padding: 8px 12px 8px 32px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    color: var(--v8-text-primary);
    font-family: inherit;
    font-size: 13px;
    transition: border-color 150ms;
}
#v8-ui .v8-filter-search-input:focus {
    outline: none;
    border-color: var(--v8-accent-x);
}
#v8-ui .v8-filter-search-input::placeholder { color: var(--v8-text-disabled); }
#v8-ui .v8-filter-search-icon {
    position: absolute;
    left: 11px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--v8-text-muted);
    width: 13px;
    height: 13px;
    pointer-events: none;
}

/* Phase 1.5 Session 6 (cf): V8 customer-search autocomplete dropdown.
   Absolute-positioned below the search input. Hidden by default; .visible
   reveals. Items have logo + name + optional Group badge + delivery total
   on the right. Highlighted state for keyboard nav and mouse hover. */
#v8-ui .v8-autocomplete {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 360px;
    overflow-y: auto;
    background: var(--v8-surface-dropdown);
    border: 1px solid var(--v8-border-strong);
    border-radius: 6px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.55);
    z-index: 1000;
    display: none;
    padding: 4px 0;
}
#v8-ui .v8-autocomplete.visible { display: block; }
#v8-ui .v8-autocomplete-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 12px;
    cursor: pointer;
    font-size: 13px;
    color: var(--v8-text-primary);
    transition: background 80ms;
}
#v8-ui .v8-autocomplete-item.highlighted,
#v8-ui .v8-autocomplete-item:hover {
    background: rgba(24, 112, 255, 0.12);
}
#v8-ui .v8-autocomplete-item.selected {
    color: var(--v8-text-muted);
}
#v8-ui .v8-autocomplete-logo {
    width: 22px; height: 22px;
    object-fit: contain;
    flex-shrink: 0;
    border-radius: 2px;
    background: rgba(255,255,255,0.04);
}
#v8-ui .v8-autocomplete-logo-placeholder {
    width: 22px; height: 22px;
    flex-shrink: 0;
    border-radius: 2px;
    background: rgba(255,255,255,0.04);
}
#v8-ui .v8-autocomplete-name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#v8-ui .v8-autocomplete-group-badge {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tac-gold, var(--v8-accent-segment));
    background: rgba(254, 171, 64, 0.10);
    padding: 1px 6px;
    border-radius: 2px;
    flex-shrink: 0;
}
#v8-ui .v8-autocomplete-total {
    font-size: 11.5px;
    color: #707683;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
#v8-ui .v8-autocomplete-check {
    color: var(--tac-blue, var(--v8-accent-x));
    font-size: 13px;
    flex-shrink: 0;
}
/* Hint footer at the bottom of the top-50 list. Visually distinct from
   selectable items: italic Source Serif, smaller, with a search-icon glyph.
   Non-interactive — cursor stays default, no hover state. */
#v8-ui .v8-autocomplete-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px 6px;
    margin-top: 4px;
    border-top: 1px solid var(--v8-border-soft);
    font-family: 'Source Serif 4', Georgia, serif;
    font-style: italic;
    font-size: 12px;
    color: #707683;
    cursor: default;
    pointer-events: none;
    position: sticky;
    bottom: 0;
    background: var(--v8-surface-dropdown);
}
#v8-ui .v8-autocomplete-hint svg {
    color: #707683;
    flex-shrink: 0;
}

/* Phase 1.5 Session 7 (ci): V8 pill-dropdown — generic styling shared by
   manufacturer/category/family/variant multi-select panels. Anchored
   relative to .v8-pill-wrap (the pill + dropdown pair). */
#v8-ui .v8-pill-wrap {
    position: relative;
    display: inline-block;
}
#v8-ui .v8-pill-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 240px;
    max-height: 380px;
    overflow-y: auto;
    background: var(--v8-surface-dropdown);
    border: 1px solid var(--v8-border-strong);
    border-radius: 6px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.55);
    z-index: 1000;
    display: none;
    padding: 4px 0;
}
#v8-ui .v8-pill-dropdown.visible { display: block; }
#v8-ui .v8-pill-dropdown-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 10px 8px;
    border-bottom: 1px solid var(--v8-border-soft);
}
/* Build dp (item 7): scope-narrowed count displayed at the top of each
   dropdown. "X" when at full universe; "X of Y" when narrowed by an
   upstream filter. JetBrains Mono matches the editorial chrome. */
#v8-ui .v8-pill-dropdown-count {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--v8-text-muted);
    letter-spacing: 0.02em;
}
#v8-ui .v8-pill-dropdown-count.narrowed {
    color: var(--v8-accent-segment-ink);
}
#v8-ui .v8-pill-dropdown-bulk {
    background: transparent;
    border: none;
    color: var(--tac-blue, var(--v8-accent-x));
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 2px;
    transition: background 80ms;
}
#v8-ui .v8-pill-dropdown-bulk:hover {
    background: rgba(24, 112, 255, 0.12);
}
/* Build dp (item 3): keyboard nav focus indicator. Item with .keyfocus
   class gets a subtle blue underlay so the user can see which row Enter
   will toggle. The class is added/removed by the keyboard handler. */
#v8-ui .v8-pill-dropdown-item.keyfocus {
    background: rgba(24, 112, 255, 0.18);
    outline: 1px solid rgba(24, 112, 255, 0.4);
    outline-offset: -1px;
}
#v8-ui .v8-pill-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    cursor: pointer;
    font-size: 13px;
    color: var(--v8-text-secondary);
    user-select: none;
    transition: background 80ms;
}
#v8-ui .v8-pill-dropdown-item:hover {
    background: rgba(24, 112, 255, 0.08);
}
#v8-ui .v8-pill-dropdown-item.checked {
    color: var(--v8-text-primary);
}
#v8-ui .v8-pill-dropdown-checkbox {
    appearance: none;
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border: 1.5px solid var(--v8-border-strong);
    border-radius: 2px;
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
    position: relative;
    transition: border-color 120ms, background 120ms;
}
#v8-ui .v8-pill-dropdown-checkbox:checked {
    background: var(--tac-blue, var(--v8-accent-x));
    border-color: var(--tac-blue, var(--v8-accent-x));
}
#v8-ui .v8-pill-dropdown-checkbox:checked::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 0px;
    width: 4px;
    height: 8px;
    border: solid #fff;
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
}
#v8-ui .v8-pill-dropdown-swatch {
    width: 12px;
    height: 12px;
    border-radius: 2px;
    flex-shrink: 0;
}
#v8-ui .v8-pill-dropdown-name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#v8-ui .v8-pill-dropdown-total {
    font-size: 11.5px;
    color: var(--v8-text-muted);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* Pills — read-only summary buttons in WHO/WHAT rows */
#v8-ui .v8-filter-pill {
    padding: 8px 13px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    color: var(--v8-text-secondary);
    font-family: inherit;
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    min-width: 130px;
    justify-content: space-between;
    transition: border-color 150ms, background 150ms;
}
#v8-ui .v8-filter-pill:hover:not(:disabled) {
    border-color: var(--v8-border-strong);
    background: rgba(24,112,255,0.06);
}
#v8-ui .v8-filter-pill[aria-expanded="true"] {
    border-color: var(--tac-blue, var(--v8-accent-x));
}
#v8-ui .v8-filter-pill[aria-expanded="true"] .pill-chevron {
    transform: rotate(180deg);
    color: var(--tac-blue, var(--v8-accent-x));
}
#v8-ui .v8-filter-pill:disabled {
    cursor: default;
    opacity: 0.65;
}
#v8-ui .v8-filter-pill.has-filter {
    border-color: var(--v8-pill-engaged-border);
    background: var(--v8-pill-engaged-bg);
    color: var(--v8-text-primary);
}
#v8-ui .v8-filter-pill .pill-chevron {
    width: 11px;
    height: 11px;
    color: var(--v8-text-disabled);
    transition: transform 150ms;
}

/* Active chips area */
#v8-ui .v8-active-filters {
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
    margin-top: 12px;
    align-items: center;
    min-height: 24px;
}
#v8-ui .v8-active-filters:empty { display: none; }
#v8-ui .v8-active-label {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--v8-text-disabled);
    margin-right: 4px;
}

/* Filter chip — unified vocabulary */
#v8-ui .v8-filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 4px 4px 9px;
    background: rgba(254,171,64,0.10);
    border: 1px solid rgba(254,171,64,0.22);
    border-radius: 2px;
    color: var(--v8-text-primary);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 12px;
}
#v8-ui .v8-filter-chip-prefix {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    color: var(--v8-accent-segment);
    padding: 1px 5px;
    background: rgba(254,171,64,0.14);
    border-radius: 2px;
    letter-spacing: 0.06em;
    font-weight: 500;
}
/* Flag emoji inside V8 country chips — sits flush before the OP/BUYER
   prefix, slightly larger than the prefix glyph so the flag reads as
   the primary identifier. Build dk: replaces ISO-code-in-prefix.
   Build dn: explicit flex centering — emoji glyphs have a tall ascent
   box that floats them above the text baseline; vertical-align tweaks
   don't fix it reliably across browsers. Wrap in a flex line with
   center alignment so the glyph sits inline with the chip text. */
#v8-ui .v8-filter-chip-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    line-height: 1;
    margin-right: 2px;
    height: 1em;
}
/* Item 4 (build do): search input row inside long dropdowns (country,
   family, variant). Slim separator above the items, JetBrains Mono so
   typed text matches the editorial chrome of the rest of the V8 UI. */
#v8-ui .v8-pill-dropdown-search-row {
    padding: 6px 10px 4px;
    border-bottom: 1px solid var(--v8-border-soft);
}
/* Build 20260508yv: country group quick-add (EU 27, G7, BRIC, …). */
#v8-ui .v8-pill-dropdown-groups {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    padding: 7px 10px;
    border-bottom: 1px solid var(--v8-border-soft);
}
#v8-ui .v8-pill-groups-label {
    font-size: 11px;
    color: var(--v8-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-right: 2px;
}
#v8-ui .v8-pill-group-btn {
    font-size: 11px;
    padding: 2px 8px;
    color: var(--v8-text-secondary);
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s;
}
#v8-ui .v8-pill-group-btn:hover {
    background: var(--v8-accent-x, #1870ff);
    border-color: var(--v8-accent-x, #1870ff);
    color: #fff;
}
/* Build 20260508yx: a group stays lit while all its members are selected;
   a second click on a lit group removes them. */
#v8-ui .v8-pill-group-btn.active {
    background: var(--v8-accent-x, #1870ff);
    border-color: var(--v8-accent-x, #1870ff);
    color: #fff;
    font-weight: 600;
}
/* Build 20260508yy: touch ergonomics — bigger hit areas for the scope chips,
   their exclude-toggle/×, and the quick-add group pills; the 9-button quick-add
   row stays on ONE line and scrolls horizontally so it doesn't eat the dropdown
   panel on a phone. Triggers on touch (hover:none) OR a narrow viewport so the
   dense full-width desktop UI is unchanged. */
@media (hover: none), (max-width: 480px) {
    #v8-ui .v8-pill-dropdown-groups {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    #v8-ui .v8-pill-dropdown-groups::-webkit-scrollbar { display: none; }
    #v8-ui .v8-pill-groups-label { flex: 0 0 auto; }
    #v8-ui .v8-pill-group-btn {
        flex: 0 0 auto;
        font-size: 13px;
        padding: 9px 13px;
        min-height: 40px;
    }
    #v8-ui .v8-chip-toggle,
    .filter-chip .chip-toggle { padding: 7px 4px 7px 2px; }
    #v8-ui .v8-chip-ex-glyph,
    .filter-chip .chip-ex-glyph { width: 13px; height: 13px; opacity: 0.6; }
    #v8-ui .v8-filter-chip-x,
    .filter-chip .remove-chip {
        min-width: 36px;
        min-height: 36px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        opacity: 0.85;
    }
    #v8-ui .v8-pill-dropdown-item { padding-top: 11px; padding-bottom: 11px; }
    #v8-ui .v8-pill-dropdown-checkbox { width: 20px; height: 20px; }
}
#v8-ui .v8-pill-dropdown-search {
    width: 100%;
    background: var(--v8-surface-control);
    color: var(--v8-text-primary);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    padding: 5px 8px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    outline: none;
    box-sizing: border-box;
}
#v8-ui .v8-pill-dropdown-search:focus {
    border-color: rgba(254,171,64,0.6);
    background: var(--v8-border-strong);
}
#v8-ui .v8-pill-dropdown-search::placeholder {
    color: var(--v8-text-disabled);
}
#v8-ui .v8-filter-chip-logo {
    width: 16px;
    height: 16px;
    border-radius: 2px;
    object-fit: contain;
    background: white;
    flex-shrink: 0;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.08);
}
#v8-ui .v8-filter-chip-x {
    width: 18px;
    height: 18px;
    border-radius: 2px;
    background: none;
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--v8-text-muted);
    font-size: 14px;
    line-height: 1;
    transition: background 150ms, color 150ms;
}
#v8-ui .v8-filter-chip-x:hover {
    background: var(--v8-border-soft);
    color: var(--v8-text-primary);
}
/* Build 20260508yy: the chip identity is an accessible exclude TOGGLE button
   carrying a persistent ⊘ glyph (discoverable without hover → works on touch).
   The × stays the separate remove control. */
#v8-ui .v8-chip-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    margin: 0;
    padding: 2px 2px 2px 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    border-radius: 2px;
}
#v8-ui .v8-chip-ex-glyph {
    width: 11px;
    height: 11px;
    flex: 0 0 auto;
    opacity: 0.45;                 /* faint always-on hint when included */
    transition: opacity 0.12s;
}
#v8-ui .v8-chip-toggle:hover .v8-chip-ex-glyph,
#v8-ui .v8-chip-toggle:focus-visible .v8-chip-ex-glyph {
    opacity: 0.9;
}
#v8-ui .v8-chip-toggle:focus-visible {
    outline: 2px solid var(--v8-accent-x, #1870ff);
    outline-offset: 1px;
}
/* Excluded = negative (red) state — distinct from a disabled/dim look, and
   higher contrast than opacity-dimming. Uses TAC red #f35841. */
#v8-ui .v8-filter-chip.excluded {
    background: rgba(243, 88, 65, 0.12);
    border-color: rgba(243, 88, 65, 0.45);
    color: #f1907f;
}
#v8-ui .v8-filter-chip.excluded .v8-chip-ex-glyph {
    opacity: 1;                    /* solid red ⊘ when excluded */
}
#v8-ui .v8-filter-chip.excluded .v8-filter-chip-name {
    text-decoration: line-through;
    text-decoration-color: rgba(243, 88, 65, 0.8);
}

#v8-ui .v8-clear-all {
    margin-left: auto;
    font-family: inherit;
    font-size: 11px;
    color: var(--v8-text-muted);
    background: none;
    border: none;
    padding: 4px 8px;
    border-radius: 2px;
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: rgba(255,255,255,0.15);
    text-underline-offset: 2px;
}
#v8-ui .v8-clear-all:hover { color: var(--v8-text-primary); }

/* Mobile */
@media (max-width: 720px) {
    #v8-ui .v8-filter-section { padding: 14px 16px 16px; }
    #v8-ui .v8-filter-row { gap: 8px; }
    #v8-ui .v8-filter-search { flex: 1 1 100%; min-width: 0; }
    #v8-ui .v8-filter-pill { flex: 1 1 calc(50% - 4px); min-width: 0; }
    /* Build xg (2026-05-27): the six scope dropdowns (region, country,
       manufacturer, category, family, variant) lay out 3-per-line on
       mobile — row 1 = region / country / manufacturer, row 2 =
       category / family / variant. A 3-col grid forces the split
       regardless of label width (e.g. "All manufacturers" vs "103
       variants"). On desktop this row stays flex-wrap (all six on one
       line); the grid only kicks in here. */
    #v8-ui .v8-scope-pills {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 8px;
        align-items: start;
    }
    #v8-ui .v8-scope-pills .v8-pill-wrap {
        display: block;
        width: 100%;
        min-width: 0;
    }
    #v8-ui .v8-scope-pills .v8-filter-pill {
        width: 100%;
        flex: none;       /* override the generic 50%-flex pill rule above */
        min-width: 0;
    }
    /* Pill label can ellipsize rather than force the cell wider */
    #v8-ui .v8-scope-pills .v8-filter-pill > span:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Build zzzq (2026-07-02): keep every scope-dropdown panel on-screen at
       narrow widths. The six pills sit in a 3-col grid (region/country/mfr •
       cat/family/variant), so a single anchor can't fit all three columns: a
       left-anchored 240px panel on the RIGHT column (manufacturer / variant)
       spilled off the right edge (the reported bug); right-anchoring the LEFT
       or MIDDLE column instead pushes IT off the left. So anchor per column:
       left column opens rightward, middle centers under its trigger, right
       column anchors to its own right edge and opens leftward toward center.
       These MUST out-specify the base `#v8-ui .v8-pill-dropdown{left:0}` (line
       ~6125), which otherwise wins by source order — the reason the build-yd
       viewport-containment rule above (which right-anchored all panels) was
       silently dead. Verified on-screen, no spill, 320–720px. */
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n+1) .v8-pill-dropdown {
        left: 0; right: auto; transform: none;
    }
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n+2) .v8-pill-dropdown {
        left: 50%; right: auto; transform: translateX(-50%);
    }
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n) .v8-pill-dropdown {
        left: auto; right: 0; transform: none;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 5 — Year-range preset caret
   Lives inside V7's year-range-container, NOT under #v8-ui scope.
   Gated on body.v8-ui-enabled so it stays hidden in V7-only mode.
   ───────────────────────────────────────────────────────────────────── */

.v8-presets-wrap {
    display: none;
    position: relative;
    margin-left: 8px;
}
body.v8-ui-enabled .v8-presets-wrap { display: inline-block; }

.v8-presets-trigger {
    width: 28px;
    height: 28px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    color: var(--v8-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: border-color 150ms, color 150ms;
    padding: 0;
}
.v8-presets-trigger:hover,
.v8-presets-trigger.open {
    border-color: #1870ff;
    color: #1870ff;
}
.v8-presets-trigger svg {
    width: 11px;
    height: 11px;
    transition: transform 200ms cubic-bezier(0.32,0.72,0,1);
}
.v8-presets-trigger.open svg { transform: rotate(180deg); }

.v8-presets-popover {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    background: var(--v8-surface-dropdown);
    border: 1px solid var(--v8-border-strong);
    border-radius: 6px;
    padding: 4px;
    list-style: none;
    margin: 0;
    min-width: 220px;
    z-index: 60;
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
    transition: opacity 150ms, transform 150ms;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
    font-family: 'Archivo', system-ui, sans-serif;
}
.v8-presets-popover.open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.v8-preset-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 10px;
    font-family: inherit;
    font-size: 13px;
    color: var(--v8-text-secondary);
    background: none;
    border: none;
    border-radius: 2px;
    width: 100%;
    text-align: left;
    cursor: pointer;
    transition: background 150ms, color 150ms;
}
.v8-preset-item:hover {
    background: rgba(24,112,255,0.08);
    color: var(--v8-text-primary);
}
.v8-preset-detail {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--v8-text-muted);
}

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 6 — Group chip member expansion
   Group chips: parent + expand chevron + member count, with member
   sub-row that drops below as a full-row flex-break (1 0 100%).
   ───────────────────────────────────────────────────────────────────── */

#v8-ui .v8-filter-chip-count {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    color: var(--v8-text-muted);
    background: var(--v8-border-soft);
    padding: 1px 6px;
    border-radius: 2px;
    font-weight: 500;
}
#v8-ui .v8-filter-chip-expand {
    width: 18px;
    height: 18px;
    border-radius: 2px;
    background: none;
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--v8-text-muted);
    transition: color 150ms, background 150ms;
}
#v8-ui .v8-filter-chip-expand svg {
    width: 10px;
    height: 10px;
    transition: transform 200ms cubic-bezier(0.32,0.72,0,1);
}
#v8-ui .v8-filter-chip-expand:hover {
    background: var(--v8-border-soft);
    color: var(--v8-text-primary);
}
#v8-ui .v8-group-chip.expanded .v8-filter-chip-expand svg {
    transform: rotate(180deg);
}

/* Member sub-row — full-row flex-break under the parent group chip */
#v8-ui .v8-group-members {
    display: none;
    flex: 1 0 100%;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px 10px 6px 12px;
    margin: 2px 0 4px;
    background: rgba(254,171,64,0.04);
    border: 1px solid rgba(254,171,64,0.12);
    border-radius: 2px;
    align-items: center;
}
#v8-ui .v8-group-chip.expanded + .v8-group-members {
    display: flex;
}
#v8-ui .v8-group-members-label {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--v8-text-disabled);
    margin-right: 2px;
}
#v8-ui .v8-group-member {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 4px 3px 7px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 2px;
    color: var(--v8-text-secondary);
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 11px;
}
#v8-ui .v8-group-member.excluded {
    opacity: 0.45;
}
#v8-ui .v8-group-member.excluded .v8-group-member-name {
    text-decoration: line-through;
    text-decoration-color: rgba(255,255,255,0.3);
}
#v8-ui .v8-group-member-toggle {
    width: 16px;
    height: 16px;
    border-radius: 2px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--v8-text-disabled);
    font-size: 12px;
    line-height: 1;
    transition: background 150ms, color 150ms;
}
#v8-ui .v8-group-member-toggle:hover {
    background: var(--v8-border-soft);
    color: var(--v8-text-primary);
}
#v8-ui .v8-filter-chip-member-logo {
    width: 14px;
    height: 14px;
    border-radius: 2px;
    object-fit: contain;
    background: white;
    flex-shrink: 0;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.08);
}

/* ═════════════════════════════════════════════════════════════════════
   Hide V7 controls that V8 has fully replaced.
   Activated when body.v8-ui-enabled is set — which is UNCONDITIONAL since
   Branch 2 (2026-07-25): the preview-era Disable button and ?v8 flags are
   retired. The hidden V7 controls stay in the DOM as the live transport
   layer (V8 dispatches change-events at them) until Tier B replaces the
   seam — see docs/transport-seam-scoping.md.
   ───────────────────────────────────────────────────────────────────── */

/* V7 stats grid — replaced by V8 tallies strip */
body.v8-ui-enabled #stats { display: none !important; }

/* V7 customer filter bar — replaced by V8 filter section mirror */
body.v8-ui-enabled #customerFilterBar { display: none !important; }

/* V7 view-tabs row inside .chart-container — top control bar with
   Manufacturers/Customers tabs + bar-layout toggle + chart-type tabs.
   All replaced by V8 X-axis chip strip + Segment-By dropdown +
   chart-type strip. Direct child selector so we don't accidentally
   match nested .view-tabs anywhere else. */
body.v8-ui-enabled .chart-container > .view-tabs { display: none !important; }

/* Wave D Build 17 (xc, 2026-05-26): V7 legacy chip selectors. The
   functionality previously delivered by these chip strips has been
   fully absorbed by the V8 SCOPE dropdowns (mfr / cat / family / variant
   selection) and the Interactive Legend (single-click hide, double-click
   isolate, cascade clicks on family + mfr group headers).
     #mfrChips       — Manufacturer chip row (Boeing/Airbus/Embraer/MDC/
                       Bombardier with color swatches). Replaced by the
                       V8 scope mfr dropdown + manufacturer rows in the
                       interactive legend.
     #itemToggles    — Wraps both #categoryQuickSelect (Quick Select:
                       All / Widebody / Single-Aisle / Regional Jet) and
                       #toggleContainer (family/variant chips grouped by
                       manufacturer with "click to hide all" affordances).
                       Replaced by the V8 scope category dropdown + the
                       interactive legend's cascade-click on mfr/family
                       group headers.
     #mfrFilterLabel — The "Manufacturers" / "Customers" label above
                       #mfrChips. The customer color-picker context is
                       clear from the chips themselves; no orphaned label
                       needed when only the picker is visible.
   IMPORTANT: #customerLegendChips (the customer color-picker, separate
   container inside #mfrFilterGroup) is intentionally NOT hidden here —
   Jon explicitly excluded it from the removal. It continues to be
   shown/hidden by renderToggles() based on currentBreakdown.
   #customerXAxisControls (V7 customer-x-axis control row) is also
   left in place — separate from the chip-strip removal scope. */
body.v8-ui-enabled #mfrChips { display: none !important; }
body.v8-ui-enabled #itemToggles { display: none !important; }
body.v8-ui-enabled #mfrFilterLabel { display: none !important; }

/* Wave D Build 20 (xk, 2026-05-28): In V8 mode, the chart container wraps
   V8 components — let it adopt the V8 surface palette so the chart sits
   in a coherent themed container (light / V8 bluer dark / dusk gray) and
   doesn't break the V8 visual envelope. V7 mode keeps the V7 --card.
   xl (2026-05-28): margin-bottom harmonized to 18px so the gap between
   SCOPE → VIEW → main chart → All Data is uniform. */
/* Wave D Build 22 (xm, 2026-05-28): In V8 mode the chart-container uses
   var(--v8-surface-section), but .chart-legend was still pulling from
   var(--card) (the V7-shared token) — so in V8 bluer dark the legend
   rendered as V7 gray #1E1E1E against a #161c24 bluer container. Both
   moon themes now match: legend background tracks the V8 surface so
   the container + legend read as one unified surface in light, dark
   (V8 bluer), and dusk (V7 gray) alike. */
body.v8-ui-enabled .chart-legend {
    background: var(--v8-surface-section);
}

body.v8-ui-enabled .chart-container {
    background: var(--v8-surface-section);
    border: 1px solid var(--v8-border-soft);
    margin-bottom: 14px;
}
/* EXPERIMENT (build zzzu): the main chart is relocated INTO #v8-ui (directly
   below the scoreboard) by the parse-time reorder script in index.html. Override
   its base 32px top margin down to 14px so the scoreboard→chart gap matches the
   14px rhythm already used between Scope→View (the base .chart-container 32px
   gap was the wider one). Scoped to #v8-ui so the All-Data table (outside
   #v8-ui) keeps its own spacing. ID specificity wins over .chart-container. */
#v8-ui .chart-container { margin-top: 14px; }

/* Wave D Build 21 (xl, 2026-05-28): All Data section — V8 visual language.
   Eyebrow at top-left in V8 muted color (not blue/gold — those accents
   are reserved for the active control sections SCOPE + View). Search
   input drops onto its own row below the eyebrow with 12px breathing
   room, matching the eyebrow→content rhythm used in .v8-filter-section
   and .control-bar. Search field styled to match V8 controls
   (--v8-surface-control surface, --v8-border-strong edge). */
body.v8-ui-enabled .v8-data-section {
    padding: 22px 24px 24px;
    border-radius: 6px;
    font-family: 'Archivo', system-ui, sans-serif;
}
body.v8-ui-enabled .v8-data-header {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 16px;
    padding-bottom: 0;
    border-bottom: none;
    align-items: flex-start;
}
body.v8-ui-enabled .v8-data-eyebrow {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--v8-text-muted);
    text-transform: uppercase;
    display: block;
}
body.v8-ui-enabled .v8-data-search {
    width: 280px;
    max-width: 100%;
    padding: 8px 12px;
    background: var(--v8-surface-control);
    border: 1px solid var(--v8-border-strong);
    border-radius: 2px;
    color: var(--v8-text-primary);
    font-family: inherit;
    font-size: 13px;
    transition: border-color 150ms;
}
body.v8-ui-enabled .v8-data-search:focus {
    outline: none;
    border-color: var(--v8-accent-x);
}
body.v8-ui-enabled .v8-data-search::placeholder {
    color: var(--v8-text-muted);
}

/* Generic hide-on-V8 class — used by JS to mark elements that need
   parent-level traversal (e.g. the Group By .filter-group, since
   we can't target the parent without :has() compat concerns). */
body.v8-ui-enabled .v8-hide-when-active { display: none !important; }

/* ═════════════════════════════════════════════════════════════════════
   V8 PHASE 1 STEP 8 — Audit fixes (pre-beta polish)
   ───────────────────────────────────────────────────────────────────── */

/* Keyboard focus indicators — V8 had only the search input. Adding
   :focus-visible (modern, only fires on keyboard not click) across all
   V8 interactive surfaces. Outline color matches TAC blue. */
#v8-ui button:focus-visible,
#v8-ui .chip:focus-visible,
#v8-ui select:focus-visible,
#v8-ui input:focus-visible,
.v8-presets-trigger:focus-visible,
.v8-preset-item:focus-visible,
.v8-resume-btn:focus-visible {
    outline: 2px solid var(--v8-accent-x);
    outline-offset: 2px;
    border-radius: 2px;
}


/* ═══════════════ Next-gen drilldown (Phase 3, behind ?ngd=1) — scoped, ngd- prefixed ═══════════════ */
.ngd-overlay{position:fixed;inset:0;z-index:9000;display:none;align-items:center;justify-content:center;background:rgba(1,4,9,.6);padding:24px;
  --bg:#0d1117;--panel:#0d1117;--line:#21262d;--line2:#30363d;--ink:#c9d1d9;--ink-hi:#f0f6fc;--muted:#8b949e;--faint:#6e7681;--blue:#1870ff;--blue-deep:#3168c4;--gold:#feab40;--canvas:#010409;
  --panel2:#161b22;--pill-bg:rgba(13,17,23,.82);--pill-ink:#cdd6e0;
  font-family:"Archivo",system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:var(--ink);}
/* Light theme (build zzzzp): the drilldown adopts the app's light surfaces — white
   panel, light hairlines, dark ink, darkened gold for contrast on white. Dark and
   dusk keep the dark token set above. NOTE the app's light mode is the ABSENCE of
   the data-theme attribute (only dark/dusk set it), so the selector is not-dark-
   not-dusk rather than [data-theme="light"]. Hovers need no equivalent: the chart
   tooltip themes via the per-theme --tooltip-* vars (dark glass on light by design). */
:root:not([data-theme="dark"]):not([data-theme="dusk"]) .ngd-overlay{
  --bg:#fafafa;--panel:#ffffff;--line:#e6e8ec;--line2:#d3d7dc;--ink:#3a434d;--ink-hi:#131313;
  --muted:#5c6570;--faint:#8a9099;--gold:#b8791f;--canvas:#eef0f3;
  --panel2:#f2f4f7;--pill-bg:rgba(255,255,255,.92);--pill-ink:#3a434d;
  background:rgba(33,37,41,.45);}
.ngd-overlay.open{display:flex;}
.ngd-modal{background:var(--panel);border:1px solid var(--line2);border-radius: 6px;overflow:hidden auto;width:720px;max-width:100%;max-height:90vh;}
.ngd-hd{padding:13px 16px 11px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:flex-start;gap:10px;}
.ngd-ident{width:40px;height:40px;border-radius:7px;background:#fff;display:flex;align-items:center;justify-content:center;flex:none;overflow:hidden;font-weight:600;font-size:14px;color:#0a2240;}
.ngd-ident img{width:100%;height:100%;object-fit:contain;padding:3px;box-sizing:border-box;}
.ngd-ttl{font-size:18px;font-weight:600;color:var(--ink-hi);line-height:1.25;}
.ngd-stl{font-size:12px;color:var(--muted);margin-top:3px;}
.ngd-close{background:none;border:0;color:var(--muted);font-size:20px;cursor:pointer;line-height:1;padding:0 2px;}
.ngd-ctlbar{padding:9px 16px;border-bottom:1px solid var(--line);display:flex;gap:10px;align-items:center;flex-wrap:wrap;}
.ngd-seg{display:inline-flex;border:1px solid var(--line2);border-radius:6px;overflow:hidden;font-size:11px;}
.ngd-seg span{padding:3px 10px;color:var(--muted);cursor:pointer;}
.ngd-seg span.on{background:var(--blue);color:#fff;}
.ngd-buyerctl{display:inline-flex;align-items:center;gap:7px;}
.ngd-tchips{display:inline-flex;border:1px solid var(--line2);border-radius:6px;overflow:hidden;font-size:11px;}
.ngd-tchips span{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;color:var(--muted);cursor:pointer;border-left:1px solid var(--line2);}
.ngd-tchips span:first-child{border-left:0;}
.ngd-tchips span.on{background:var(--line2);color:var(--ink);}
.ngd-tchips span .d{width:8px;height:8px;border-radius:2px;flex:none;}
.ngd-resetbtn{font:inherit;color:var(--muted);background:var(--bg);border:1px solid var(--line2);border-radius:6px;padding:4px 6px;cursor:pointer;margin-left:auto;display:inline-flex;align-items:center;position:relative;}
.ngd-resetbtn:hover{border-color:var(--gold);color:var(--gold);}
.ngd-resetbtn svg{display:block;}
.ngd-rtip{position:absolute;top:calc(100% + 6px);right:0;white-space:nowrap;background:var(--panel2);border:1px solid var(--line2);border-radius:6px;padding:4px 8px;font-size:10.5px;color:var(--ink);opacity:0;pointer-events:none;transition:opacity .12s;z-index:10;}
.ngd-resetbtn:hover .ngd-rtip{opacity:1;transition-delay:.55s;}
.ngd-kpis{padding:11px 16px;border-bottom:1px solid var(--line);display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap;}
.ngd-kpi{flex:1;background:var(--bg);border:1px solid var(--line);border-radius: 6px;padding:6px 9px;min-width:58px;}
.ngd-kpi .v{font-size:16px;font-weight:600;color:var(--ink-hi);}
.ngd-kpi .l{font-size:9.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;}
.ngd-pill{font-size:10.5px;color:#9cc4ff;background:rgba(24,112,255,.12);border:1px solid rgba(24,112,255,.3);border-radius: 2px;padding:2px 9px;margin-top:4px;}
.ngd-body{display:flex;align-items:stretch;}
.ngd-rail{width:190px;flex:none;border-right:1px solid var(--line);padding:11px 12px;}
.ngd-right{flex:1;min-width:0;padding:11px 14px;}
.ngd-dist{display:flex;justify-content:space-between;align-items:center;margin-bottom:7px;gap:8px;}
.ngd-dist .lbl{font-size:12px;font-weight:600;color:var(--ink-hi);}
.ngd-lenssel{font:inherit;font-size:12px;font-weight:500;color:var(--ink-hi);background:var(--bg);border:1px solid var(--line2);border-radius:6px;padding:3px 8px;cursor:pointer;}
.ngd-tmwrap{position:relative;}
.ngd-tmwrap svg{width:100%;height:auto;display:block;background:var(--canvas);border-radius:6px;}
.ngd-directoverlay{position:absolute;top:8px;left:50%;transform:translateX(-50%);z-index:3;display:inline-flex;align-items:center;gap:6px;padding:4px 11px;font-size:11px;font-weight:500;color:var(--pill-ink);background:var(--pill-bg);border:1px solid var(--line2);border-radius: 2px;pointer-events:none;white-space:nowrap;}
.ngd-directoverlay[hidden]{display:none;}
.ngd-directoverlay .ti{font-size:13px;color:#6c7f95;}
.ngd-tip{position:absolute;pointer-events:none;opacity:0;transition:opacity .08s;background:var(--panel2);border:1px solid var(--line2);border-radius:6px;padding:5px 8px;font-size:11px;color:var(--ink-hi);white-space:nowrap;z-index:5;}
.ngd-tmnote{font-size:10px;color:var(--faint);margin:5px 0 12px;}
.ngd-dt{font-size:12px;font-weight:600;color:var(--ink-hi);margin-bottom:5px;}
.ngd-dt .cnt{color:var(--muted);font-weight:400;font-size:11px;}
.ngd-dtscroll{max-height:280px;overflow-y:auto;}
.ngd-table{width:100%;border-collapse:collapse;}
.ngd-table th,.ngd-table td{padding:3px 7px;text-align:left;font-size:11px;border-bottom:1px solid #1c2128;}
.ngd-table th{color:var(--muted);font-weight:500;text-transform:uppercase;letter-spacing:.03em;font-size:9.5px;position:sticky;top:0;background:var(--panel);z-index:1;}
.ngd-table th.sortable{cursor:pointer;user-select:none;white-space:nowrap;}
.ngd-table th .caret{color:var(--gold);font-weight:600;}
.ngd-vchip{background:#21262d;border-radius: 2px;padding:1px 5px;white-space:nowrap;display:inline-block;}
/* keep variant on one line (auto-sizes to the longest, e.g. "Legacy 600/650"); shrink customer to fit */
.ngd-table td[data-col="variant"],.ngd-table td[data-col="region"]{white-space:nowrap;}
.ngd-table td[data-col="customer"]{white-space:nowrap;}
.ngd-cust{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom;}
.ngd-via{font-size:9px;color:var(--muted);}
.ngd-micro{font-size:9px;color:var(--faint);margin-top:6px;line-height:1.4;}
/* left-rail: period rail + pinnable facet (Phase 3B) — bare sub-classes scoped under .ngd-overlay */
.ngd-overlay .ngd-raillab{font-size:10px;color:var(--gold);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;padding-left:4px;}
.ngd-overlay .ngd-raillab .dim{color:var(--faint);text-transform:none;letter-spacing:0;}
.ngd-overlay .ngd-allrow{display:flex;justify-content:space-between;font-size:11px;padding:3px 8px;border-radius: 2px;}
.ngd-overlay .ngd-allrow.sel{background:var(--blue);color:#fff;}
.ngd-overlay .ngd-allrow.plain{background:var(--panel2);}
.ngd-overlay .ngd-slot{display:flex;align-items:center;gap:6px;font-size:11px;padding:2px 4px;}
.ngd-overlay .ngd-slot .bar{height:8px;border-radius:2px;flex:none;background:var(--blue-deep);}
.ngd-overlay .ngd-slot .nm{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink);}
.ngd-overlay .ngd-slot .ct,.ngd-overlay .ngd-allrow .ct{color:var(--muted);}
.ngd-overlay .ngd-prow{cursor:pointer;}
.ngd-overlay .ngd-allrow.ngd-prow:hover,.ngd-overlay .ngd-slot.ngd-prow:hover{background:#1c2330;}
.ngd-overlay .ngd-slot.psel{background:rgba(254,171,64,.16);border-radius: 2px;}
.ngd-overlay .ngd-qgrid{max-height:184px;overflow-y:auto;display:grid;grid-template-columns:repeat(4,1fr);gap:3px;padding-right:3px;}
.ngd-overlay .ngd-ygrid{max-height:190px;overflow-y:auto;display:grid;grid-template-columns:repeat(3,1fr);gap:3px;padding-right:3px;}
.ngd-overlay .ngd-qc{border:1px solid var(--line);border-radius: 2px;padding:3px 4px;text-align:center;line-height:1.2;}
.ngd-overlay .ngd-qc .qn{font-size:11px;font-weight:600;}
.ngd-overlay .ngd-qc .ql{font-size:8.5px;color:var(--muted);}
.ngd-overlay .ngd-qc.empty{opacity:.32;background:transparent!important;}
.ngd-overlay .ngd-qc.psel{outline:1px solid var(--gold);}
.ngd-overlay .ngd-heat{display:grid;grid-template-columns:24px repeat(12,1fr);gap:2px;align-items:center;}
.ngd-overlay .ngd-heat .hm{font-size:7.5px;color:var(--faint);text-align:center;}
.ngd-overlay .ngd-heat .hy{font-size:8.5px;color:var(--muted);}
.ngd-overlay .ngd-heat .hc{aspect-ratio:1;border-radius:2px;}
.ngd-overlay .ngd-heat .hc.empty{border:1px solid var(--line);}
.ngd-overlay .ngd-fscroll{max-height:200px;overflow-y:auto;padding-right:3px;}
.ngd-overlay .ngd-faclab{display:flex;align-items:center;justify-content:space-between;gap:6px;}
.ngd-overlay .ngd-pinbtn{font:inherit;background:transparent;border:1px solid var(--line2);border-radius: 2px;color:var(--faint);cursor:pointer;padding:2px 5px;line-height:0;display:inline-flex;align-items:center;}
.ngd-overlay .ngd-pinbtn:hover{color:var(--ink);}
.ngd-overlay .ngd-pinbtn.on{color:var(--gold);border-color:var(--gold);}
@media(max-width:640px){
  .ngd-body{flex-direction:column}
  .ngd-rail{width:auto;border-right:0;border-bottom:1px solid var(--line)}
  /* Build zzzs (2026-07-02): mobile polish for the next-gen drilldown modal.
     H2 — reclaim ~48px of width: shrink the overlay gutter so the modal uses
     the full phone width. */
  .ngd-overlay{padding:8px;}
  /* H3 — the modal's only dismiss control was a ~24px hit area; give it a
     ≥40px tap target. */
  .ngd-close{min-width:40px;min-height:40px;display:inline-flex;align-items:center;justify-content:center;padding:0;margin:-6px -6px 0 0;}
  /* H4 — in-modal segmented toggles (view / timeframe / buyer-type chips) were
     ~22px tall; bump to a finger-friendly height. */
  .ngd-seg span,.ngd-tchips span{padding:9px 12px;}
  /* M3 — let a wide details table scroll horizontally instead of clipping/
     pushing the modal. */
  .ngd-dtscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .ngd-cust{max-width:120px;}
  /* M1 — lift the sub-10px labels to the mobile-legible floor. */
  .ngd-table th{font-size:10.5px;}
  .ngd-via{font-size:10.5px;}
  .ngd-micro{font-size:10px;}
  .ngd-kpi .l{font-size:10.5px;}
}


/* ═══════════════════════════════════════════════════════════════════════════
   EMBED MODE (2026-10-08) — `?embed=1`: the page booted from a permalink inside an iframe.
   html.embed-mode is set in the early inline script (before first paint) and again by app.js.
   Only title · subhead · notes · legend · chart · attribution remain; everything that edits,
   navigates or persists is removed. The chart fills the iframe's height.
   ═══════════════════════════════════════════════════════════════════════════ */
html.embed-mode, html.embed-mode body { height: 100%; margin: 0; overflow-x: hidden; overflow-y: auto; }   /* never clip: a too-short frame scrolls instead */
html.embed-mode body { display: flex; flex-direction: column; padding: 0; min-height: 0; }
html.embed-mode .theme-toggle, html.embed-mode .header, html.embed-mode #tacTicker, html.embed-mode #stats,
html.embed-mode #v8-ui > :not(.chart-container), html.embed-mode #customerFilterBar, html.embed-mode #v8-resume-prompt,
html.embed-mode .view-tabs, html.embed-mode #dataControlsRow, html.embed-mode #itemToggles,
html.embed-mode #toggleContainer, html.embed-mode .year-range-container, html.embed-mode .click-hint,
html.embed-mode .v8-data-section, html.embed-mode .footer, html.embed-mode #confirmOverlay,
html.embed-mode .chart-title-actions, html.embed-mode .chart-subhead-edit, html.embed-mode .chart-title-reset,
html.embed-mode .legend-color-badge, html.embed-mode .v8x-tt-drill, html.embed-mode .tooltip-explore-btn,
html.embed-mode #customerXAxisControls, html.embed-mode #recordLevelXAxisControls,
html.embed-mode .cust-note-default, html.embed-mode .cust-note-tip { display: none !important; }
html.embed-mode #v8-ui { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; margin: 0; padding: 0; }
html.embed-mode .chart-container { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0;
    margin: 0; border: 0; border-radius: 0; padding: 14px 16px 10px; box-shadow: none; }
html.embed-mode .chart-container.v8-data-section { display: none !important; }
html.embed-mode .chart-wrap { flex: 1 1 auto; min-height: 260px; height: auto; cursor: crosshair; }   /* drag-to-measure stays live */   /* the chart's floor — below this the frame scrolls rather than squashes */
html.embed-mode .chart-container { flex-shrink: 0; }
html.embed-mode .chart-header h2 { font-size: 1.15rem; }
html.embed-mode .legend-color-btn { pointer-events: none; cursor: default; }
html.embed-mode .chart-branding { padding: 6px 0 0; }
/* 2026-10-09 (Jon): the link showed on the FULL chart page — `.chart-branding a { display:flex }` (0,1,1) outranked
   the bare `.embed-explore { display:none }` (0,1,0). Both states now carry the branding ancestor, so the hide wins
   on the page and the show wins only under html.embed-mode. */
.chart-branding .embed-explore { display: none; font-size: 12px; color: var(--v8-accent, #1870ff); text-decoration: none; }
html.embed-mode .chart-branding .embed-explore { display: inline; }
.chart-branding .embed-explore:hover { text-decoration: underline; }

/* The Embed popover on the viz (sits beside the utility buttons like the presets popover) */
.v8-embed-wrap { position: relative; display: inline-block; }
.v8-embed-popover {
    position: absolute; right: 0; bottom: calc(100% + 8px); width: 360px; max-width: calc(100vw - 32px);
    background: var(--v8-surface-dropdown); border: 1px solid var(--v8-border-strong); border-radius: 6px;
    padding: 12px; z-index: 70; opacity: 0; transform: translateY(4px); pointer-events: none;
    transition: opacity 150ms, transform 150ms; box-shadow: 0 8px 24px rgba(0,0,0,0.4);
    font-family: 'Archivo', system-ui, sans-serif; font-size: 12px; color: var(--v8-text, inherit); text-align: left;
}
.v8-embed-popover.open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.v8-embed-head { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
.v8-embed-note { margin: 0 0 8px; color: var(--v8-text-muted, #959595); line-height: 1.4; }
.v8-embed-min { margin: 2px 0 4px; color: var(--v8-text-muted, #959595); font-size: 11px; }
.v8-embed-row { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.v8-embed-row label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.v8-embed-lbl { min-width: 48px; color: var(--v8-text-muted, #959595); text-transform: uppercase; letter-spacing: 0.05em; font-size: 10px; }
.v8-embed-row input[type="number"] { width: 72px; font: inherit; padding: 3px 6px; border: 1px solid var(--v8-border-strong); border-radius: 2px; background: transparent; color: inherit; }
#v8-embed-code { width: 100%; box-sizing: border-box; margin-top: 6px; font: 11px/1.4 'JetBrains Mono', ui-monospace, monospace;
    background: rgba(0,0,0,0.18); color: inherit; border: 1px solid var(--v8-border-strong); border-radius: 2px; padding: 6px; resize: vertical; }
.v8-embed-copy { margin-top: 8px; width: 100%; padding: 7px 10px; font: inherit; font-weight: 600; border: 0; border-radius: 6px;
    background: var(--v8-accent, #1870ff); color: #fff; cursor: pointer; }
.v8-embed-copy:hover { filter: brightness(1.1); }

/* ═══════════════════════════════════════════════════════════════════════════════
   UI SWEEP 2026-10-09 (Jon: "comprehensive UI cleanup… all responsive sizes… light,
   dark and dusk") — every rule here fixes a defect seen in the sweep (phone 375 ·
   tablet 768 · desktop, three themes). Token-based, so the three themes agree.
   ═══════════════════════════════════════════════════════════════════════════════ */
/* 1. The fixed theme toggle sat over "Aviation Data" and the end of the title on phones
      (and floated over every card while scrolling). ≤768: it lives in the header corner
      and scrolls with the page; the header text keeps clear of it. */
@media (max-width: 768px) {
    .theme-toggle { position: absolute; top: 0.75rem; right: 0.75rem; }
    .header-left { padding-right: 108px; }
}
/* ≤480: the eyebrow's "/ Aviation Data" wrapped into two lines against the toggle — the
   wordmark alone carries the masthead there (as on the welcome card); the title keeps clear. */
@media (max-width: 480px) {
    .header .header-eyebrow .eyebrow-sep, .header .header-eyebrow .eyebrow-aviation { display: none; }
    .header-left { padding-right: 112px; min-width: 0; }
}
/* 2. The caption ("Showing Time series of…") ran under the utility buttons at phone width —
      the 132px reserve is not enough for a 184px button row. ≤480: the buttons drop below
      the caption, right-aligned. */
@media (max-width: 480px) {
    #v8-ui .control-bar > .chart-utilities { position: static; justify-content: flex-end; margin-top: 10px; }
    #v8-ui .auto-caption { padding-right: 0; }
}
/* 3. The imported-overlay controls (Metric / Split / Roll-up / Clear, all empty) showed on
      every page although the row is `hidden` — `.v8-sched-row { display:flex }` outranked
      the attribute (the same class of bug the schematic layer had on 2026-09-29). */
#v8-ui .v8-sched-row[hidden] { display: none; }
/* 4. Scope pills: three per row truncated every label on phones ("All count…"); two per row
      fits the full words. On tablets the sixth pill wrapped alone — the 3-column grid now
      applies up to 820px. */
@media (max-width: 820px) and (min-width: 721px) {
    #v8-ui .v8-scope-pills { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; align-items: start; }
    #v8-ui .v8-scope-pills .v8-pill-wrap { display: block; width: 100%; min-width: 0; }
    #v8-ui .v8-scope-pills .v8-filter-pill { width: 100%; flex: none; min-width: 0; }
}
@media (max-width: 480px) {
    #v8-ui .v8-scope-pills { grid-template-columns: repeat(2, 1fr); }
}
/* 5. Welcome popup at phone width: "Aviation Data" wrapped into the × — the wordmark alone
      carries the masthead there, with room kept for the control; the matrix notes stay on
      one line so rows do not balloon while the table scrolls sideways. */
@media (max-width: 480px) {
    .welcome-masthead { padding-right: 40px; }
    .welcome-masthead .eyebrow-sep, .welcome-masthead .eyebrow-aviation { display: none; }
    .welcome-matrix td.c small { white-space: nowrap; max-width: none; }
    .welcome-card { padding: 18px 16px; }
}
/* 6. Drilldown KPI tiles clipped their labels on phones ("MANUFACT", "OPERATORS" cut) —
      three tiles per row, labels allowed to wrap. */
@media (max-width: 480px) {
    .ngd-kpi { flex: 1 1 calc(33.333% - 6px); min-width: 0; padding: 6px 7px; }
    .ngd-kpi .l { white-space: normal; line-height: 1.15; }
    .ngd-kpi .v { font-size: 15px; }
}
/* 7. Tally strip on tablets: the auto-fit grid broke the row mid-way, so OPERATORS sat on
      the manufacturers' row. 721–1024px: six columns — the six dataset stats on one row,
      the six manufacturers on the next. */
@media (max-width: 1024px) and (min-width: 721px) {
    #v8-ui .v8-tallies { grid-template-columns: repeat(6, 1fr); }
    #v8-ui .v8-tally-label { letter-spacing: 0.04em; }
}
/* 8. Data table headers wrapped ("FIRST / YEAR") inside a table that already scrolls. */
.table-container th { white-space: nowrap; }
/* 9. Footer line: the "About this data" link never breaks mid-phrase. */
.footer .welcome-open { white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R1 — 2026-10-09 (docs/DESIGN-AUDIT-2026-10-09.md §1.2 – §1.4; Jon's ruling; roadmap §7).
   Two radii · rails → a rule under the section name · three label tiers.
   This is an OVERRIDE block by design: it sits last in the cascade, so the earlier rules it supersedes stay
   in place for the reference census a later cleanup build will run (Rule 5). The hard-coded radii were swept
   IN PLACE in the same build (3 / 4 / 5 / 14 / 20 px → 2 px; 8 / 10 / 12 px → 6 px; 73 declarations).
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── D1a · two radii: 2 px on anything small and interactive, 6 px on the few containers ── */
:root {
    --radius-xs: 2px; --radius-sm: 2px; --radius-md: 2px; --radius-lg: 2px;
    --radius-xl: 6px; --radius-2xl: 6px;
}
/* containers that had been on the small token */
.chart-tooltip, .confirm-dialog, .customer-cap-toast, .year-range-container, .welcome-matrix, .chart-container { border-radius: 6px; }
/* controls that had been on a container radius */
#v8-ui .dropdown-trigger, #v8-ui .v8-histdata-select { border-radius: 2px; }

/* ── D1b · the section rails go; the section NAME carries the accent as a short rule ── */
#v8-ui .control-bar, #v8-ui .v8-filter-section, #v8-ui .v8-histdata-section { border-left: 1px solid var(--v8-border-soft); }
/* notes keep the ONE rail on the page, and it is gold everywhere */
.customer-mode-notes { border-left: 2px solid var(--tac-gold); }

/* ── D2 · tier 1: the four section names — the only uppercase on the page ── */
#v8-ui .v8-view-eyebrow, #v8-ui .v8-filter-eyebrow, #v8-ui .v8-histdata-eyebrow, body.v8-ui-enabled .v8-data-eyebrow {
    display: flex; align-items: center; gap: 10px;
    font-size: 12px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--v8-text-primary);
    margin-bottom: 14px;
}
#v8-ui .v8-view-eyebrow::after, #v8-ui .v8-filter-eyebrow::after, #v8-ui .v8-histdata-eyebrow::after, body.v8-ui-enabled .v8-data-eyebrow::after {
    content: ''; width: 28px; height: 2px; flex: 0 0 28px;
    background: var(--v8-accent-x);
}
#v8-ui .v8-filter-eyebrow::after { background: var(--v8-accent-segment); }
#v8-ui .v8-histdata-eyebrow::after { background: var(--v8-accent-histdata); }
body.v8-ui-enabled .v8-data-eyebrow::after { background: var(--v8-border-strong); }

/* ── D2 · tier 2: control labels — sentence case, untracked, 12 px, muted ── */
#v8-ui .selector-label, #v8-ui .v8-cust-label, #v8-ui .v8-cust-label-suffix, #v8-ui .v8-histdata-label,
#v8-ui .v8-histdata-dim-label, #v8-ui .v8-active-label, #v8-ui .v8-pill-groups-label, #v8-ui .v8-group-members-label,
.year-range-label, .controls-row-label, .filter-group label, .category-qs-label, .v8-embed-row label,
.measurement-panel .mp-endpoints {
    text-transform: none; letter-spacing: 0;
    font-size: 12px; font-weight: 500;
    color: var(--v8-text-muted);
}
#v8-ui .selector-label .dot { display: none; }          /* the accent now lives on the section rule */
#v8-ui .v8-autocomplete-group-badge { text-transform: none; letter-spacing: 0; font-size: 11px; font-weight: 600; }
.legend-mfr-header { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 600; }
/* table heads and the Range | Single switch: sentence case (the welcome matrix keeps its own rule — not adopted) */
th { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 500; }
.year-range-mode-toggle { text-transform: none; letter-spacing: 0; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R2 — 2026-10-09 (audit §1.5; roadmap §7). TABS, NOT PILLS.
   Every segmented control becomes a row of text labels: the active one in the text color with a 2 px
   underline — BLUE for anything that decides what is on the x-axis (dimension, chart type, labels, sort,
   cumulative mode, Range | Single), GOLD for scope and segment (grain, Operator | Buyer). Strip containers
   lose their box; the x-axis strip keeps one hairline under the whole row. Override block, like R1.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── the x-axis strip: one row of eight tabs over a hairline ── */
#v8-ui .chip-strip {
    background: none; border: 0; border-bottom: 1px solid var(--v8-border-soft); border-radius: 0;
    padding: 0; gap: 0 22px; max-width: none; flex-wrap: wrap; align-items: flex-end;
    justify-content: flex-start; align-self: stretch; margin: 0;
    flex-direction: row;   /* the xaxis @container rule stacks the OLD two-tier strip as a column below 620 px; tabs wrap instead */
}
/* the two tiers dissolve: all eight tabs are direct flex items of the strip and wrap as one left-aligned row */
#v8-ui .chip-strip-tier, #v8-ui .chip-strip-tier.primary, #v8-ui .chip-strip-tier.secondary { display: contents; }
#v8-ui .chip-strip-divider { display: none; }
#v8-ui .chip {
    flex: 0 0 auto; padding: 0 0 8px; margin-bottom: -1px;
    font-size: 14px; font-weight: 500; color: var(--v8-text-secondary);
    background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 0; box-shadow: none;
    text-align: left;
    transition: color 150ms, border-color 150ms;
}
#v8-ui .chip:hover { background: none; color: var(--v8-text-primary); }
#v8-ui .chip.active { background: none; color: var(--v8-text-primary); font-weight: 600; border-bottom-color: var(--v8-accent-x); box-shadow: none; }

/* ── chart type: a smaller tab row beneath ── */
#v8-ui .chart-type-strip { background: none; border: 0; border-radius: 0; padding: 0; gap: 4px 18px; max-width: none; justify-content: flex-start; align-self: stretch; }
#v8-ui .chart-type-btn {
    padding: 0 0 2px; font-size: 13px; color: var(--v8-text-secondary);
    background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 0; box-shadow: none;
    transition: color 150ms, border-color 150ms, opacity 150ms;
}
#v8-ui .chart-type-btn:hover { background: none; color: var(--v8-text-primary); }
#v8-ui .chart-type-btn.active { background: none; color: var(--v8-text-primary); font-weight: 600; border-bottom-color: var(--v8-accent-x); box-shadow: none; }
#v8-ui .chart-type-btn.disabled { opacity: 1; color: var(--v8-text-disabled); }
#v8-ui .chart-type-btn.disabled:hover { color: var(--v8-text-disabled); }

/* ── the small switches: grain (gold), cumulative mode (blue), labels / sort (blue), Operator | Buyer (gold), Range | Single (blue) ── */
#v8-ui .v8-timescale, #v8-ui .v8-cumulative-mode, #v8-ui .v8-cust-btn-group, #v8-ui .v8-filter-mode-switch, .year-range-mode-toggle, #v8-ui .v8-cmode-group {
    background: none; border: 0; border-radius: 0; padding: 0; gap: 0 16px; overflow: visible;
}
#v8-ui .v8-ts-btn, #v8-ui .v8-cmode-btn, #v8-ui .v8-cust-btn, #v8-ui .v8-filter-mode-btn, .year-mode-btn {
    padding: 0 0 2px; font-size: 13px; font-weight: 500; color: var(--v8-text-muted);
    background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 0; box-shadow: none; outline: none;
    transition: color 150ms, border-color 150ms;
}
#v8-ui .v8-ts-btn:hover, #v8-ui .v8-cmode-btn:hover, #v8-ui .v8-cust-btn:hover, #v8-ui .v8-filter-mode-btn:hover, .year-mode-btn:hover:not(.active) { background: none; color: var(--v8-text-primary); }
#v8-ui .v8-ts-btn.active, #v8-ui .v8-cmode-btn.active, #v8-ui .v8-cust-btn.active, #v8-ui .v8-cust-btn.auto-active, #v8-ui .v8-filter-mode-btn.active, .year-mode-btn.active {
    background: none; color: var(--v8-text-primary); font-weight: 600; border-bottom-color: var(--v8-accent-x); box-shadow: none; outline: none;
}
#v8-ui .v8-ts-btn.active, #v8-ui .v8-filter-mode-btn.active { border-bottom-color: var(--v8-accent-segment); }
#v8-ui .v8-cust-btn.auto-active { border-bottom-style: dashed; }          /* the auto-chosen label format: a dashed underline, not a dashed box */
#v8-ui .v8-cust-btn.auto-base { background: none; box-shadow: none; }
.year-mode-btn + .year-mode-btn { border-left: 0; }
.year-range-mode-toggle { font-size: 13px; font-weight: 500; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R3 — 2026-10-10 (audit §1.1 scoreboard, §1.11 wire line, the masthead; roadmap §7).
   THE BY-THE-NUMBERS STRIP replaces the twelve stat tiles; THE WIRE LINE replaces the ticker card; the
   masthead's "/ Aviation Data" becomes a sentence-case word after a hairline; Noticia Text is the house
   serif (loaded in index.html; the token --font-serif is the ONE place to name it). Override block, like R1 / R2.
   ═══════════════════════════════════════════════════════════════════════════════ */
:root { --font-serif: 'Noticia Text', Georgia, 'Times New Roman', serif; }

/* ── the strip: one serif line of figures-in-sentences, then the manufacturer counts in house colors ── */
#v8-ui .v8-tallies {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 0;
    background: none; border: 0; border-top: 1px solid var(--v8-border-strong); border-bottom: 1px solid var(--v8-border-strong);
    border-radius: 0; box-shadow: none; padding: 16px 0 14px; margin: 0 0 18px;
}
#v8-ui .v8-tally {
    display: inline-flex; flex-direction: row; align-items: baseline; gap: 8px;
    padding: 0; border: 0; margin: 0; background: none;
}
#v8-ui .v8-tally-value {
    font-family: var(--font-serif); font-size: 27px; font-weight: 700; line-height: 1; letter-spacing: -0.01em;
    color: var(--v8-text-primary); font-variant-numeric: tabular-nums;
}
#v8-ui .v8-tally-suffix, #v8-ui .v8-tally-label {
    font-family: var(--font-serif); font-size: 17px; font-weight: 400; line-height: 1.2;
    color: var(--v8-text-secondary); text-transform: none; letter-spacing: 0; margin: 0;
}
#v8-ui .v8-tally-suffix { margin-left: 0.3em; }
/* the first line reads as a sentence: "1958–2026 years covered · 2018 peak year …" (the markup keeps its capitals) */
#v8-ui .v8-tally:not(.v8-tally-mfr) .v8-tally-label { text-transform: lowercase; }
#v8-ui .v8-tallies > .v8-tally:first-child .v8-tally-label { display: none; }     /* "52,465 deliveries" already says it */
/* a middle dot between the figures on the first line (the host of the manufacturer cells is the 7th child) */
#v8-ui .v8-tally:not(.v8-tally-mfr)::after { content: '\00B7'; font-family: var(--font-serif); font-size: 17px; color: var(--v8-text-muted); margin: 0 12px; }
#v8-ui .v8-tally:nth-child(6)::after { content: none; }
/* the manufacturer counts: a second line, Archivo, the figure in the house color, the name after it */
#v8-ui #v8-tally-mfrs-host { display: flex; flex-basis: 100%; flex-wrap: wrap; gap: 6px 22px; margin-top: 8px; }
#v8-ui .v8-tally.v8-tally-mfr { border: 0; margin: 0; }
#v8-ui .v8-tally-mfr .v8-tally-value { font-family: 'Archivo', system-ui, sans-serif; font-size: 15px; font-weight: 700; letter-spacing: 0; }
#v8-ui .v8-tally-mfr .v8-tally-label { font-family: 'Archivo', system-ui, sans-serif; font-size: 14px; font-weight: 400; color: var(--v8-text-secondary); }
@media (max-width: 480px) {
    #v8-ui .v8-tally-value { font-size: 24px; }
    #v8-ui .v8-tally-suffix, #v8-ui .v8-tally-label { font-size: 15px; }
    #v8-ui .v8-tally:not(.v8-tally-mfr)::after { margin: 0 10px; font-size: 15px; }
    #v8-ui #v8-tally-mfrs-host { gap: 4px 16px; }
}

/* ── the wire line: hairlines, "Latest", the headline in the serif, Subscribe as a gold text link ── */
.tac-ticker {
    background: none; border: 0; border-top: 1px solid var(--v8-border-strong); border-bottom: 1px solid var(--v8-border-strong);
    border-radius: 0; box-shadow: none; padding: 10px 0; margin: 0 0 14px; gap: 16px; align-items: baseline;
}
.tac-ticker-live { display: none; }                                   /* the strip rotates; that is the liveness */
.tac-ticker-brand { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 500; color: var(--v8-text-muted); }
.tac-ticker-headline { font-family: var(--font-serif); font-size: 17px; font-weight: 400; color: var(--v8-text-primary); }
.tac-subscribe-btn { background: none; padding: 0; border-radius: 0; font-size: 13px; font-weight: 600; color: var(--v8-accent-segment-ink); }
.tac-subscribe-btn::after { content: ' \2192'; }
.tac-subscribe-btn:hover { filter: none; text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 520px) { .tac-ticker-brand-txt { display: inline; } .tac-ticker-headline { font-size: 15px; } }

/* ── the masthead: "/ Aviation Data" → a hairline and a sentence-case word ── */
.header-eyebrow .eyebrow-aviation { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 500; color: var(--text-muted); }
.header-eyebrow .eyebrow-sep { font-size: 0; width: 1px; height: 14px; background: var(--border); margin: 0 10px; }

/* R2 follow-up: a wrapped second row of chart-type tabs stays flush left (the buttons had been growing to fill) */
#v8-ui .chart-type-btn { flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R4 — 2026-10-10 (audit §1.8 motion, §1.9 icons; roadmap §7).
   ONE inline line-icon set (app.js `_ICONS` + the SVGs in index.html) replaces every emoji and text glyph; the
   decorative animations go — motion stays only where it reports a state change (the util flash after Copy link,
   the measurement arm, the resume card, the empty state). Override block, like R1 – R3.
   ═══════════════════════════════════════════════════════════════════════════════ */
.ic { width: 14px; height: 14px; display: inline-block; vertical-align: -2px; flex-shrink: 0; }
.theme-opt .ic { width: 15px; height: 15px; vertical-align: middle; }
.theme-toggle .theme-opt { display: inline-flex; align-items: center; justify-content: center; line-height: 1; }
#v8-ui .v8-autocomplete-check .ic { width: 13px; height: 13px; }
.ngd-pill .ic { width: 12px; height: 12px; vertical-align: -2px; margin-right: 2px; }
.data-coverage-note .ic, .age-hint .ic { margin-right: 4px; }
/* the motion diet */
.customer-empty-arrow, .customer-search-input.glow-attention, .variant-toggle-btn-inline.pulse, #v8-ui .chip.pulse-once, .tac-ticker-live { animation: none; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R5 — 2026-10-10 (audit §1.10 numerals, §1.12 copy, §1.13 one frame; the serif; roadmap §7).
   The serif token everywhere a serif was named; Archivo tabular figures where mono had been used for numbers
   (mono stays for code: the embed snippet, kbd); the chart as ONE frame — the legend unboxed, the year range
   a rule with square gold thumbs, the hint and captions in serif italic. Override block, like R1 – R4.
   ═══════════════════════════════════════════════════════════════════════════════ */
/* the serif, by token */
.welcome-lede, body.v8-ui-enabled .customer-empty-subtitle, #v8-ui .auto-caption, .v8-resume-title, .v8-resume-summary,
.v8-resume-filters, #v8-ui .v8-autocomplete-hint { font-family: var(--font-serif); }
/* figures in Archivo, tabular; mono only for code */
.cxc-topn-value, .cxc-slider-bound, #v8-ui .dropdown-item .item-tag, #v8-ui .v8-new-tag, #v8-ui .v8-phase2-tag, .v8-resume-timestamp,
#v8-ui .v8-sched-meta, #v8-ui .v8-pill-dropdown-header, #v8-ui .v8-pill-dropdown-count, #v8-ui .v8-filter-chip-prefix,
#v8-ui .v8-filter-chip-flag, #v8-ui .v8-pill-dropdown-search, .v8-preset-detail, #v8-ui .v8-filter-chip-count {
    font-family: 'Archivo', system-ui, sans-serif; font-variant-numeric: tabular-nums;
}
#v8-ui, .chart-container, .chart-tooltip, .ngd-overlay { font-variant-numeric: tabular-nums; }
/* one frame: the legend sits on the chart surface, no box */
.chart-legend, body.v8-ui-enabled .chart-legend { background: none; padding: 8px 0; }
/* the hint and the captions: serif italic */
.click-hint { font-family: var(--font-serif); font-style: italic; font-size: 13px; color: var(--v8-text-muted); }
#v8-ui .auto-caption { font-size: 14px; border-top: 1px solid var(--v8-border-soft); }
/* the year range: a rule with square gold thumbs, no box */
.year-range-container { background: none; border: 0; border-top: 1px solid var(--v8-border-soft); border-radius: 0; padding: 14px 0 0; margin-top: 10px; }
.year-range-track { height: 2px; background: var(--v8-border-strong); border-radius: 0; }
.year-range-selected { height: 2px; background: var(--tac-blue); border-radius: 0; }
.year-range-thumb { width: 12px; height: 12px; background: var(--tac-gold); border: 0; border-radius: 2px; box-shadow: none; }
.year-range-thumb:hover, .year-range-thumb.dragging { box-shadow: 0 0 0 4px rgba(254, 171, 64, 0.25); }
@media (pointer: coarse) { .year-range-thumb { width: 18px; height: 18px; } }
/* the title pencils: line icons */
.chart-title-btn .ic { width: 13px; height: 13px; vertical-align: -2px; }

/* ═══════════════════════════════════════════════════════════════════════════════
   DESIGN REFRESH R6 — 2026-10-10 (the component sheet's hover tooltip, drilldown head and notes; Jon: "make sure
   the proposed component sheet, including hover tooltip, is reflected in the current visual rebuild").
   Override block, like R1 – R5.
   ═══════════════════════════════════════════════════════════════════════════════ */
/* the hover tooltip: serif title, tabular rows, a hairline foot with two text links (gold measure · blue open) */
.chart-tooltip { border-radius: 6px; min-width: 200px; }
.chart-tooltip .v8x-tt-head { padding: 10px 12px 6px; }
.chart-tooltip .v8x-tt-title { font-family: var(--font-serif); font-size: 20px; font-weight: 700; letter-spacing: 0; }
.chart-tooltip .v8x-tt-sub { font-family: 'Archivo', system-ui, sans-serif; font-size: 12px; margin-top: 2px; }
.chart-tooltip .v8x-tt-row { font-size: 13px; padding: 3px 12px; }
.chart-tooltip .v8x-tt-row .tooltip-color { width: 10px; height: 10px; border-radius: 2px; }
.chart-tooltip .v8x-tt-foot { background: none; border-top: 1px solid var(--tooltip-border); border-radius: 0; padding: 8px 12px; font-size: 12px; }
.chart-tooltip .v8x-tt-measure { font-weight: 600; }
.chart-tooltip .v8x-tt-drill { font-weight: 600; }
.chart-tooltip .v8x-tt-measure:hover, .chart-tooltip .v8x-tt-drill:hover { filter: none; text-decoration: underline; text-underline-offset: 3px; }
.chart-tooltip .v8x-tt-undis .ic { width: 12px; height: 12px; margin-right: 2px; color: var(--tooltip-ink-gold); }
/* the drilldown head: six KPI tiles become one serif line; the coverage pill becomes a serif-italic sentence */
.ngd-kpis { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 0; padding: 12px 16px 10px; }
.ngd-kpi { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 6px; background: none; border: 0; border-radius: 0; padding: 0; min-width: 0; }
.ngd-kpi .v { font-family: var(--font-serif); font-size: 20px; font-weight: 700; line-height: 1.1; }
.ngd-kpi .l { font-family: var(--font-serif); font-size: 14px; color: var(--muted); text-transform: lowercase; letter-spacing: 0; line-height: 1.2; }
.ngd-kpi::after { content: '\00B7'; font-family: var(--font-serif); font-size: 14px; color: var(--muted); margin: 0 10px; }
.ngd-kpi:last-of-type::after { content: none; }
.ngd-pill { font-family: var(--font-serif); font-style: italic; font-size: 13px; color: var(--muted); background: none; border: 0; padding: 0; margin-top: 6px; }
.ngd-pill .ic { display: none; }
@media (max-width: 480px) {
    .ngd-kpi { flex: 0 0 auto; padding: 0; }
    .ngd-kpi .v { font-size: 17px; }
    .ngd-kpi .l { font-size: 13px; }
    .ngd-kpi::after { margin: 0 7px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SUB-YEAR BOUNDS + THE EYEBROW (2026-10-11) — Jon: the year range interrogates one
   quarter or one month; the eyebrow reads AVIATION DATA | BETA (BETA in TAC blue).
   ═══════════════════════════════════════════════════════════════════════════ */
/* The paired period selects show only at the quarter / month grain (`.has-sub` is
   stamped by yearRangeSlider.syncSubSelects); single mode keeps only the start pair. */
.year-range-values .year-sub-wrap { display: none; }
.year-range-values.has-sub .year-sub-wrap { display: inline-block; }
.year-range-values.has-sub .year-sub-wrap select { min-width: 3.4ch; }
.year-range-values.single-mode #yearRangeMaxSubWrap { display: none; }
/* The eyebrow: the section name in caps, tracked; BETA in TAC blue (#1870ff). */
.header-eyebrow .eyebrow-aviation { text-transform: uppercase; letter-spacing: 0.12em; }
.header-eyebrow .eyebrow-beta { color: #1870ff; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; margin-left: 8px; white-space: nowrap; }
@media (max-width: 480px) { .header .header-eyebrow .eyebrow-beta, .welcome-masthead .eyebrow-beta { display: none; } }
/* 2026-10-11 (Jon): no double rules around the headlines — the header draws the hairline ABOVE
   (its bottom border) and the by-the-numbers strip draws the ONE hairline BELOW (its top border),
   so the wire line draws none of its own. Spacing is symmetric.
   2026-10-12 (Jon): "bring the horizontal lines … halfway closer" — 24 px → 12 px each side:
   above = header margin 14 − 2 + padding 0; below = padding 0 + margin 12. */
.tac-ticker { border-top: 0; border-bottom: 0; padding-top: 0; padding-bottom: 0; margin-top: -2px; margin-bottom: 12px; }

/* ═══════════════════════════════════════════════════════════════════════════
   SCOPE DROPDOWNS ON PHONES (2026-10-12) — Jon's screenshots: the manufacturer, country and
   family panels clipped at the viewport edges; only Regions opened cleanly.
   WHY: the ≤480 breakpoint turns the six scope pills into a TWO-column grid (UI sweep
   2026-10-09) but the per-column anchoring written for the three-column grid still ran —
   child 1/4 left-anchored, 2/5 centred, 3/6 right-anchored — so a centred panel under a
   right-column pill spilled right, a right-anchored panel under a left-column pill spilled
   left, and `width: max-content` made every panel wider than its column. On a phone the
   panel now spans the WHOLE pills block: the grid is the positioning context, the wrap is
   static, every panel is left 0 / right 0 below the block (its own list still scrolls). */
@media (max-width: 480px) {
    #v8-ui .v8-scope-pills { position: relative; }
    #v8-ui .v8-scope-pills .v8-pill-wrap { position: static; }
    #v8-ui .v8-scope-pills .v8-pill-wrap .v8-pill-dropdown,
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n+1) .v8-pill-dropdown,
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n+2) .v8-pill-dropdown,
    #v8-ui .v8-scope-pills .v8-pill-wrap:nth-child(3n) .v8-pill-dropdown {
        left: 0; right: 0; width: auto; min-width: 0; max-width: none; transform: none;
        top: calc(100% + 6px);
    }
    /* The quick-add chip row (EU · G7 · G20 · BRIC · ASEAN …; the family presets) was a
       741-px strip scrolling sideways inside a 323-px panel — it wraps on a phone. */
    #v8-ui .v8-pill-dropdown .v8-pill-dropdown-groups { flex-wrap: wrap; overflow-x: visible; row-gap: 6px; }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   USER GUIDE LINK ON THE WELCOME SCREEN (2026-10-16, Jon) — a text link beside the
   Explore button, in the tooltip-foot link style (blue, no underline until hover).
   ═══════════════════════════════════════════════════════════════════════════════ */
.welcome-actions { display: inline-flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.welcome-text .welcome-guide { font-family: var(--font-ui); font-weight: 600; font-size: 14px; color: var(--tac-blue); text-decoration: none; white-space: nowrap; }
.welcome-text .welcome-guide:hover { text-decoration: underline; text-underline-offset: 2px; color: var(--tac-blue); }

/* ═══════════════════════════════════════════════════════════════════════════════
   USER GUIDE LINK UNDER THE CHART (2026-10-16, Jon) — beside the hint line on every
   view: the hint stays serif italic, the link is the tooltip-foot text link (blue,
   underline on hover). `.chart-branding .chart-guide-link` outranks the row's
   `.chart-branding a { display:flex }` (the embed-explore lesson); hidden in embeds.
   ═══════════════════════════════════════════════════════════════════════════════ */
.chart-branding .chart-hint-wrap { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; min-width: 0; }
.chart-branding .chart-guide-link { display: inline; font-family: var(--font-ui); font-size: 13px; font-weight: 600; color: var(--tac-blue); text-decoration: none; white-space: nowrap; }
.chart-branding .chart-guide-link:hover { text-decoration: underline; text-underline-offset: 2px; }
html.embed-mode .chart-branding .chart-guide-link { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════════
   "YEARS:Years" UNDOUBLED (2026-10-16): at ≤768 px a July rule hid the label's text
   (font-size 0) and printed "Years:" from ::before; the design-refresh tier-2 rule
   (12 px) restored the text, so both showed. The markup's "Years" is the label now.
   ═══════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
    .year-range-label::before { content: none; }
}

/* ── INLINE TITLE / SUBHEAD EDITOR (2026-10-17, replaces window.prompt) ─────────────────────────────── */
.inline-edit {
    font: inherit; color: inherit; letter-spacing: inherit;
    background: var(--v8-surface-section, transparent);
    border: 1px solid var(--v8-border-strong, #888); border-radius: 2px;
    padding: 1px 6px; margin: -2px 0;
    width: 100%; min-width: 16ch; max-width: 100%; box-sizing: border-box;
    outline: none;
}
.inline-edit:focus { border-color: #1870ff; box-shadow: 0 0 0 2px rgba(24, 112, 255, 0.18); }

/* ── SHOW LOGOS IN THE CUSTOMER KEY (2026-10-17) ─────────────────────────────────────────────────────── */
.chart-legend .legend-mfr-header.has-logo { display: inline-flex; align-items: center; gap: 6px; }
.legend-header-logo { height: 16px; width: auto; max-width: 44px; object-fit: contain; background: #fff; border-radius: 2px; padding: 1px; flex-shrink: 0; }

/* ── THE EMBED'S SOURCE LINE (2026-10-17): "Source: Boeing, Airbus & ATR", medium gray, embeds only ─────────── */
.chart-branding .chart-source { display: none; font-size: 12px; color: var(--text-muted); letter-spacing: 0.01em; }
html.embed-mode .chart-branding .chart-source { display: inline; }


/* ═══ RELEASE QA E2 + F-04 (2026-10-17): keyboard access to the legend, the tooltip's links and the chart ═══ */
/* The tooltip's two links are <button>s now (they were spans) — reset the control chrome so they read as the
   same text links; the colour, weight and hover rules above still apply by class. */
.chart-tooltip .v8x-tt-measure, .chart-tooltip .v8x-tt-drill {
    background: none; border: 0; padding: 0; margin: 0; font: inherit; line-height: inherit; color: inherit;
    cursor: pointer; appearance: none; -webkit-appearance: none;
}
.chart-tooltip .v8x-tt-drill { color: var(--tooltip-ink-accent); }
.chart-tooltip .v8x-tt-measure { color: var(--tooltip-ink-gold); }
.chart-tooltip .v8x-tt-measure:focus-visible, .chart-tooltip .v8x-tt-drill:focus-visible,
.chart-legend .legend-clickable:focus-visible,
#timeChart:focus-visible {
    outline: 2px solid var(--v8-accent-x);
    outline-offset: 2px;
    border-radius: 2px;
}
.chart-legend .legend-clickable:focus-visible { background-color: rgba(24, 112, 255, 0.08); }
#timeChart:focus { outline: none; }                 /* a pointer click never draws the ring */
#timeChart:focus-visible { outline: 2px solid var(--v8-accent-x); outline-offset: -2px; }

/* ═══ RELEASE QA E4 (2026-10-17): the drilldown's controls are keyboard controls — one visible focus ring ═══ */
.ngd-modal [tabindex="0"]:focus-visible, .ngd-modal button:focus-visible, .ngd-modal select:focus-visible,
.ngd-modal th.sortable:focus-visible {
    outline: 2px solid var(--v8-accent-x, #1870ff);
    outline-offset: 1px;
}
.ngd-modal .ngd-seg [data-view]:focus-visible, .ngd-modal .ngd-tchips [data-tf]:focus-visible { outline-offset: -2px; }

/* ═══ RELEASE QA F-05 (2026-10-18): gold TEXT reads through the ink token — the raw gold (#feab40) is 1.9:1 on the
   light page. --v8-accent-segment-ink is #9a5c00 on light (≥ 5.1:1 on every light surface) and the raw gold on dusk
   and dark, so those two themes do not change. Fills, swatches, underlines and borders keep --v8-accent-segment. ═══ */
#periodTotal .subhead-scope,
.update-instructions .known-issues p.lim b,
#v8-ui .v8-new-tag,
#v8-ui .v8-filter-eyebrow,
#v8-ui .v8-filter-chip-prefix { color: var(--v8-accent-segment-ink); }

/* ═══ RELEASE QA F-11 + F-14 (2026-10-18): 24-px targets and the blue text ink on light ═══ */
/* F-11 — WCAG 2.5.8 Target Size (Minimum). Every undersized pointer target gets a 24-px HIT BOX without a visual change:
   a ::after pseudo-element extends the clickable area (a pseudo-element belongs to its element, so the click lands on
   the control); the painted swatch, tab underline and link text stay exactly as drawn. Coarse pointers already get
   36–44 px from the existing (pointer: coarse) rules. */
.chart-legend .legend-color-btn, button.chip-color-btn,
.chart-title-btn, #chartGuide, .tac-subscribe-btn, .footer .welcome-open, .welcome-text .welcome-guide, a.eyebrow-logo,
#v8-ui .v8-ts-btn, #v8-ui .v8-cmode-btn, #v8-ui .v8-cust-btn, #v8-ui .v8-filter-mode-btn, .year-mode-btn, .chart-type-btn { position: relative; }
.chart-legend .legend-color-btn::after { content: ''; position: absolute; inset: -1.5px -5px; } /* 14 → 24 wide; vertically the ROW's own 17 px — a taller box would take the neighbouring row's clicks */
button.chip-color-btn::after { content: ''; position: absolute; inset: -6px; }                   /* 12 → 24 */
.chart-title-btn::after { content: ''; position: absolute; inset: -4px -2px; }                  /* 19–23 → 27+ */
#chartGuide::after, .tac-subscribe-btn::after, .footer .welcome-open::after, .welcome-text .welcome-guide::after, a.eyebrow-logo::after { content: ''; position: absolute; inset: -4px 0; }
#v8-ui .v8-ts-btn::after, #v8-ui .v8-cmode-btn::after, #v8-ui .v8-cust-btn::after, #v8-ui .v8-filter-mode-btn::after, .year-mode-btn::after, .chart-type-btn::after { content: ''; position: absolute; inset: -3px 0; }
/* NOT changed: the legend ROW pitch (17 px). A 24-px pitch is a design ruling — it adds up to ~200 px to the variant legend. */
#v8-ui .v8-cust-slider { min-height: 24px; }                                                    /* the range input's hit height; the 12-px thumb is unchanged */
#v8-embed-height { min-height: 24px; }
.year-range-values select { min-height: 24px; }                                                 /* the native year picker: 14 → 24 px tall */
/* F-14 — WCAG 1.4.3: small blue text on the light theme reads through --link-ink (#0059eb); on dusk and dark the token is
   the raw blue, so nothing moves there. Fills, underlines, rings and the chart's own blue keep --tac-blue. */
.header-eyebrow .eyebrow-beta, .welcome-masthead .eyebrow-beta,
.welcome-text .welcome-guide, .chart-branding .chart-guide-link, .footer .welcome-open,
.update-instructions summary,
#v8-ui .v8-cust-topn-value,
.year-range-values select, .year-range-values #yearRangeSeparator { color: var(--link-ink); }

/* ═══ RELEASE QA F-17 (2026-10-18): 320-px phones — the light wordmark (222 px wide against the dark one's 157) plus the
   112-px reserve for the theme toggle overran a 320-px viewport by 14 px. Below 360 px the wordmark scales to the width it has. ═══ */
@media (max-width: 360px) {
    .header-left { min-width: 0; }
    .header-eyebrow, .header-eyebrow .eyebrow-logo { max-width: 100%; }
    .header-eyebrow .eyebrow-logo img { max-width: 100%; height: auto; }
}

/* ═══ RELEASE QA F-18 (2026-10-18): the embed's Notes option — `notes=0` hides the three advisory notes in an embed ═══ */
html.embed-no-notes #dataAvailabilityNote, html.embed-no-notes #customerModeNotes, html.embed-no-notes #v8RecordNote { display: none !important; }

/* ═══ CLEANUP 2026-10-18 (Jon): (1) the X-axis tabs' underline sits as close under the word as the chart-type tabs'
   (2 px, the "Stacked" reference — the R2 block had 8 px); the tab keeps its −1 px overlap onto the strip's hairline.
   (2) the drilldown's variant chip on the LIGHT theme: a solid fill in the manufacturer's house colour with white text
   (the inline tint — 20 % fill, 55 %-lightened text — was unreadable on white); --vc is set inline by ngdVchipStyle. ═══ */
#v8-ui .chip { padding: 0 0 2px; }
#v8-ui .chip-strip { row-gap: 6px; }   /* the 8 px padding had spaced a wrapped second row of tabs; the strip's row gap does now */
:root:not([data-theme="dark"]):not([data-theme="dusk"]) .ngd-vchip {
    background: var(--vc, #5c5c5c) !important; border-color: var(--vc, #5c5c5c) !important; color: #fff !important;
}

/* ═══ CUSTOMER ROLES B2′ (2026-10-18): the search row's two role figures beside the union — "flew 595 · bought 657" ═══ */
#v8-ui .v8-autocomplete-roles { display: block; font-size: 11px; color: var(--v8-text-muted); font-variant-numeric: tabular-nums; margin-top: 1px; }

/* ═══ CUSTOMER ROLES B3′ (2026-10-18): the Operator | Buyer VIEW tabs sit in the customer row and decide what the
   x-axis means — BLUE underline (R2's x-axis rule), where the Scope-era switch had the gold one; the buyer-kind
   tabs in Scope (All · Lessors · Airlines & others) are a scope filter — gold. The old box styles of the switch
   and the retired Lessors-only toggle (.v8-buyer-scope's toggle) are superseded by the R2 tab rules. ═══ */
#v8-ui .v8-cust-view .v8-filter-mode-switch { display: inline-flex; gap: 0 14px; background: none; border: 0; padding: 0; }
#v8-ui .v8-cust-view .v8-filter-mode-btn { padding: 0 0 2px; font-size: 13px; border-radius: 0; }
#v8-ui .v8-cust-view .v8-filter-mode-btn.active { background: none; border-bottom-color: var(--v8-accent-x); }
/* B5′ (2026-10-19, Jon): the buyer-kind filter left Scope for the line UNDER the Operator | Buyer tabs — two
   independent check switches (Lessors · Airlines & others), a 12-px square that fills gold when on (scope colour,
   so they read as a qualifier of the blue view above them, never as more tabs); the view control becomes a grid so
   the switches sit indented under the tabs, not under the "View" label. One of the two stays on. */
#v8-ui .v8-cust-view { display: grid; grid-template-columns: auto auto; column-gap: 8px; row-gap: 4px; align-items: center; }
#v8-ui .v8-cust-view .v8-buyer-kinds { grid-column: 2; display: flex; flex-wrap: wrap; gap: 0 14px; }
#v8-ui .v8-cust-view .v8-buyer-kinds[hidden] { display: none; }
#v8-ui .v8-bkind-btn {
    display: inline-flex; align-items: center; gap: 6px; min-height: 24px; padding: 0; margin: 0;
    background: none; border: 0; border-radius: 0; cursor: pointer;
    font-family: 'Archivo', system-ui, sans-serif; font-size: 12px; font-weight: 500; line-height: 1;
    color: var(--v8-text-muted);
}
#v8-ui .v8-bkind-btn.active { color: var(--v8-text-primary); }
#v8-ui .v8-bkind-box {
    width: 12px; height: 12px; box-sizing: border-box; flex: 0 0 12px;
    border: 1.5px solid var(--v8-border-strong); border-radius: 2px; background: none; position: relative;
}
#v8-ui .v8-bkind-btn.active .v8-bkind-box { border-color: var(--v8-accent-segment); background: var(--v8-accent-segment); }
#v8-ui .v8-bkind-btn.active .v8-bkind-box::after {
    content: ''; position: absolute; left: 3px; top: 0.5px; width: 3px; height: 6px;
    border: solid #fff; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
#v8-ui .v8-bkind-btn:focus-visible { outline: 2px solid var(--v8-accent-x); outline-offset: 2px; }
#v8-ui .v8-bkind-btn:hover .v8-bkind-box { border-color: var(--v8-accent-segment); }

/* ═══ CUSTOMER ROLES B4′ (2026-10-19): the muted era detail inside a hover's name — "now US Airways" on a period's
   row, "Allegheny Airlines 1960–1978 · USAir 1979–1996" under a bar that spans the window. ═══ */
.chart-tooltip .v8x-tt-era { display: block; font-size: 11px; font-weight: 400; opacity: .68; line-height: 1.25; margin-top: 1px; }
.chart-tooltip .v8x-tt-title .v8x-tt-era { font-family: var(--font-ui, inherit); font-style: normal; font-size: 12px; }

/* 2026-10-20 (Jon): the eyebrow's bar sits as far from BETA as it does from DATA. The bar is its own span (the
   "| BETA" text had put one space — 3.8 px — after it against 16 px before it); the right margin below makes the
   space after the bar equal the space before it, and the bar's own tracking is removed so it does not add to the gap. */
.header-eyebrow .eyebrow-beta-bar, .welcome-masthead .eyebrow-beta-bar { letter-spacing: 0; margin-right: 16px; }

/* 2026-10-20 (Jon): three cleanups. (1) The headline strip's Subscribe link in caps, tracked like the eyebrow.
   (2) The Buyers check switches take the VIEW's blue (--v8-accent-x), not the scope gold — they belong to the
   Operator | Buyer tabs above them. (3) The customer row's "View" and "Labels" labels: the two controls that can
   stack on the left edge share one label column (Operator and Name start at the same x), and every label in the
   row sits on its tabs' BASELINE — the tabs carry a 2-px underline pad, so centring the boxes had put each label
   about 2 px below the words beside it. */
.tac-subscribe-btn { text-transform: uppercase; letter-spacing: 0.08em; }
#v8-ui .v8-bkind-btn.active .v8-bkind-box { border-color: var(--v8-accent-x); background: var(--v8-accent-x); }
#v8-ui .v8-bkind-btn:hover .v8-bkind-box { border-color: var(--v8-accent-x); }
#v8-ui .v8-cust-row .v8-cust-control { align-items: baseline; }
#v8-ui .v8-cust-row .v8-cust-control.v8-cust-cluster,
#v8-ui .v8-cust-row .v8-cust-control:has(input[type="range"]) { align-items: center; }   /* a toggle or a slider has no text baseline */
#v8-ui .v8-cust-view .v8-cust-label, #v8-ui .v8-cust-labels .v8-cust-label { min-width: 40px; }

/* 2026-10-20 (Jon): the headline strip's three items centred VERTICALLY on one line — "Latest", the rotating
   headline and SUBSCRIBE had shared a text baseline, which set the 17-px serif headline about 2.5 px above the
   centre of the two 12–13-px labels beside it. */
.tac-ticker, .tac-ticker.tac-ticker-in { align-items: center; }
.tac-ticker .tac-ticker-brand, .tac-ticker .tac-subscribe-btn { display: inline-flex; align-items: center; }

/* SCOPE NOTES (2026-10-20, Jon: the footer's "Scope, limits by manufacturer and known issues" brought up to date):
   the cross-manufacturer notes under the six cards — a plain list, left-justified like the cards, the lead phrase
   in the text colour. */
.update-instructions .known-issues-notes {
    margin: var(--space-3) 0 0;
    padding-left: 1.1em;
    text-align: left;
    font-size: var(--text-sm);
    line-height: 1.45;
    color: var(--text-muted);
}
.update-instructions .known-issues-notes li { margin: 0 0 var(--space-1); }
.update-instructions .known-issues-notes b { color: var(--text); font-weight: 600; }

/* THE WORDMARK STAYS RIGHT (2026-10-19, Jon: "TAC logo and wordmark on the chart in responsive smaller widths should be
   right justified, not left"): the row is space-between, so a wordmark that WRAPS onto its own line (481–768 px) sat at the
   left, and at ≤480 px the row stacks as a left-aligned column. The auto margin pushes it right on any line; the column
   aligns it to the end. */
.chart-branding .chart-wordmark { margin-left: auto; }
@media (max-width: 480px) {
    .chart-branding .chart-wordmark { align-self: flex-end; margin-left: 0; }
}

/* 2026-10-19 (Jon, on-device): the HOVER tooltip's × on phones — hidden everywhere else (the media block near the top
   shows it under (pointer: coarse) and (max-width: 720px)). A 24-px tap box, the frozen ×'s muted ink, top-right. */
.chart-tooltip .v8x-tt-hclose {
    display: none;
    align-items: center; justify-content: center;
    width: 24px; height: 24px; margin: -4px -6px 0 auto; padding: 0;
    background: none; border: 0; cursor: pointer;
    color: var(--tooltip-muted); font-size: 20px; line-height: 1;
    align-self: flex-start; flex: 0 0 auto;
}
.chart-tooltip .v8x-tt-hclose:hover { color: var(--tooltip-text); }

/* 2026-10-19 (Jon: "the drilldown windows aren't opening in the center of the window"): inside a same-origin frame the
   host stretches to the page's full height (theaircurrent.com), the centred layers centre on the part of the frame that
   is ON SCREEN — --frame-top / --frame-h / --frame-bottom, written by _syncFrameBand() in app.js (html.in-frame).
   Outside a frame nothing here applies. */
html.in-frame .ngd-overlay,
html.in-frame .confirm-overlay,
html.in-frame .welcome-overlay,
html.in-frame #v8-resume-prompt {
    top: var(--frame-top, 0px);
    bottom: auto;
    height: var(--frame-h, 100vh);
}
html.in-frame .ngd-modal { max-height: calc(var(--frame-h, 100vh) * 0.9); }
html.in-frame .customer-color-picker.ccp-centered { top: calc(var(--frame-top, 0px) + var(--frame-h, 100vh) / 2); }
html.in-frame .customer-cap-toast { bottom: calc(var(--frame-bottom, 0px) + 1.5rem); }

