/* ============================================================
   PULSE // MISSION CONTROL — visual skin (V20.14.47).
   Loaded LAST on every surface. A single, opinionated identity: deep-space
   glass panels with HUD brackets, electric signal lines, telemetry, and glow
   that carries meaning (live = green, selected = signal cyan, alert = amber,
   critical = red, projection = violet). Everything derives from the tokens in
   pulse-tokens.css; this sheet re-tunes the palette and layers the effects.
   Light theme ("Daylight Ops") keeps the same geometry with paper surfaces
   and ink lines. Reduced motion removes every ambient animation.
   ============================================================ */

/* ---------- 1. Palette re-tune ---------- */
:root {
  /* Lifted one step (pass 14): the void was #03060d, close to black, and the
     page read as a hole rather than a surface. Still navy, still dark. */
  --bg-void: #0a1322;
  --bg-deep: #0e192c;
  --bg-panel: #132240;
  --bg-panel-hi: #192d4d;
  --bg-panel-line: rgba(0, 229, 255, .16);
  --line: rgba(0, 229, 255, .16);
  --line-strong: rgba(0, 229, 255, .32);
  --bg-input: rgba(4, 10, 22, .85);
  --bg-hover: rgba(0, 229, 255, .07);
  --bg-selected: rgba(0, 229, 255, .14);
  --cyan: #00e5ff;
  --cyan-dim: #0b6b7d;
  --cyan-soft: rgba(0, 229, 255, .10);
  --cyan-line: rgba(0, 229, 255, .34);
  --gold: #ffb020;
  --gold-soft: rgba(255, 176, 32, .12);
  --gold-line: rgba(255, 176, 32, .36);
  --green: #48ffb4;
  --green-soft: rgba(72, 255, 180, .11);
  --green-line: rgba(72, 255, 180, .34);
  --red: #ff4d6d;
  --red-soft: rgba(255, 77, 109, .12);
  --red-line: rgba(255, 77, 109, .36);
  --purple: #9d8bff;
  --purple-soft: rgba(157, 139, 255, .13);
  --blue: #5ea3ff;
  --text-hi: #e8f3ff;
  --text-mid: #a2b6d2;
  --text-dim: #8298b8; /* WCAG AA: 4.57 on the dark panel, 4.68 on the lighter panel tone */
  --chart-1: #00e5ff; --chart-2: #ffb020; --chart-3: #48ffb4; --chart-4: #9d8bff; --chart-5: #ff8a4d; --chart-6: #5ea3ff; --chart-7: #ff6fb1;
  --chart-grid: rgba(0, 229, 255, .12); --chart-axis: #7189ab; --chart-label: #a2b6d2; --chart-label-hi: #e8f3ff; --chart-tooltip-bg: #08101f;
  --chart-positive: #48ffb4; --chart-negative: #ff4d6d; --chart-target: #ffb020; --chart-forecast: #9d8bff;
  --shadow-md: 0 10px 30px rgba(0, 0, 0, .45);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .6);
  --glow-cyan: 0 0 18px rgba(0, 229, 255, .28);
  --glow-cyan-strong: 0 0 28px rgba(0, 229, 255, .45), 0 0 2px rgba(0, 229, 255, .9);
  --glow-green: 0 0 14px rgba(72, 255, 180, .45);
  --glow-gold: 0 0 14px rgba(255, 176, 32, .45);
  --glow-red: 0 0 14px rgba(255, 77, 109, .5);
  --mc-glass: linear-gradient(160deg, rgba(22, 38, 66, .80), rgba(12, 22, 40, .84));
  --mc-glass-hi: linear-gradient(160deg, rgba(30, 50, 84, .88), rgba(16, 28, 50, .9));
  --mc-bracket: rgba(0, 229, 255, .55);
  --mc-scan: rgba(255, 255, 255, .018);
  --brand-portfolio: #9d8bff;
  --pulse-bg-void: var(--bg-void); --pulse-bg-deep: var(--bg-deep); --pulse-bg-panel: var(--bg-panel); --pulse-bg-panel-hi: var(--bg-panel-hi);
  --pulse-line: var(--line); --pulse-cyan: var(--cyan); --pulse-gold: var(--gold); --pulse-green: var(--green); --pulse-red: var(--red);
  --pulse-text-hi: var(--text-hi); --pulse-text-mid: var(--text-mid); --pulse-text-dim: var(--text-dim);
}
:root[data-theme="light"] {
  /* V20.14.353 -- slate: the same glass, glows and brackets as the dark HUD above, in the slate cyan (#007ea8) and
     gold (#8a6200) on the slate panel (#f5f9fc). The glass is the panel itself, so a light panel is the colour Ramy
     named, and the brackets are the full accent, as the dark ones are the full dark accent. */
  --glow-cyan: 0 0 18px rgba(0, 126, 168, .20);
  --glow-cyan-strong: 0 0 0 1px rgba(0, 126, 168, .30), 0 0 26px rgba(0, 126, 168, .24);
  --glow-green: 0 0 15px rgba(15, 118, 110, .20);
  --glow-gold: 0 0 15px rgba(138, 98, 0, .18);
  --glow-red: 0 0 15px rgba(194, 56, 58, .18);
  --mc-glass: linear-gradient(160deg, #f5f9fc, #f5f9fc);
  --mc-glass-hi: linear-gradient(160deg, #f5f9fc, #eaf1f7);
  --mc-bracket: #007ea8;
  --mc-scan: rgba(0, 40, 80, .012);
}

/* ---------- 2. Deep-space ground: glows, perspective grid, scanlines ---------- */
html.mc-has-telemetry body { padding-top: 34px; }
body {
  background-color: var(--bg-void) !important;
  background-image:
    radial-gradient(ellipse 900px 520px at 12% -10%, rgba(0, 229, 255, .10), transparent 60%),
    radial-gradient(ellipse 700px 480px at 92% 8%, rgba(157, 139, 255, .09), transparent 60%),
    radial-gradient(ellipse 1200px 500px at 50% 110%, rgba(0, 229, 255, .07), transparent 60%) !important;
  background-attachment: fixed !important;
}
/* V20.14.202 -- the light ground used to be painted here as well: a white
   background-color and a blueprint grid, both !important. Neither ever
   reached a pixel. pulse-light-revamp.css declares the same two properties
   with !important on the identical selector and loads after this file on
   every page that loads either, so it won on order. Removing a rule that
   never rendered changes nothing on screen and leaves one owner. */
:root[data-theme="light"] body::after { display: none !important; }

/* ---------- 3. Telemetry bar ---------- */
.mc-telemetry {
  position: fixed; top: 0; left: 0; right: 0; height: 34px; z-index: 1500;
  display: flex; align-items: center; gap: 14px; padding: 0 16px;
  background: linear-gradient(90deg, rgba(4, 9, 20, .96), rgba(6, 14, 28, .94) 50%, rgba(4, 9, 20, .96));
  border-bottom: 1px solid var(--line-strong);
  box-shadow: 0 1px 0 rgba(0, 229, 255, .12), 0 8px 24px rgba(0, 0, 0, .35);
  font: 600 11px var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
/* V20.14.172 -- the gateway rail joins the light theme.
   It used to stay dark in both, on the argument that it reads as instrument
   chrome rather than page surface. He reported it: "control panel in the upper
   right corner is ugly in light theme", and he is right about the effect if not
   the cause. The rail was the ONE dark band left on a white page, and the
   cluster inside it draws its glyphs in #9fb6d3 on that band -- pale blue on
   near-black, immediately under a white header. It read as an artefact rather
   than as chrome, and the argument for keeping it dark was about how it reads
   in isolation rather than in the page it sits on.
   Same rail, same information, same layout; daylight key. The values are the
   ones the other three headers already use (body > .topbar, .pulse-sticky-header,
   .cp-sticky-shell), so the four bands of chrome on a light page now agree
   instead of three agreeing and one not. */
:root[data-theme="light"] .mc-telemetry { background: linear-gradient(180deg, #ffffff 0%, #f6fbff 100%); border-bottom-color: rgba(7, 143, 197, .30); box-shadow: 0 1px 0 rgba(7, 185, 234, .18), 0 6px 20px rgba(20, 50, 90, .07); color: #566d88; }
:root[data-theme="light"] .mc-telemetry .mc-tel-brand { color: #0b2039; }
:root[data-theme="light"] .mc-telemetry .mc-tel-brand b { color: #0a6d94; }
:root[data-theme="light"] .mc-telemetry .mc-tel-item b { color: #143352; }
:root[data-theme="light"] .mc-telemetry .mc-tel-item .hud-icon { color: #0d8bb0; }
:root[data-theme="light"] .mc-telemetry .mc-tel-page { color: #0a6d94; border-color: rgba(7, 143, 197, .38); background: rgba(7, 185, 234, .10); }
:root[data-theme="light"] .mc-telemetry .mc-tel-page small { color: #566d88; }
.mc-tel-left, .mc-tel-right { display: flex; align-items: center; gap: 14px; min-width: 0; }
.mc-tel-right { margin-left: auto; }
.mc-tel-brand { display: inline-flex; align-items: center; gap: 6px; color: var(--text-hi); letter-spacing: .26em; font-weight: 700; white-space: nowrap; }
.mc-tel-brand b { color: var(--cyan); font-weight: 700; text-shadow: var(--glow-cyan); }
.mc-tel-brand .hud-icon { color: var(--cyan); filter: drop-shadow(0 0 6px rgba(0,229,255,.6)); }
.mc-tel-logo { width: 20px; height: 20px; margin-right: 4px; border-radius: 50%; filter: drop-shadow(0 0 6px rgba(0,229,255,.55)); }
.mc-tel-page { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border: 1px solid var(--cyan-line); border-radius: 4px; color: var(--cyan); background: var(--cyan-soft); white-space: nowrap; }
.mc-tel-page small { color: var(--text-mid); text-transform: none; letter-spacing: .04em; font-weight: 500; }
/* Live-signal meter. This was a 1px rail with three glow blobs sliding left to
   right, and that is precisely the shape of an indeterminate progress bar --
   people read it as the page still loading and waited for it to finish. An
   equaliser has no start and no end: the bars rise and fall in place, which
   says "a signal is arriving" without ever implying a journey from 0% to 100%.
   scaleY is composited, so fifteen bars animating continuously cost nothing per
   frame; animating their height would have laid the row out again each time. */
/* V20.14.92 -- the same cyan equaliser, with more life in it:
   - it now radiates from a beating core in the middle: bars the same distance
     from the centre move together, so the wave rolls OUT from the core on both
     sides (a pulse, which is the product's name) instead of scrolling one way;
   - every 3.6 s a heartbeat flash runs outwards along the bars from the core;
   - a faint baseline breathes under the bars;
   - it quickens under the pointer and while the report is fetching data, so the
     meter now says something: faster = work in progress.
   Still transform/opacity for the continuous motion (composited); the flash
   and the core's ring are brief and cover a few pixels. */
/* V20.14.111 -- see SIGNAL_MARK in pulse-mission.js. The 22-bar equaliser that
   used to sit here was ~180px of bouncing columns: the widest thing in the bar,
   for something that only ever meant "the page is awake". The trace is the
   portal's own signal, drawn on and cleared inside a pair of reticle brackets,
   in a little over half the width. It still quickens under the pointer and
   while the report is fetching, so the mark says something. */
.mc-tel-stream { position: relative; flex: 1 1 auto; min-width: 40px; display: flex; align-items: center; justify-content: center; height: 20px; }
.mc-tel-sig { width: 100px; height: 20px; flex: none; overflow: visible; }
.mc-sig-rail { fill: none; stroke: rgba(0, 229, 255, .20); stroke-width: 1; }
.mc-sig-bracket { fill: none; stroke: rgba(0, 229, 255, .55); stroke-width: 1.2; stroke-linecap: round; }
.mc-sig-trace {
  fill: none; stroke: var(--cyan, #00e5ff); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 128; stroke-dashoffset: 128;
  filter: drop-shadow(0 0 3px rgba(0, 229, 255, .7));
  animation: mcSigDraw 3.4s ease-in-out infinite;
}
.mc-sig-scan { fill: #c8faff; filter: drop-shadow(0 0 5px #00e5ff); animation: mcSigScan 3.4s ease-in-out infinite; }
@keyframes mcSigDraw { 0% { stroke-dashoffset: 128; opacity: .22; } 30%, 64% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: -128; opacity: .22; } }
@keyframes mcSigScan { 0% { transform: translateX(6px); opacity: 0; } 12% { opacity: .9; } 86% { opacity: .9; } 100% { transform: translateX(90px); opacity: 0; } }
/* Faster under the pointer, faster again while the report is fetching data. */
.mc-tel-stream:hover .mc-sig-trace, .mc-tel-stream:hover .mc-sig-scan { animation-duration: 1.7s; }
html.pulse-busy .mc-sig-trace, html.pulse-busy .mc-sig-scan { animation-duration: 1.1s; }
/* Stops where every other animation stops, resting at drawn rather than blank. */
:root.pulse-motion-off .mc-sig-trace, :root.pulse-motion-off .mc-sig-scan { animation: none !important; }
:root.pulse-motion-off .mc-sig-trace { stroke-dashoffset: 0; opacity: 1; }
:root.pulse-motion-off .mc-sig-scan { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .mc-sig-trace, .mc-sig-scan { animation: none !important; }
  .mc-sig-trace { stroke-dashoffset: 0; opacity: 1; }
  .mc-sig-scan { opacity: 0; }
}
.mc-tel-item { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.mc-tel-item .hud-icon { color: var(--cyan); opacity: .9; }
.mc-tel-item b { color: var(--text-hi); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: .06em; }
.mc-tel-item b.ok { color: var(--green); } .mc-tel-item b.warn { color: var(--gold); } .mc-tel-item b.bad { color: var(--red); }
.mc-tel-live b { color: var(--green); }
.mc-led { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: var(--glow-green); animation: mcLed 2.2s ease-in-out infinite; }
@keyframes mcLed { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (max-width: 1100px) { .mc-tel-page small { display: none; } }
@media (max-width: 760px) { .mc-tel-stream, .mc-tel-page, .mc-tel-item:not(.mc-tel-live):not([title="Riyadh time"]) { display: none; } .mc-telemetry { padding: 0 10px; gap: 8px; } .mc-tel-brand { letter-spacing: .1em; } .mc-tel-right { gap: 10px; } }

/* ---------- 4. HUD glass panels ---------- */
.mc-hud, .panel, .kpi-card, .v46-brief, .v46-trustbar, .filterbar, .login-card, .launch-map, .section-tab, .section-workspace, .route-report-node,
.qa-drawer, .global-panel, .system-map-panel, .health-banner, .chart-box, .settings-form, .modal-box, .v21-modal, .v38-drawer, .pulse-notice-panel, .profile-dropdown {
  background: var(--mc-glass) !important;
  border: 1px solid var(--line) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04), 0 12px 32px rgba(0, 0, 0, .35) !important;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
:root[data-theme="light"] .mc-hud, :root[data-theme="light"] .panel, :root[data-theme="light"] .kpi-card, :root[data-theme="light"] .v46-brief, :root[data-theme="light"] .v46-trustbar, :root[data-theme="light"] .filterbar, :root[data-theme="light"] .login-card, :root[data-theme="light"] .launch-map, :root[data-theme="light"] .section-tab, :root[data-theme="light"] .section-workspace, :root[data-theme="light"] .route-report-node, :root[data-theme="light"] .qa-drawer, :root[data-theme="light"] .global-panel, :root[data-theme="light"] .system-map-panel, :root[data-theme="light"] .health-banner, :root[data-theme="light"] .chart-box, :root[data-theme="light"] .settings-form, :root[data-theme="light"] .modal-box, :root[data-theme="light"] .v21-modal, :root[data-theme="light"] .v38-drawer, :root[data-theme="light"] .pulse-notice-panel, :root[data-theme="light"] .profile-dropdown {
  box-shadow: inset 0 1px 0 #ffffff, 0 12px 32px rgba(20, 50, 90, .10) !important;
}
/* Corner brackets drawn as backgrounds so no pseudo-element is consumed. */
.mc-hud, .panel, .kpi-card, .v46-brief, .launch-map, .login-card, .section-workspace, .global-panel, .system-map-panel {
  background-image:
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    var(--mc-glass) !important;
  background-repeat: no-repeat !important;
  background-size: 14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px, 100% 100% !important;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%, 0 0 !important;
  border-radius: 6px !important;
}
.panel:hover, .kpi-card:hover, .section-tab:hover, .route-report-node:hover { border-color: var(--cyan-line) !important; box-shadow: inset 0 1px 0 rgba(255,255,255,.05), var(--glow-cyan), 0 16px 40px rgba(0,0,0,.4) !important; }
.panel::after, .kpi-card::after { background: radial-gradient(180px circle at var(--mx) var(--my), rgba(0, 229, 255, .10), transparent 70%) !important; }

/* ---------- 5. Command deck (dashboard header) ---------- */
/* V20.14.193 -- the sticky offset is 0 in all four files that set it. The deck
   sticks inside #mainShell, whose box already begins below the fixed portal
   bar, so any offset here is clearance for something already cleared and
   pushes the deck down onto the content behind it.
   V20.14.200 -- true of #mainShell's own bar, and not of the telemetry strip,
   which is `position: fixed; top: 0; z-index: 1500` and therefore outside
   #mainShell entirely. A sticky element pins relative to the VIEWPORT, so the
   body padding that clears the strip at rest does nothing once the deck is
   stuck -- which is where the reasoning above went wrong. Measured: the strip
   held 0..52 while the stuck deck held 0..160, and the basis and comparison
   toggles lived inside that overlap, present, covered and unclickable. */
.pulse-sticky-header {
  top: var(--mc-bar-h, 0px) !important;
  background: linear-gradient(180deg, rgba(5, 10, 22, .96), rgba(6, 12, 26, .9)) !important;
  border-bottom: 1px solid var(--line-strong);
  box-shadow: 0 12px 40px -18px rgba(0, 229, 255, .35), 0 10px 30px rgba(0, 0, 0, .45) !important;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
:root[data-theme="light"] .pulse-sticky-header { background: linear-gradient(180deg, rgba(255,255,255,.96), rgba(244,248,253,.92)) !important; box-shadow: 0 10px 30px rgba(20,50,90,.10) !important; }
.pulse-sticky-header::before { display: none !important; }
.pulse-sticky-header::after { background: linear-gradient(90deg, transparent, var(--cyan) 30%, var(--purple) 70%, transparent) !important; box-shadow: 0 0 16px rgba(0, 229, 255, .45) !important; height: 1px !important; }
.header-scan { display: none; }
.brandmark h1 { background: linear-gradient(90deg, var(--text-hi) 20%, var(--cyan) 70%, var(--purple)) !important; -webkit-background-clip: text !important; background-clip: text !important; text-shadow: none; letter-spacing: .16em !important; }
.pulse-badge::before { background: conic-gradient(from 0deg, var(--cyan), var(--purple), var(--cyan)) !important; opacity: .45 !important; filter: blur(8px) !important; }
.pulse-logo-caption { color: var(--cyan) !important; text-shadow: var(--glow-cyan); }
.segmented-control { background: rgba(4, 10, 22, .7) !important; border: 1px solid var(--line-strong) !important; box-shadow: inset 0 0 0 1px rgba(0,229,255,.05); border-radius: 8px !important; }
:root[data-theme="light"] .segmented-control { background: #ffffff !important; }
.segmented-option { border-radius: 6px !important; font-family: var(--font-mono) !important; letter-spacing: .1em; }
.segmented-option.active { background: var(--cyan) !important; color: var(--btn-primary-text) !important; box-shadow: var(--glow-cyan-strong) !important; }
.topbar-controls { border: 0 !important; background: transparent !important; box-shadow: none !important; backdrop-filter: none !important; padding: 0 !important; }
.pulse-sticky-header .topbar { background: transparent !important; border: 0 !important; box-shadow: none !important; }
.icon-btn { background: rgba(4, 10, 22, .6) !important; border: 1px solid var(--line-strong) !important; color: var(--text-mid) !important; border-radius: 8px !important; }
:root[data-theme="light"] .icon-btn { background: #ffffff !important; }
.icon-btn:hover, .icon-btn:focus-visible { color: var(--cyan) !important; background: var(--cyan-soft) !important; border-color: var(--cyan) !important; box-shadow: var(--glow-cyan) !important; }
.clock .live { color: var(--green) !important; text-shadow: var(--glow-green); font-family: var(--font-mono); letter-spacing: .12em; }
.live-dot { box-shadow: var(--glow-green) !important; }

/* Asset selector (brand switcher) */
/* Brand rail (V20.14.50)
   The logos carry their own colour, so the chips stay out of the way: no white
   plate, unselected chips sit back (dimmed and desaturated), and only the
   selected one comes forward with its own brand glow. PORTFOLIO reads the same
   way -- it used to be painted purple whether or not it was the current scope,
   which made it look permanently selected. */
.brand-btn.logo-only {
  background: transparent !important; border: 1px solid var(--line) !important; border-radius: 8px !important;
  box-shadow: none !important; opacity: .48; filter: saturate(.45) contrast(.95);
  transition: opacity .22s ease, filter .22s ease, transform .22s cubic-bezier(.2,.8,.2,1), border-color .22s ease, box-shadow .22s ease;
}
.brand-btn.logo-only .brand-logo { filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .5)); }
:root[data-theme="light"] .brand-btn.logo-only .brand-logo { filter: drop-shadow(0 1px 1px rgba(10, 30, 60, .5)) drop-shadow(0 0 3px rgba(10, 30, 60, .25)); }
.brand-btn.logo-only:hover { opacity: .85; filter: none; transform: translateY(-2px); border-color: var(--cyan-line) !important; }
.brand-btn.logo-only.active {
  opacity: 1; filter: none;
  border-color: var(--brand-accent, var(--cyan)) !important;
  background: radial-gradient(120% 140% at 50% 120%, rgba(var(--brand-glow, 0, 229, 255), .16), transparent 70%) !important;
  box-shadow: 0 0 0 1px var(--brand-accent, var(--cyan)), 0 0 22px rgba(var(--brand-glow, 0, 229, 255), .40), 0 8px 20px rgba(0, 0, 0, .3) !important;
}
.brand-btn.logo-only.active::after { display: none !important; }
.brand-btn.portfolio-btn {
  background: transparent !important; border: 1px solid var(--line) !important; color: var(--text-mid) !important;
  border-radius: 8px !important; box-shadow: none !important; opacity: .62;
  transition: opacity .22s ease, color .22s ease, border-color .22s ease, box-shadow .22s ease, background .22s ease;
}
.brand-btn.portfolio-btn .portfolio-icon { color: var(--text-dim) !important; transition: color .22s ease; }
.brand-btn.portfolio-btn:hover { opacity: .9; border-color: var(--purple) !important; color: var(--text-hi) !important; }
.brand-btn.portfolio-btn.active {
  opacity: 1; color: var(--purple) !important; border-color: var(--purple) !important;
  background: radial-gradient(120% 140% at 50% 120%, rgba(157, 139, 255, .18), transparent 70%) !important;
  box-shadow: 0 0 0 1px var(--purple), 0 0 22px rgba(157, 139, 255, .45) !important;
}
.brand-btn.portfolio-btn.active .portfolio-icon { color: var(--purple) !important; }
.brand-btn .tag { color: var(--text-dim) !important; }

/* Filter deck */
.filterbar { border-radius: 8px !important; backdrop-filter: none !important; gap: 8px !important; }
.filterbar .v20-control, .filter-reset { padding: 6px 9px !important; letter-spacing: .04em !important; }
#v20SavedViews { max-width: 128px; }
/* Two-row filter deck: selects on row one; scope chips + view actions + reset on row two. */
.filterbar .flabel, .filterbar .mc-select, .filterbar select.fselect { order: 1; }
.filterbar #v20Scope { order: 4; width: auto !important; flex: 1 1 auto; margin-top: 4px !important; padding-top: 0 !important; border-top: 0 !important; min-width: 0; }
.filterbar .v20-control { order: 5; margin-top: 4px; }
.filterbar .filter-reset { order: 6; margin-top: 4px; margin-left: 8px !important; }
.filterbar .filter-pill { order: 7; }
.filterbar::after { content: ""; order: 3; flex-basis: 100%; height: 0; }
.filterbar .flabel { display: inline-flex !important; align-items: center; gap: 6px; color: var(--cyan) !important; }
.mc-select { position: relative; display: inline-flex; align-items: center; }
.mc-select .mc-select-icon { position: absolute; left: 9px; color: var(--cyan); pointer-events: none; opacity: .9; }
.mc-select select.fselect { padding-left: 26px !important; padding-right: 22px !important; background-position: right 7px center !important; }
select.fselect { background-color: var(--bg-input) !important; border: 1px solid var(--line-strong) !important; border-radius: 6px !important; color: var(--text-hi) !important; font-family: var(--font-mono) !important; font-size: var(--fs-xs) !important; letter-spacing: .02em; }
select.fselect:hover, select.fselect:focus { border-color: var(--cyan) !important; box-shadow: var(--glow-cyan) !important; }
select.fselect.is-active { border-color: var(--cyan) !important; box-shadow: 0 0 0 1px var(--cyan), var(--glow-cyan) !important; }
/* V20.14.157 -- `:not(.v20-icon)`. A LABELLED control needs a plate: the box is
   what tells you the words are a button. An icon-only control does not -- the
   glyph is the affordance, and a box around each one turns a row of tools into
   a row of cells. Reported as "remove boxes around upper right corner icons,
   make them bigger". The icon cluster's appearance is stated once, further
   down this file, and this rule now stays out of its way rather than being
   out-weighted by it. */
.filterbar .v20-control:not(.v20-icon), .filter-reset { background: rgba(4, 10, 22, .6) !important; border: 1px solid var(--line-strong) !important; color: var(--text-mid) !important; border-radius: 6px !important; }
:root[data-theme="light"] .filterbar .v20-control:not(.v20-icon), :root[data-theme="light"] .filter-reset { background: #ffffff !important; }
.filterbar .v20-save:hover, .filter-reset:hover { color: var(--cyan) !important; border-color: var(--cyan) !important; box-shadow: var(--glow-cyan) !important; }
.filter-reset:hover { color: var(--red) !important; border-color: var(--red) !important; box-shadow: var(--glow-red) !important; }
.v20-chip { box-shadow: var(--glow-cyan); }
.v46-trustbar { border-radius: 6px !important; }
.v46-freshness-pill.ok { box-shadow: var(--glow-green); } .v46-freshness-pill.stale { box-shadow: var(--glow-gold); } .v46-freshness-pill.failed { box-shadow: var(--glow-red); }
.v38-context-action { background: rgba(4,10,22,.6) !important; border-color: var(--line-strong) !important; border-radius: 6px !important; }
:root[data-theme="light"] .v38-context-action { background: #fff !important; }

/* ---------- 6. Tab rail with icons ---------- */
.tabnav { display: flex; gap: 6px !important; padding: 6px !important; margin-bottom: 18px !important; border: 1px solid var(--line) !important; border-radius: 8px; background: var(--mc-glass); overflow-x: auto; }
#tabNav .tab-btn {
  display: inline-flex !important; align-items: center; gap: 8px; padding: 9px 14px !important; border: 1px solid transparent !important; border-radius: 6px !important;
  font: 600 var(--fs-xs) var(--font-mono) !important; letter-spacing: .12em; color: var(--text-mid) !important; transition: all var(--dur-base) var(--ease-standard);
}
#tabNav .tab-btn .mc-tab-icon { flex: none; opacity: .8; }
#tabNav .tab-btn:hover { color: var(--text-hi) !important; background: var(--bg-hover) !important; border-color: var(--line) !important; }
#tabNav .tab-btn.active { color: var(--cyan) !important; background: var(--cyan-soft) !important; border-color: var(--cyan-line) !important; box-shadow: var(--glow-cyan) !important; /* V20.14.222 -- underline removed; #tabSlider draws the one line now, and can travel and breathe. The glow stays. Section tabs and Control Panel tabs below keep theirs: they have no travelling mark. */ text-shadow: 0 0 10px rgba(0,229,255,.5); }
#tabNav .tab-btn.active .mc-tab-icon { opacity: 1; filter: drop-shadow(0 0 6px rgba(0,229,255,.7)); }
#tabNav .tab-btn.active::after { display: none !important; }

/* ---------- 7. KPI cards ---------- */
.kpi-card .kvalue { text-shadow: 0 0 18px rgba(0, 229, 255, .18); }
.kpi-card.tone-pos .kvalue { text-shadow: 0 0 18px rgba(72, 255, 180, .22); }
.kpi-card.tone-neg .kvalue { text-shadow: 0 0 18px rgba(255, 77, 109, .22); }
:root[data-theme="light"] .kpi-card .kvalue { text-shadow: none; }
.kpi-card::before { height: 1px !important; background: linear-gradient(90deg, var(--brand-accent, var(--cyan)), transparent 70%) !important; box-shadow: 0 0 10px var(--brand-accent, var(--cyan)); opacity: .9 !important; }
.kpi-specific-icon { color: var(--cyan) !important; filter: drop-shadow(0 0 6px rgba(0,229,255,.6)); }
.kpi-card .klabel { color: var(--text-dim) !important; }
/* No glow, no box behind the KPI delta -- it is a coloured figure, nothing else (see 17a). */
.kpi-drill:hover, .kpi-info:hover, .kpi-trace:hover { box-shadow: var(--glow-cyan); }

/* ---------- 8. Panels, titles, briefs ---------- */
.panel .ptitle { font-family: var(--font-display) !important; letter-spacing: .02em; }
.pcard-icon, .v23-card-icon { color: var(--cyan) !important; filter: drop-shadow(0 0 6px rgba(0,229,255,.55)); }
.v20-explain, .v46-chart-btn { background: rgba(4,10,22,.7) !important; border-color: var(--line-strong) !important; color: var(--cyan) !important; }
:root[data-theme="light"] .v20-explain, :root[data-theme="light"] .v46-chart-btn { background: #fff !important; }
.v20-explain:hover, .v46-chart-btn:hover { box-shadow: var(--glow-cyan) !important; border-color: var(--cyan) !important; }
.v46-brief-kicker i { box-shadow: 0 0 0 3px var(--cyan-soft), var(--glow-cyan) !important; }
.v46-insight { background: rgba(8, 16, 30, .55) !important; border-color: var(--line) !important; }
:root[data-theme="light"] .v46-insight { background: #f6f9fd !important; }
.v46-insight::before { box-shadow: 0 0 10px currentColor; }
.v46-act { box-shadow: var(--glow-cyan); }
.v21-narrative, .insight, .caveat-note { border-radius: 6px !important; }
.tab-page-head, .v24-workspace-head { border-radius: 6px !important; }

/* ---------- 9. Agent drawer ---------- */
.qa-drawer { border-radius: 0 !important; border-left: 1px solid var(--cyan-line) !important; box-shadow: -20px 0 60px rgba(0, 0, 0, .55), inset 1px 0 0 rgba(0,229,255,.2) !important; }
.qa-fab { border: 1px solid var(--cyan-line) !important; background: var(--cyan-soft) !important; box-shadow: var(--glow-cyan) !important; border-radius: 8px !important; }
.qa-send { background: var(--cyan) !important; color: var(--btn-primary-text) !important; box-shadow: var(--glow-cyan-strong) !important; border-radius: 6px !important; }
.qa-mode-btn.active, .qa-answer-btn.active { background: var(--cyan) !important; color: var(--btn-primary-text) !important; border-color: var(--cyan) !important; box-shadow: var(--glow-cyan) !important; }
.qa-drawer { top: 34px !important; height: calc(100vh - 34px) !important; max-height: calc(100vh - 34px) !important; }
.qa-backdrop { top: 34px !important; }
.qa-brief { border-color: var(--cyan-line) !important; }

/* ---------- 10. Hub ---------- */
.hub-title-row { display: flex !important; align-items: center; justify-content: flex-start; gap: 12px; }
.hub-title-row::before { content: none !important; }
.mc-hub-anim { width: 62px; height: 62px; overflow: visible; }
.mc-hub-anim .ring { transform-box: fill-box; transform-origin: center; animation: mcHubSpin 14s linear infinite; }
.mc-hub-anim .ring2 { transform-box: fill-box; transform-origin: center; animation: mcHubSpin 9s linear infinite reverse; }
.mc-hub-anim rect { transform-box: fill-box; transform-origin: center; opacity: .4; animation: mcHubCell 2.4s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes mcHubSpin { to { transform: rotate(360deg); } }
@keyframes mcHubCell { 0%, 100% { opacity: .4; transform: scale(.88); } 50% { opacity: 1; transform: scale(1.1); filter: drop-shadow(0 0 4px currentColor); } }
@media (prefers-reduced-motion: reduce) { .mc-hub-anim .ring, .mc-hub-anim .ring2, .mc-hub-anim rect { animation: none; opacity: 1; } }
/* The animated hub glyph stands on its own. It used to sit inside a 54px
   tinted, bordered, glowing tile, and that frame competed with the mark it
   was framing -- at a glance you read the box first and the four pulsing
   cells second. Frame removed and the artwork enlarged to fill the space
   the tile used to occupy, so the animation is the thing you see. */
.mc-hub-title-icon { display: grid; place-items: center; width: 62px; height: 62px; border: 0; background: none; box-shadow: none; color: var(--cyan); }
.hub-title-icon { display: none !important; }
.hub-period-chip { display: inline-flex !important; align-items: center; gap: 7px; border: 1px solid var(--cyan-line) !important; background: var(--cyan-soft) !important; color: var(--cyan) !important; border-radius: 6px !important; box-shadow: var(--glow-cyan); font-family: var(--font-mono) !important; letter-spacing: .1em; }
.launch-map { border-radius: 8px !important; }
.launch-map-head span, .route-category-head span { color: var(--cyan) !important; text-shadow: var(--glow-cyan); }
.section-tab { position: relative; border-radius: 6px !important; }
.section-tab .mc-tab-glyph { position: absolute; right: 10px; bottom: 8px; color: var(--text-dim); opacity: .8; }
.section-tab .mc-tab-glyph svg { width: 22px; height: 22px; }
.section-tab.is-active { border-color: var(--cyan) !important; box-shadow: var(--glow-cyan), inset 0 -2px 0 var(--cyan) !important; background: var(--mc-glass-hi) !important; }
.section-tab.is-active .mc-tab-glyph { color: var(--cyan); opacity: 1; filter: drop-shadow(0 0 6px rgba(0,229,255,.7)); }
/* Section tiles: larger brand icons with no white plate (dark: bare artwork; light: navy chip so white-lettered artwork stays legible). */
.section-tab { grid-template-columns: 66px minmax(0, 1fr) !important; min-height: 88px !important; gap: 12px !important; }
.section-tab-icon { width: 66px !important; height: 66px !important; padding: 3px !important; border-radius: 10px; background: transparent !important; border: 0 !important; box-shadow: none !important; filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .45)); }
.application-mark { background: transparent !important; border: 0 !important; box-shadow: none !important; width: 58px !important; height: 58px !important; }
.application-mark img { width: 54px !important; height: 54px !important; filter: drop-shadow(0 5px 10px rgba(0, 0, 0, .45)); }
:root[data-theme="light"] .application-mark img { filter: drop-shadow(0 1px 1px rgba(10, 30, 60, .55)) drop-shadow(0 0 3px rgba(10, 30, 60, .28)); }
.section-tab.is-planned { opacity: .88; filter: saturate(.85); }
.section-tab.is-live-tab.is-active .section-tab-icon { filter: drop-shadow(0 0 10px rgba(52, 211, 153, .45)); }
/* Light: no plate either -- a thin dark halo keeps white lettering in the artwork readable on the white card. */
:root[data-theme="light"] .section-tab-icon, :root[data-theme="light"] .route-category-head img, :root[data-theme="light"] .application-mark, :root[data-theme="light"] .application-mark img { background: transparent !important; border: 0 !important; box-shadow: none !important; filter: drop-shadow(0 1px 1px rgba(10, 30, 60, .55)) drop-shadow(0 0 3px rgba(10, 30, 60, .28)); }
/* Light mode: section tiles read as crisp white cards, not muted grey glass. */
:root[data-theme="light"] .section-tab { color: #153454; background: linear-gradient(150deg, #ffffff, #eef7fd) !important; border: 1px solid rgba(7, 143, 197, .34) !important; box-shadow: 0 8px 20px rgba(20, 50, 90, .09), inset 0 1px #ffffff !important; opacity: 1; filter: none; }
:root[data-theme="light"] .section-tab b { color: #10294a; }
:root[data-theme="light"] .section-tab small { color: #4a6485; }
:root[data-theme="light"] .section-tab .mc-tab-glyph { color: #2b7fb3; opacity: .85; }
:root[data-theme="light"] .section-tab.is-planned em { color: #7a4d00; border-color: rgba(255, 170, 0, .5); background: rgba(255, 201, 60, .16); }
:root[data-theme="light"] .section-tab:hover { border-color: rgba(7, 143, 197, .7) !important; box-shadow: 0 10px 26px rgba(7, 143, 197, .18), inset 0 1px #ffffff !important; }
:root[data-theme="light"] .section-tab.is-active { background: linear-gradient(125deg, #dff6fc, #ffffff) !important; border-color: #078fc5 !important; box-shadow: 0 0 0 1px rgba(7, 143, 197, .18), 0 10px 26px rgba(7, 143, 197, .2), inset 0 -2px 0 #078fc5 !important; }
:root[data-theme="light"] .section-tab.is-live-tab.is-active { background: linear-gradient(125deg, #dcfbef, #ffffff) !important; border-color: #17a06a !important; box-shadow: 0 0 0 1px rgba(23, 160, 106, .18), 0 10px 26px rgba(23, 160, 106, .18), inset 0 -2px 0 #27c982 !important; }
:root[data-theme="light"] .section-tab.is-live-tab.is-active .section-tab-icon { filter: drop-shadow(0 1px 1px rgba(10, 30, 60, .55)) drop-shadow(0 0 8px rgba(39, 201, 130, .5)); }
/* Light: section tiles and application cards carry a slowly travelling light along their border. */
@property --mc-ang { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
:root[data-theme="light"] .section-tab, :root[data-theme="light"] .route-report-node { position: relative; --mc-b1: #078fc5; --mc-b2: #8fe6ff; }
:root[data-theme="light"] .section-tab.is-live-tab.is-active, :root[data-theme="light"] .section-workspace.is-available .route-report-node { --mc-b1: #17a06a; --mc-b2: #9df5cf; }
:root[data-theme="light"] .section-tab::after, :root[data-theme="light"] .route-report-node::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1.5px; pointer-events: none; z-index: 3;
  background: conic-gradient(from var(--mc-ang), transparent 0deg, transparent 235deg, var(--mc-b1) 292deg, var(--mc-b2) 322deg, transparent 350deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
  animation: mcBorderSpin 7s linear infinite;
}
:root[data-theme="light"] .section-tab:nth-child(2)::after { animation-delay: -1.4s; } :root[data-theme="light"] .section-tab:nth-child(3)::after { animation-delay: -2.8s; } :root[data-theme="light"] .section-tab:nth-child(4)::after { animation-delay: -4.2s; } :root[data-theme="light"] .section-tab:nth-child(5)::after { animation-delay: -5.6s; }
:root[data-theme="light"] .route-report-node::after { animation-duration: 9s; }
@keyframes mcBorderSpin { to { --mc-ang: 360deg; } }
@media (prefers-reduced-motion: reduce) { :root[data-theme="light"] .section-tab::after, :root[data-theme="light"] .route-report-node::after { animation: none; } }
.section-application.is-flagship { border-color: var(--cyan-line) !important; box-shadow: inset 3px 0 0 var(--cyan), var(--glow-cyan) !important; }
.section-application > i { color: var(--cyan) !important; }
.launch-map-status { border: 1px solid var(--line-strong) !important; border-radius: 6px !important; background: var(--mc-glass-hi) !important; }
.launch-map-status b { color: var(--cyan) !important; text-shadow: var(--glow-cyan); }
.header-icon, .hub-profile-button { border: 1px solid var(--line-strong) !important; background: rgba(4,10,22,.6) !important; border-radius: 8px !important; }
:root[data-theme="light"] .header-icon, :root[data-theme="light"] .hub-profile-button { background: #fff !important; }
.header-icon:hover, .hub-profile-button:hover { border-color: var(--cyan) !important; color: var(--cyan) !important; box-shadow: var(--glow-cyan) !important; }
body.hub .topbar, .hub-topbar { background: transparent; }
/* Theme switch on the hub: light mode gives these surfaces a continuous edge-signal
   animation at higher specificity, which swallowed the switch animation when going
   dark -> light. Re-assert both float animations here (this layer loads last), so the
   directory box, the five section tiles and the selected-section box rise into place
   in BOTH directions. Keyframes live with the page that uses them (hub.html). */
:root[data-theme="light"] .theme-switching .launch-map, :root[data-theme="light"] .theme-switching .pulse-command-node, :root[data-theme="light"] .theme-switching .route-category, :root[data-theme="light"] .theme-switching .route-report-node { animation: themeBoxSwitch .55s cubic-bezier(.2, .8, .2, 1) both; }
:root[data-theme="light"] .theme-switching .pulse-command-node { animation-delay: .035s; }
:root[data-theme="light"] .theme-switching .route-category:nth-child(1) { animation-delay: .07s; }
:root[data-theme="light"] .theme-switching .route-category:nth-child(2) { animation-delay: .105s; }
:root[data-theme="light"] .theme-switching .route-report-node { animation-delay: .14s; }
:root[data-theme="light"] .theme-switching .section-tab, :root[data-theme="light"] .theme-switching .section-workspace { animation: themeTileFloat .48s cubic-bezier(.2, .8, .2, 1) both; }
:root[data-theme="light"] .theme-switching .section-tab:nth-child(2) { animation-delay: .06s; }
:root[data-theme="light"] .theme-switching .section-tab:nth-child(3) { animation-delay: .12s; }
:root[data-theme="light"] .theme-switching .section-tab:nth-child(4) { animation-delay: .18s; }
:root[data-theme="light"] .theme-switching .section-tab:nth-child(5) { animation-delay: .24s; }
:root[data-theme="light"] .theme-switching .section-workspace { animation-delay: .2s; }
@media (prefers-reduced-motion: reduce) { :root[data-theme="light"] .theme-switching .launch-map, :root[data-theme="light"] .theme-switching .pulse-command-node, :root[data-theme="light"] .theme-switching .route-category, :root[data-theme="light"] .theme-switching .route-report-node, :root[data-theme="light"] .theme-switching .section-tab, :root[data-theme="light"] .theme-switching .section-workspace { animation: none; } }
/* Light: the page headers are clean white-to-ice, not the warm/cool blended glass (which read as grey). Applies to hub, Pulse and Control Panel headers alike. */
:root[data-theme="light"] body > .topbar, :root[data-theme="light"] .pulse-sticky-header, :root[data-theme="light"] .cp-sticky-shell {
  background: linear-gradient(180deg, #ffffff 0%, #f6fbff 100%) !important;
  border-bottom: 1px solid rgba(7, 143, 197, .30) !important;
  box-shadow: 0 10px 28px rgba(20, 50, 90, .07) !important;
  animation: none !important;
  backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
}
:root[data-theme="light"] body > .topbar::before, :root[data-theme="light"] .pulse-sticky-header::before, :root[data-theme="light"] .cp-sticky-shell::before { opacity: 0 !important; }
:root[data-theme="light"] body > .topbar { position: relative; }
:root[data-theme="light"] body > .topbar::after, :root[data-theme="light"] .pulse-sticky-header::after, :root[data-theme="light"] .cp-sticky-shell::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; pointer-events: none; opacity: 1 !important;
  background: linear-gradient(90deg, transparent 0%, #07b9ea 12%, #38bdf8 40%, #3178df 60%, #07b9ea 88%, transparent 100%) !important;
  box-shadow: 0 0 10px rgba(7, 185, 234, .85), 0 0 26px rgba(7, 185, 234, .45), 0 2px 18px rgba(49, 120, 223, .3) !important;
  animation: mcRailShine 11s ease-in-out infinite;
}
@keyframes mcRailShine { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.35); } }
:root[data-theme="light"] .cp-sticky-shell .topbar { background: transparent !important; }
/* Light: firmer digital frame. The four corner brackets sit OUTSIDE the box edge
   (drawn on a ::before that is inset by -9px), the way the original skin had them. */
:root[data-theme="light"] .launch-map, :root[data-theme="light"] .section-workspace, :root[data-theme="light"] .panel, :root[data-theme="light"] .global-panel, :root[data-theme="light"] .system-map-panel {
  position: relative;
  border: 1.5px solid var(--line-strong) !important;
  overflow: visible !important;   /* the box clips its own decoration; the brackets sit outside it */
  background-image: none !important;
  /* V20.14.353 -- the slate glass, not a white-to-ice gradient */
  background: var(--mc-glass) !important;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .9), 0 14px 34px rgba(20, 50, 90, .10) !important;
}
:root[data-theme="light"] .launch-map::before, :root[data-theme="light"] .section-workspace::before, :root[data-theme="light"] .global-panel::before, :root[data-theme="light"] .system-map-panel::before {
  content: ""; position: absolute; inset: -2.5px; z-index: 0; pointer-events: none; border-radius: 8px; opacity: 1;
  mask-image: none !important; -webkit-mask-image: none !important;   /* the box's own veil mask would clip the corners away */
  /* V20.14.353 -- the brackets are the HUD's (--mc-frame, the slate cyan), not a hard-coded blue */
  background:
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame));
  background-repeat: no-repeat;
  background-size: 30px 2.5px, 2.5px 30px, 30px 2.5px, 2.5px 30px, 30px 2.5px, 2.5px 30px, 30px 2.5px, 2.5px 30px;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%;
  filter: drop-shadow(0 0 4px rgba(0, 126, 168, .30));
}
:root[data-theme="light"] .section-workspace::before { inset: -2.5px; background-size: 24px 2.5px, 2.5px 24px, 24px 2.5px, 2.5px 24px, 24px 2.5px, 2.5px 24px, 24px 2.5px, 2.5px 24px; }

/* ---------- 11. Login gateway ---------- */
.login-card { border-radius: 8px !important; padding: 40px 44px !important; }
.login-card::before { background: linear-gradient(90deg, transparent, var(--cyan), var(--purple), transparent) !important; }
.login-eyebrow { color: var(--gold) !important; text-shadow: var(--glow-gold); }
.login-headline .accent { color: var(--cyan) !important; text-shadow: 0 0 24px rgba(0,229,255,.45); }
.login-signal-strip { border-radius: 6px !important; }
.login-signal b { color: var(--cyan) !important; }
.login-btn { border-radius: 6px !important; }
.mc-gateway { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 0 0 16px; }
.mc-gateway span { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px; background: rgba(4, 10, 22, .5); font: 600 var(--fs-2xs) var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); text-align: left; }
:root[data-theme="light"] .mc-gateway span { background: #f6f9fd; }
.mc-gateway span .hud-icon { width: 14px; height: 14px; color: var(--cyan); flex: none; filter: drop-shadow(0 0 5px rgba(0,229,255,.5)); }
.mc-gateway span b { margin-left: auto; color: var(--green); text-shadow: var(--glow-green); }
.ksa-caption b, .ksa-legend { font-family: var(--font-mono); }
.hud-corner { opacity: .9 !important; box-shadow: none; }
body > .theme-toggle { top: 46px !important; }

/* ---------- 12. Control Panel ---------- */
.cp-sticky-shell { top: 34px !important; }
.cp-sticky-shell .topbar { background: linear-gradient(180deg, rgba(5,10,22,.96), rgba(6,12,26,.9)) !important; border-bottom: 1px solid var(--line-strong) !important; backdrop-filter: blur(12px); }
:root[data-theme="light"] .cp-sticky-shell .topbar { background: linear-gradient(180deg, rgba(255,255,255,.96), rgba(244,248,253,.92)) !important; }
.cp-sticky-shell .tabnav { border-radius: 0 !important; margin-bottom: 0 !important; border-left: 0 !important; border-right: 0 !important; }
.mc-cp-tab { display: inline-flex !important; align-items: center; gap: 8px; border: 1px solid transparent !important; border-radius: 6px !important; font-family: var(--font-mono) !important; letter-spacing: .1em; }
.mc-cp-tab.active, .cp-sticky-shell .tabnav button.active { color: var(--cyan) !important; background: var(--cyan-soft) !important; border-color: var(--cyan-line) !important; box-shadow: var(--glow-cyan), inset 0 -2px 0 var(--cyan) !important; }
.mc-cp-tab .mc-tab-icon { width: 15px; height: 15px; }
.health-pill.ok { border-color: var(--green-line) !important; box-shadow: var(--glow-green) !important; }
.health-pill .hp-dot { box-shadow: var(--glow-green); }
.tb-title { background: linear-gradient(90deg, var(--text-hi) 20%, var(--cyan) 80%) !important; -webkit-background-clip: text !important; background-clip: text !important; -webkit-text-fill-color: transparent; letter-spacing: .14em !important; }
.status-chip, .pill { border-radius: 4px !important; font-family: var(--font-mono) !important; }
.system-node { border-radius: 6px !important; border: 1px solid var(--line) !important; background: var(--mc-glass-hi) !important; }
.system-node-state.online, .system-node .online { text-shadow: var(--glow-green); }
.btn.primary, .pui-btn.primary { box-shadow: var(--glow-cyan-strong) !important; }

/* ---------- 13. Shared controls ---------- */
.pui-btn { border-radius: 6px; font-family: var(--font-mono); letter-spacing: .1em; }
.pui-btn.primary { box-shadow: var(--glow-cyan); }
.pui-status.ok, .pui-status.live, .pui-status.success { box-shadow: var(--glow-green); }
.pui-status.warn, .pui-status.warning, .pui-status.stale { box-shadow: var(--glow-gold); }
.pui-status.error, .pui-status.danger, .pui-status.failed { box-shadow: var(--glow-red); }
.pui-modal-card, .v46-chart-card { border-radius: 8px !important; border: 1px solid var(--cyan-line) !important; box-shadow: var(--shadow-lg), var(--glow-cyan) !important; }
.pui-toast { border-radius: 6px; }
::selection { background: var(--cyan); color: var(--btn-primary-text); }
::-webkit-scrollbar-thumb { background: rgba(0, 229, 255, .25) !important; border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: rgba(0, 229, 255, .45) !important; }
::-webkit-scrollbar-track { background: transparent !important; }

/* ---------- 14. Boot sequence ---------- */
html.mc-booting #tabContent .kpi-card, html.mc-booting #tabContent .panel, html.mc-booting .v46-brief, html.mc-booting .launch-map, html.mc-booting .login-card, html.mc-booting #tabBody > * {
  animation: mcBoot .7s var(--ease-out) both;
}
html.mc-booting #tabContent .kpi-card:nth-child(2) { animation-delay: .06s; } html.mc-booting #tabContent .kpi-card:nth-child(3) { animation-delay: .12s; }
html.mc-booting #tabContent .kpi-card:nth-child(4) { animation-delay: .18s; } html.mc-booting #tabContent .kpi-card:nth-child(5) { animation-delay: .24s; } html.mc-booting #tabContent .kpi-card:nth-child(6) { animation-delay: .3s; }
html.mc-booting .v46-brief { animation-delay: .3s; }
html.mc-booting #tabContent .panel:nth-of-type(1) { animation-delay: .38s; } html.mc-booting #tabContent .panel:nth-of-type(2) { animation-delay: .46s; } html.mc-booting #tabContent .panel:nth-of-type(3) { animation-delay: .54s; }
@keyframes mcBoot { from { opacity: 0; transform: translateY(10px); filter: brightness(1.6) saturate(1.4); } 60% { filter: brightness(1.15); } to { opacity: 1; transform: none; filter: none; } }

/* ---------- 15. Motion discipline ---------- */
@media (prefers-reduced-motion: reduce) {
  .mc-sig-trace, .mc-sig-scan, .mc-led, .pulse-badge::before { animation: none !important; }
  html.mc-booting * { animation: none !important; }
}
@media (max-width: 760px) {
  html.mc-has-telemetry body { padding-top: 32px; }
  /* V20.14.193 -- 0 here too. This is the third file setting the deck's sticky
     offset and the one that bites hardest: at 760px and below the deck is tall
     enough that the offset engages, which is what put 40px of header over the
     first section heading. See pulse-v151-user-revision.css for why the offset
     was clearance the scroll container had already provided. */
  /* V20.14.200 -- the strip is fixed at every width, so the deck clears it
     here too, with the same variable the rest of the portal uses. */
  .pulse-sticky-header { top: var(--mc-bar-h, 0px) !important; }
  .mc-gateway { grid-template-columns: 1fr; }
}
@media (max-width: 480px) { .mc-tel-item[title="Riyadh time"] { display: none; } .mc-tel-brand { font-size: 11px; } }

/* ---------- 11. Pulse guide (light theme) ---------- */
/* Both dashboard CTAs keep the dark theme's gold identity in light mode. */
:root[data-theme="light"] .landing-cta {
  background: linear-gradient(180deg, #ffd75e, #f5b71f) !important;
  color: #23180a !important; border: 1px solid rgba(180, 128, 8, .45) !important;
  box-shadow: 0 6px 18px rgba(214, 158, 20, .28) !important;
}
:root[data-theme="light"] .landing-cta:hover { box-shadow: 0 10px 26px rgba(214, 158, 20, .38) !important; }
/* Term-chip tooltips follow the light surface instead of staying deep navy. */
:root[data-theme="light"] .pui-tooltip {
  background: #ffffff; color: #12314f; border-color: rgba(7, 143, 197, .45);
  box-shadow: 0 12px 26px rgba(20, 50, 90, .16);
}
:root[data-theme="light"] .guide-meta-card, :root[data-theme="light"] .landing-card { background: linear-gradient(150deg, #ffffff, #f3f9fe) !important; border-color: rgba(7, 143, 197, .28) !important; }
:root[data-theme="light"] .landing-card:hover, :root[data-theme="light"] .guide-meta-card:hover { border-color: rgba(7, 143, 197, .6) !important; box-shadow: 0 12px 26px rgba(20, 50, 90, .12), 0 0 18px rgba(7, 143, 197, .12) !important; }

/* ---------- 12. Header chrome states (V20.14.50) ---------- */
/* Exceptions inbox: quiet when clear, red and pulsing when it holds items. */
.icon-btn.has-exceptions, #v38ExceptionsBtn.has-exceptions, .header-icon.has-exceptions {
  color: #ff6b6b !important; border-color: rgba(255, 107, 107, .65) !important;
  background: rgba(255, 107, 107, .12) !important;
  animation: mcAlertPulse 2.4s ease-in-out infinite;
}
@keyframes mcAlertPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, .0), 0 0 10px rgba(255, 107, 107, .25); }
  50% { box-shadow: 0 0 0 4px rgba(255, 107, 107, .10), 0 0 20px rgba(255, 107, 107, .55); }
}
@media (prefers-reduced-motion: reduce) { .icon-btn.has-exceptions, #v38ExceptionsBtn.has-exceptions, .header-icon.has-exceptions { animation: none; } }
/* Suggestion (lightbulb): same family as its neighbours, with a slow glow so it
   invites a click instead of looking like a stray colour. */
.v21-suggest-btn, #v21SuggestBtn, .icon-btn.suggest-btn { position: relative; color: var(--text-mid) !important; }
.v21-suggest-btn svg, #v21SuggestBtn svg, .icon-btn.suggest-btn svg { transition: transform .25s cubic-bezier(.2,.8,.2,1), filter .25s ease; }
.v21-suggest-btn:hover, #v21SuggestBtn:hover, .icon-btn.suggest-btn:hover { color: var(--gold) !important; border-color: rgba(255, 201, 60, .6) !important; }
.v21-suggest-btn:hover svg, #v21SuggestBtn:hover svg, .icon-btn.suggest-btn:hover svg { transform: translateY(-1px) scale(1.08); filter: drop-shadow(0 0 8px rgba(255, 201, 60, .7)); }
.v21-suggest-btn::after, #v21SuggestBtn::after, .icon-btn.suggest-btn::after {
  content: ""; position: absolute; inset: -2px; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 12px rgba(255, 201, 60, .0); animation: mcSuggestGlow 4.2s ease-in-out infinite;
}
@keyframes mcSuggestGlow { 0%, 100% { box-shadow: 0 0 0 rgba(255, 201, 60, 0); } 50% { box-shadow: 0 0 14px rgba(255, 201, 60, .35); } }
@media (prefers-reduced-motion: reduce) { .v21-suggest-btn::after, #v21SuggestBtn::after, .icon-btn.suggest-btn::after { animation: none; } }
/* WHAT-IF: a travelling light around the button rather than a flat halo. */
.v21-scenario-pulse, .v21-scenario-btn, #v21ScenarioBtn { position: relative; overflow: hidden; animation: none !important; }
.v21-scenario-pulse::after, .v21-scenario-btn::after, #v21ScenarioBtn::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1.4px; pointer-events: none;
  background: conic-gradient(from var(--mc-ang, 0deg), transparent 0deg, transparent 250deg, rgba(255, 201, 60, .75) 310deg, #fff2c8 336deg, transparent 356deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
  animation: mcBorderSpin 5.2s linear infinite;
}
.v21-scenario-pulse:hover, .v21-scenario-btn:hover, #v21ScenarioBtn:hover { color: var(--gold) !important; box-shadow: 0 0 18px rgba(255, 201, 60, .35) !important; }
.v21-scenario-pulse:hover::after, .v21-scenario-btn:hover::after, #v21ScenarioBtn:hover::after { animation-duration: 1.6s; }
@media (prefers-reduced-motion: reduce) { .v21-scenario-pulse::after, .v21-scenario-btn::after, #v21ScenarioBtn::after { animation: none; } }

/* ---------- 13. Agent, brief, KPI deltas (V20.14.50) ---------- */
/* PULSE AGENT sits in the brand rail; at 34 px it read as another small icon.
   Larger, with a slow orbit ring and a breathing core, so it invites a click. */
.qa-fab {
  width: 52px !important; min-width: 52px !important; height: 52px !important; padding: 0 !important;
  position: relative; overflow: visible !important;
  border: 1px solid var(--cyan-line) !important; border-radius: 10px !important;
  background: radial-gradient(120% 130% at 50% 120%, rgba(0, 229, 255, .22), var(--cyan-soft) 70%) !important;
  box-shadow: 0 0 0 1px rgba(0, 229, 255, .18), 0 0 20px rgba(0, 229, 255, .28) !important;
  transition: transform .22s cubic-bezier(.2,.8,.2,1), box-shadow .22s ease, border-color .22s ease;
}
.qa-fab::after {
  content: ""; position: absolute; inset: -5px; border-radius: 13px; pointer-events: none;
  border: 1px dashed rgba(0, 229, 255, .45); animation: mcAgentOrbit 9s linear infinite;
}
.qa-fab .qa-fab-orb, .qa-fab svg { width: 34px !important; height: 34px !important; }
.qa-fab:hover { transform: translateY(-2px) scale(1.04); border-color: var(--cyan) !important; box-shadow: 0 0 0 1px var(--cyan), 0 0 30px rgba(0, 229, 255, .55) !important; }
.qa-fab:hover::after { animation-duration: 3.4s; border-color: rgba(0, 229, 255, .8); }
.qa-fab:active { transform: translateY(0) scale(.97); }
@keyframes mcAgentOrbit { to { transform: rotate(360deg); } }
@keyframes mcAgentBreathe { 0%, 100% { transform: scale(1); filter: drop-shadow(0 0 4px rgba(0, 229, 255, .35)); } 50% { transform: scale(1.07); filter: drop-shadow(0 0 10px rgba(0, 229, 255, .75)); } }
@media (prefers-reduced-motion: reduce) { .qa-fab::after, .qa-fab .qa-fab-orb, .qa-fab svg { animation: none !important; } }

/* The brief carries the one paragraph that explains the whole screen, and it was
   losing the competition with everything around it. Give it its own frame. */
.v46-brief {
  border: 1px solid var(--cyan-line) !important;
  background: linear-gradient(140deg, rgba(0, 229, 255, .07), var(--mc-glass) 45%) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), 0 0 0 1px rgba(0, 229, 255, .10), 0 14px 34px rgba(0, 0, 0, .32) !important;
  position: relative; overflow: hidden;
}
.v46-brief::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--cyan), rgba(157, 139, 255, .8) 60%, transparent);
  box-shadow: 0 0 14px rgba(0, 229, 255, .55);
}
.v46-brief .v46-brief-head { padding-left: 18px !important; }
:root[data-theme="light"] .v46-brief { background: linear-gradient(140deg, #eaf8ff, #ffffff 55%) !important; border-color: rgba(7, 143, 197, .45) !important; box-shadow: 0 0 0 1px rgba(7, 143, 197, .10), 0 12px 28px rgba(20, 50, 90, .12) !important; }

/* KPI delta (V20.14.51): a directional figure with a magnitude track under it.
   The pill shape read as a label; this reads as a measurement -- the arrow says
   direction, the number says how much, and the bar gives it a size at a glance
   (|percent| against a 50% ceiling, so a 3% move and a 40% move look different). */
.kpi-foot .kdelta {
  display: inline-grid; grid-template-columns: auto auto; grid-auto-rows: auto; gap: 0 7px;
  align-items: center; padding: 0; border: 0; background: none; border-radius: 0;
  font-variant-numeric: tabular-nums;
}
.kpi-foot .kdelta i { grid-row: 1; font-style: normal; font-size: 11px; line-height: 1; opacity: .95; }
.kpi-foot .kdelta b { grid-row: 1; font: 700 var(--fs-xl) var(--font-display); letter-spacing: -.01em; line-height: 1.05; }
.kpi-foot .kdelta .kdelta-track { grid-row: 2; grid-column: 1 / -1; margin-top: 5px; height: 3px; width: 100%; min-width: 74px; border-radius: 3px; background: var(--line); overflow: hidden; }
.kpi-foot .kdelta .kdelta-track i { display: block; height: 100%; border-radius: 3px; background: currentColor; box-shadow: 0 0 8px currentColor; font-size: 0; }
.kpi-card.tone-pos .kdelta { color: var(--green); }
.kpi-card.tone-neg .kdelta { color: #ff7a7a; }
.kpi-card.tone-neutral .kdelta { color: var(--text-dim); }
.kpi-card.tone-neutral .kdelta .kdelta-track { display: none; }

/* Two-point comparison mark (used where no monthly series exists yet). */
.kspark.kcompare .kcompare-base { stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 3; }
.kspark.kcompare .kcompare-line { stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.kspark.kcompare .kcompare-dot { fill: var(--bg-panel); stroke: currentColor; stroke-width: 1.6; }
.kspark.kcompare .kcompare-dot.to { fill: currentColor; }
.kspark.kcompare.pos { color: var(--green); }
.kspark.kcompare.neg { color: #ff7a7a; }

/* ---------- 14. Header icon rail (V20.14.51) ---------- */
/* Every control in the rail shares one box so nothing sits a pixel proud of its
   neighbours (the profile button and WHAT-IF each used to). */
#headerIconGroup { display: flex; align-items: center; gap: 8px; }
#headerIconGroup > * { align-self: center; }
#headerIconGroup .icon-btn, #headerIconGroup .v21-icon-btn, #headerIconGroup .profile-menu > .icon-btn {
  width: 34px !important; height: 34px !important; min-height: 34px; padding: 0 !important;
  display: inline-flex !important; align-items: center; justify-content: center; box-sizing: border-box;
}
#headerIconGroup .v21-btn:not(.v21-icon-btn) { height: 34px !important; min-height: 34px; display: inline-flex !important; align-items: center; box-sizing: border-box; }
#headerIconGroup .profile-menu { display: inline-flex; align-items: center; }
#headerIconGroup .icon-btn svg, #headerIconGroup .v21-icon-btn svg { width: 17px; height: 17px; }
#headerIconGroup .profile-avatar { width: 100%; height: 100%; }

/* ---------- 15. AI orb (V20.14.51) ---------- */
/* The agent reads as an assistant, not a radar: a soft core inside three
   gradient rings that drift at different speeds. */
.ai-orb { display: grid; place-items: center; }
.ai-orb svg { overflow: visible; }
.ai-orb-ring { transform-box: fill-box; transform-origin: center; }
.ai-orb-ring.a { animation: aiOrbSpinA 7s linear infinite; }
.ai-orb-ring.b { animation: aiOrbSpinB 5.2s linear infinite; }
.ai-orb-ring.c { animation: aiOrbSpinA 9.5s linear infinite reverse; }
.ai-orb-core { transform-box: fill-box; transform-origin: center; animation: aiOrbCore 2.6s ease-in-out infinite; }
.ai-orb-halo { transform-box: fill-box; transform-origin: center; animation: aiOrbHalo 3.4s ease-in-out infinite; }
@keyframes aiOrbSpinA { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes aiOrbSpinB { from { transform: rotate(60deg); } to { transform: rotate(420deg); } }
@keyframes aiOrbCore { 0%, 100% { transform: scale(.9); opacity: .85; } 50% { transform: scale(1.12); opacity: 1; } }
@keyframes aiOrbHalo { 0%, 100% { transform: scale(.94); opacity: .35; } 50% { transform: scale(1.08); opacity: .6; } }
.qa-fab:hover .ai-orb-ring.a { animation-duration: 2.6s; } .qa-fab:hover .ai-orb-ring.b { animation-duration: 1.9s; }
@media (prefers-reduced-motion: reduce) { .ai-orb-ring, .ai-orb-core, .ai-orb-halo { animation: none !important; } }

/* Agent drawer: fewer competing rows before the first question. */
.qa-options { margin: 0 14px 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--mc-glass); }
.qa-options > summary { list-style: none; cursor: pointer; padding: 7px 11px; font: 600 var(--fs-2xs) var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.qa-options > summary::-webkit-details-marker { display: none; }
.qa-options > summary::after { content: "▾"; float: right; opacity: .7; }
.qa-options[open] > summary::after { content: "▴"; }
.qa-options .qa-answer-style, .qa-options .qa-scope { margin: 0 11px 10px; }
.qa-welcome { color: var(--text-mid) !important; font-size: var(--fs-sm) !important; }
.qa-head-actions .qa-head-btn { font-size: var(--fs-2xs); }

/* Ambient spotlight, portal-wide (V20.14.51). The guide had it; every page now
   carries the same soft wash so the surfaces sit in one lit room. */
/* The wash drifts on a CHILD that the viewport-sized parent clips. Animating
   the fixed layer itself (translate3d(1.5%, 1%) scale(1.04)) pushed roughly
   twenty pixels past the right edge, and Chrome counts that toward the
   document's scrollable width -- so a decorative background quietly gave every
   page a few pixels of horizontal scroll that came and went with the drift. */
.mc-spotlight { position: fixed; inset: 0; z-index: -2; pointer-events: none; overflow: hidden; }
.mc-spotlight::before {
  content: ""; position: absolute; inset: -6%;
  background:
    radial-gradient(760px 520px at 14% 4%, rgba(0, 229, 255, .13), transparent 62%),
    radial-gradient(680px 480px at 88% 10%, rgba(139, 92, 246, .11), transparent 60%),
    radial-gradient(900px 560px at 52% 104%, rgba(0, 229, 255, .09), transparent 62%);
  animation: mcSpotDrift 26s ease-in-out infinite alternate;
}
:root[data-theme="light"] .mc-spotlight::before {
  background:
    radial-gradient(760px 520px at 14% 4%, rgba(7, 143, 197, .10), transparent 62%),
    radial-gradient(680px 480px at 88% 10%, rgba(92, 182, 246, .07), transparent 60%),
    radial-gradient(900px 560px at 52% 104%, rgba(7, 143, 197, .07), transparent 62%);
}
@keyframes mcSpotDrift { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(1.5%, 1%, 0) scale(1.04); } }
@media (prefers-reduced-motion: reduce) { .mc-spotlight::before { animation: none; } }

/* Selected brand logo keeps its own artwork -- no drop shadow on it. */
.brand-btn.logo-only.active .brand-logo { filter: none !important; }
:root[data-theme="light"] .brand-btn.logo-only.active .brand-logo { filter: none !important; }

/* Guide digest follows the light theme instead of staying dark, and is framed
   like the section it is: what moved since last month. */
:root[data-theme="light"] .guide-digest-card { background: linear-gradient(150deg, #ffffff, #f2f9fe) !important; border-color: rgba(7, 143, 197, .32) !important; }
:root[data-theme="light"] .guide-digest-value { color: #10294a !important; }
:root[data-theme="light"] .guide-digest-body, :root[data-theme="light"] .guide-digest-note { color: #4a6485 !important; }
.guide-digest-card { border-left: 3px solid var(--cyan) !important; }
:root[data-theme="light"] .guide-digest-card { border-left-color: #078fc5 !important; }

/* ============================================================
   16. LIGHT-THEME PARITY PASS (V20.14.51)
   Light mode had drifted into being a paler copy of dark rather than its own
   finished surface: the selected tab and the active filter were barely
   distinguishable from their neighbours, the cards had lost the corner
   brackets that give every other box its frame, and the brackets that DID
   survive were drawn at a different size than the same box wears in dark.
   ============================================================ */

/* --- 16a. Corner brackets: one geometry for both themes ---
   Dark drew 14px x 1px marks just inside the box edge; light drew 24-30px x
   2.5px marks just outside it. Same box, visibly bigger frame in light --
   which is exactly what it looked like on Reporting Categories. Both themes
   now use the same 22px x 2px mark, so switching theme changes the colour of
   the frame and nothing else. */
.mc-hud, .panel, .kpi-card, .v46-brief, .launch-map, .login-card, .section-workspace, .global-panel, .system-map-panel {
  background-size: 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 100% 100% !important;
}
:root[data-theme="light"] .launch-map::before,
:root[data-theme="light"] .section-workspace::before,
:root[data-theme="light"] .global-panel::before,
:root[data-theme="light"] .system-map-panel::before {
  background-size: 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px;
}

/* --- 16b. Cards keep their brackets in light ---
   The light "firmer digital frame" rule sets background-image:none on .panel
   so the outside ::before brackets are the only frame -- but .panel is not in
   the ::before rule, so it ended up with no brackets at all, and .kpi-card /
   .v46-brief / .filterbar were left with the 1px dark-theme marks that are
   invisible on white. Drawn here as backgrounds (the same technique dark uses)
   because ::before and ::after are both already spoken for on these elements:
   the accent rule and the cursor spotlight. */
:root[data-theme="light"] .panel,
:root[data-theme="light"] .kpi-card,
:root[data-theme="light"] .v46-brief,
:root[data-theme="light"] .filterbar {
  /* V20.14.353 -- the HUD's brackets and glass in the slate tokens, not a hard-coded blue on white */
  background-image:
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    var(--mc-glass) !important;
  background-repeat: no-repeat !important;
  background-size: 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 100% 100% !important;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%, 0 0 !important;
  border-color: var(--line-strong) !important;
}
/* .panel was switched to overflow:visible in light so a set of brackets drawn
   OUTSIDE the box on a ::before would not be clipped away -- but no such rule
   was ever written for .panel, so all it did was let a panel grow to its
   content. On the Stores tab that meant the 1,786px transaction table dragged
   its panel to 1,846px and gave the whole page a horizontal scrollbar in light
   mode only. The brackets above are backgrounds drawn inside the border box,
   so the panel can clip again exactly as it does in dark. */
:root[data-theme="light"] .panel { overflow: hidden !important; }

/* --- 16c. The selected tab actually looks selected ---
   Section 6 paints the active tab with --cyan-soft and a cyan text-shadow.
   On the dark surface that is a lit panel; on white it is a pale wash barely
   a shade off its neighbours, and the glow only softens the text further. */
:root[data-theme="light"] #tabNav .tab-btn.active {
  color: #ffffff !important;
  background: linear-gradient(135deg, #0b86bb, #0a6f9e) !important;
  border-color: #076b98 !important;
  box-shadow: 0 6px 16px rgba(7, 107, 152, .28), inset 0 1px rgba(255, 255, 255, .25) !important;
  text-shadow: none !important;
}
:root[data-theme="light"] #tabNav .tab-btn.active .mc-tab-icon { opacity: 1; filter: none; }
:root[data-theme="light"] #tabNav .tab-btn:hover:not(.active) { color: #0b4f7b !important; background: #e7f5fd !important; border-color: rgba(7, 143, 197, .35) !important; }

/* --- 16d. The active filter reads as set, not merely focused ---
   .is-active previously differed from an untouched control only by a 2px ring
   in --cyan-soft, which on white is almost the page colour. A set filter is a
   statement about what the numbers on screen mean, so it gets a tinted field,
   a firm border and bolder text. */
:root[data-theme="light"] select.fselect.is-active,
:root[data-theme="light"] .mc-select.is-active select.fselect {
  color: #06405e !important;
  font-weight: 700 !important;
  background-color: #e4f5fe !important;
  border-color: #0b86bb !important;
  box-shadow: 0 0 0 2px rgba(11, 134, 187, .22), inset 0 1px #ffffff !important;
}

/* --- 16e. No black flash when a filter list opens ---
   The native <select> popup is painted by the browser using the CONTROL's own
   colour scheme, not the document's. The light theme sets color-scheme:light
   on :root, but a form control inside a surface that declares its own scheme
   (or is composited over one) can still open its list with the dark chrome for
   a frame before the option colours land -- which is the black flash. Stating
   the scheme and the option colours on the control itself removes the guess. */
:root[data-theme="light"] select,
:root[data-theme="light"] select.fselect,
:root[data-theme="light"] input,
:root[data-theme="light"] textarea { color-scheme: light; }
:root[data-theme="light"] select option,
:root[data-theme="light"] select.fselect option {
  background-color: #ffffff !important;
  color: #173b60 !important;
}
:root[data-theme="light"] select option:checked,
:root[data-theme="light"] select.fselect option:checked { background-color: #e4f5fe !important; }

/* --- 16f. Full-height overlays start below the telemetry rail ---
   The rail is fixed at the top of every page at z-index 1500 -- above the
   drawers deliberately, because it is instrument chrome that should stay
   readable. A drawer pinned to top:0 therefore loses its first 34px: the
   Exception Inbox's kicker disappeared and its close button was cut in half.
   Start them where the rail ends instead. */
/* The exception drawer is pinned top:0 with height:100vh, so it needs both
   moved. The agent drawer is inset from all four edges (top:18px/bottom:18px)
   and only needs its top pushed past the rail -- setting a height on it as
   well would over-constrain the box and cost it its bottom inset. */
html.mc-has-telemetry .v38-drawer { top: 34px !important; height: calc(100vh - 34px) !important; }
html.mc-has-telemetry .v38-backdrop { top: 34px; }
html.mc-has-telemetry .qa-drawer { top: 52px !important; }
@media (max-width: 620px) {
  html.mc-has-telemetry .v38-drawer { top: 32px !important; height: calc(100vh - 32px) !important; }
  html.mc-has-telemetry .v38-backdrop { top: 32px; }
  html.mc-has-telemetry .qa-drawer { top: 50px !important; }
}

/* --- 16g. Decoration never gives the page a horizontal scrollbar ---
   Roughly one sample in five, the document's scrollWidth was 11px wider than
   the viewport and a horizontal scrollbar flickered in, yet no ELEMENT ever
   measured past the right edge -- the overflow comes from the animated
   ::before/::after decoration (sweeps, orbit rings, pulse halos), which
   getBoundingClientRect cannot see and which is purely ornamental. `clip`
   rather than `hidden` on purpose: `hidden` would make the body a scroll
   container and break the sticky header that sits inside it, while `clip`
   trims the painting and leaves positioning alone. Vertical scrolling is
   untouched. */
body { overflow-x: clip; }

/* ============================================================
   17. PASS 14 (7 Sep 2026)
   ============================================================ */

/* --- 17a. KPI delta is a bare coloured figure ---
   The ring shadow (--glow-green / --glow-red) painted a dark halo behind the
   percentage and, in light mode, a tinted box; with the magnitude track under
   it the whole thing read as a badge sitting on the card. Arrow and number in
   green or red, nothing behind them. The track is kept but made hairline so it
   informs without framing. */
.kpi-card .kdelta, .kpi-foot .kdelta { background: none !important; border: 0 !important; box-shadow: none !important; padding: 0 !important; border-radius: 0 !important; text-shadow: none !important; }
.kpi-foot .kdelta .kdelta-track { height: 2px; background: transparent; }
.kpi-foot .kdelta .kdelta-track i { box-shadow: none; opacity: .55; }
.kpi-card.tone-neg .kdelta { color: var(--red); }
/* V20.14.353 -- the slate green and red (6.0:1 on the slate panel); #138546 / #c8323d were tuned for white */
:root[data-theme="light"] .kpi-card.tone-pos .kdelta { color: var(--green); }
:root[data-theme="light"] .kpi-card.tone-neg .kdelta { color: var(--red); }

/* --- 17b. Filter deck: filters left, view actions right, no scope strip ---
   Row one is the FILTERS label and the selects, flush left. Row two is one
   right-aligned cluster in this order: Saved views, SAVE VIEW, SHARE VIEW,
   EXPORT CSV, UNDO FILTER, EXPORT PDF, RESET. The INTERPRETED SCOPE strip is
   hidden rather than removed: its chips still drive the reset counter, the
   selects' is-active state and the URL, and the tests pin that wiring. */
.filterbar #v20Scope { display: none !important; }
.filterbar .filter-share { order: 6; margin-top: 4px; }
.filterbar #v20SavedViews { order: 5; margin-left: auto; }
.filterbar #v20SaveView { order: 5; }
.filterbar #v20UndoFilter, .filterbar #v20ExportPdf { order: 7; }
.filterbar .filter-reset { order: 8; }

/* --- 17c. Tab rail inside the frozen deck --- */
/* ==========================================================================
   V20.14.158 -- THE TWO NUMBERS THAT DECIDE WHAT COVERS WHAT, TOGETHER.
   The filter bar carries `position:relative; z-index:2` from the page's own
   stylesheet, which makes it a STACKING CONTEXT. Everything inside it is
   painted at 2, whatever z-index the child asks for -- so the new hover label
   on the icon cluster was drawn under the tab strip at 701 no matter how large
   a number it used. I raised it to 60, then to the --z-tooltip token at 1400,
   and neither could work: a child cannot escape its own context, so the number
   was never the thing that was wrong.
   The filter bar is the control surface and the tab strip sits beneath it, so
   the bar's transient overlays belong above it. The two values are stated here
   on adjacent lines, because they only mean anything relative to each other
   and the last time they were set 600 lines and one release apart the later
   one silently won.
   ========================================================================== */
.pulse-sticky-header .filterbar { position: relative; z-index: 702; }
.pulse-sticky-header .tabnav { margin-top: 10px !important; margin-bottom: 0 !important; position: relative; z-index: 701; }
.pulse-sticky-header .tabnav[hidden] { display: none !important; }

/* --- 17d. PULSE AGENT is just the orb ---
   No box, no border, no dashed orbit ring, no tinted plate: the orb's own rings
   already animate, and everything drawn around it made it a button wearing a
   frame. The orb grows to fill the 52px footprint so the click target is
   unchanged. */
.qa-fab, .qa-fab:hover, .qa-fab:active { border: 0 !important; background: none !important; box-shadow: none !important; }
.qa-fab::before, .qa-fab::after { display: none !important; }
.qa-fab .qa-fab-orb { background: none !important; border: 0 !important; box-shadow: none !important; }
.qa-fab .qa-fab-orb::before, .qa-fab .qa-fab-orb::after { display: none !important; }
.qa-fab .qa-fab-orb, .qa-fab svg { width: 46px !important; height: 46px !important; }
.qa-fab:hover svg { filter: drop-shadow(0 0 12px rgba(0, 229, 255, .8)); }
:root[data-theme="light"] .qa-fab, :root[data-theme="light"] .qa-fab:hover { border: 0 !important; background: none !important; box-shadow: none !important; }
:root[data-theme="light"] .qa-fab .qa-fab-orb { background: none !important; box-shadow: none !important; }

/* --- 17e. KPI cards: one row, one reading order ---
   Six cards (invoices joins the row) stay on one line down to 1180px. Inside
   a card the order is fixed and the sizes step down: label, then the value
   with its trace beside it, then the change as a coloured figure followed by
   the comparison on the same line, then the actions. The magnitude track and
   the separate "vs YTD" tag are gone -- both repeated what the line already
   said and made the foot of the card the busiest part of it. */
.kpi-row { gap: 10px !important; } /* column count is set inline per card count (renderKpiRow) */
.kpi-card { padding: 12px 14px 8px !important; gap: 5px !important; min-height: 0 !important; }
.kpi-head { align-items: center; }
.kpi-card .klabel { font-size: 11px !important; letter-spacing: .12em; }
.kpi-main { align-items: center !important; min-height: 34px !important; gap: 8px !important; }
.kpi-card .kvalue { font-size: 24px !important; }
.kpi-card .kspark { max-width: 46%; height: 26px; }
.kpi-foot { flex-wrap: nowrap !important; gap: 8px !important; align-items: baseline !important; min-width: 0; }
.kpi-foot .kdelta { display: inline-flex !important; gap: 4px; flex: none; }
.kpi-foot .kdelta i { font-size: 11px; }
.kpi-foot .kdelta b { font-size: 14px !important; }
.kpi-foot .kdelta .kdelta-track { display: none !important; }
.kpi-foot .ksub { font-size: 11px !important; color: var(--text-dim); line-height: 1.3; min-width: 0; }
.kpi-actions { padding-top: 4px !important; }
.kpi-card.is-missing .kvalue { color: var(--text-dim) !important; }
.kpi-card.is-missing .kdelta { color: var(--text-dim) !important; }
@media (max-width: 1180px) { .kpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; } }
@media (max-width: 720px) { .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }

/* --- 17f. Breathing room between panels and the boxes around them ---
   The insight strip that sits between two rows of charts had 16px above and
   nothing below, so it read as glued to the top of the next panel row (the
   Branch Contribution panel in particular). Even spacing on both sides. */
#tabBody .insight, #tabBody .v21-narrative, #tabBody .caveat-note, #tabBody .v20-callout { margin-top: 18px !important; margin-bottom: 18px !important; }
#tabBody .panel-grid + .insight, #tabBody .panel + .insight { margin-top: 18px !important; }
#tabBody .insight + .panel-grid, #tabBody .insight + .panel { margin-top: 0 !important; }
#tabBody .panel-grid { gap: 18px !important; }
#tabBody .panel-grid + .panel-grid, #tabBody .panel + .panel-grid, #tabBody .panel-grid + .panel { margin-top: 18px !important; }

/* --- 17g. Reporting Categories: frozen section rail, grouped 4-up applications ---
   1. The section rail stays put while the applications scroll under it, so
      the way to another section is always one click away. overflow:hidden on
      .launch-map made sticky impossible (an overflow ancestor pins a sticky
      child to itself); clip keeps the decorative grid inside the box without
      creating a scroll container.
   2. Sections that are not selected sit back at reduced opacity; the selected
      one, and any one under the cursor, is fully drawn.
   3. Each application group is its own bracketed box, and applications sit
      four to a row as tiles instead of one long list. */
.launch-map { overflow: clip !important; }
.section-switcher {
  position: sticky; top: 34px; z-index: 6;
  margin: 0 -22px; padding: 12px 22px !important;
  background: var(--bg-panel); box-shadow: 0 10px 18px -12px rgba(0, 0, 0, .55);
}
/* V20.14.353 -- the switcher sits in the workspace glass in light as in dark: no white band */
:root[data-theme="light"] .section-switcher { background: transparent; box-shadow: none; }
.section-tab:not(.is-active) { opacity: .5 !important; filter: saturate(.6); }
.section-tab:not(.is-active):hover, .section-tab:not(.is-active):focus-visible { opacity: 1 !important; filter: none; }
.section-tab.is-active { opacity: 1 !important; filter: none; }

/* Groups: bracketed boxes. */
.application-group {
  position: relative; margin-top: 14px !important; padding: 12px 12px 12px;
  border: 1px solid var(--line-strong); border-radius: 8px;
  background-image:
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket)),
    linear-gradient(var(--mc-bracket), var(--mc-bracket)), linear-gradient(var(--mc-bracket), var(--mc-bracket));
  background-repeat: no-repeat;
  background-size: 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px, 22px 2px, 2px 22px;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%;
}
.application-group:first-child { margin-top: 6px !important; }
.application-group-head { margin-bottom: 10px !important; }
/* V20.14.353 -- the group keeps the HUD's own bracket colour and sits on the slate panel */
:root[data-theme="light"] .application-group { border-color: var(--line-strong); background-color: var(--bg-panel); }

/* Tiles, four to a row. */
.application-group-body, .section-application-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) !important; gap: 10px !important; }
.section-application-grid > .application-group { grid-column: 1 / -1; }
.section-application {
  grid-template-columns: 1fr !important; grid-template-rows: auto 1fr auto; justify-items: start;
  min-height: 0 !important; padding: 12px 12px 10px !important; gap: 8px !important; border-radius: 8px !important;
}
.section-application.is-flagship { grid-column: auto !important; }
.section-application .application-mark { width: 44px !important; height: 44px !important; border-radius: 9px !important; }
.section-application .application-mark img { width: 36px !important; height: 36px !important; }
.section-application > div:not(.application-mark) { min-width: 0; align-self: start; }
.section-application > div > span { display: block; font: 700 11px var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.section-application b { font-size: 12.5px !important; line-height: 1.2 !important; margin: 4px 0 3px !important; }
.section-application small { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.section-application > i { position: static !important; justify-self: start; margin-top: 2px; padding: 3px 7px; border: 1px solid var(--line-strong); border-radius: 999px; font-size: 11px !important; }
.section-application.is-coming-soon > i { color: var(--gold) !important; border-color: var(--gold-line); background: var(--gold-soft); }
.section-application.is-locked:not(.is-coming-soon) > i { color: var(--text-dim) !important; }
.section-application.is-flagship > i, .section-application:not(.is-locked) > i { color: var(--green) !important; border-color: var(--green-line); background: var(--green-soft); }
@media (max-width: 1100px) { .application-group-body, .section-application-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; } }
@media (max-width: 800px) { .application-group-body, .section-application-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }
@media (max-width: 520px) { .application-group-body, .section-application-grid { grid-template-columns: 1fr !important; } }

/* Stats box: one icon per figure. */
.launch-map-status { grid-template-columns: auto auto auto !important; column-gap: 8px !important; align-items: center; }
.launch-map-status .lms-icon { display: inline-flex; width: 18px; height: 18px; color: var(--cyan); }
.launch-map-status .lms-icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.launch-map-status .lms-icon.is-live { color: var(--green); }
.launch-map-status .lms-icon.is-pending { color: var(--gold); }

/* --- 17h. Stores table fits the page ---
   The table was pinned to min-width:1660px inside a 1,358px panel, so it
   always scrolled sideways and never lined up with the page edge. Fixed
   layout at 100% with a wider column for the store name and narrower ones
   for the short numerics keeps all seventeen columns on one screen at
   1440px; the wrapper keeps overflow:auto as the fallback below that. */
.store-table { min-width: 0 !important; width: 100% !important; table-layout: fixed; font-size: 11px !important; }
.store-table col.col-name { width: 13%; }
.store-table col.col-id { width: 7.5%; }
.store-table col.col-narrow { width: 4.4%; }
.store-table col.col-status { width: 6%; }
.store-table col.col-perf { width: 8.6%; }
.store-table th { white-space: normal !important; line-height: 1.2; padding: 6px 4px !important; font-size: 11px !important; vertical-align: bottom; }
.store-table th .sort-button { white-space: normal; font-size: 11px !important; letter-spacing: .04em !important; padding: 0 !important; }
.store-table td { padding: 5px 5px !important; overflow: hidden; text-overflow: ellipsis; }
.store-table .status-chip { font-size: 11px !important; padding: 2px 5px !important; letter-spacing: .04em !important; }
@media (max-width: 1280px) { .store-table { min-width: 1280px !important; table-layout: auto; } }

/* --- 17i. A leaner frozen deck ---
   With the tab rail inside it the deck is ~380px tall at 1440x900. Vertical
   padding trimmed across its four rows; nothing is removed. */
.pulse-sticky-header { padding-bottom: 8px !important; margin-bottom: 16px !important; }
.pulse-sticky-header .topbar { padding-top: 10px !important; padding-bottom: 8px !important; }
.pulse-sticky-header .brand-switcher { margin-bottom: 8px !important; padding-top: 6px !important; padding-bottom: 6px !important; }
.pulse-sticky-header .filterbar { padding: 8px 12px !important; }
.pulse-sticky-header .tabnav { margin-top: 8px !important; padding: 4px !important; }
.pulse-sticky-header #tabNav .tab-btn { padding: 7px 12px !important; }
/* Light: the orb's white core and pale rings vanished on a white rail once the
   plate behind it was removed. A soft shadow and a little more saturation
   give it presence without putting a box back around it. */
:root[data-theme="light"] .qa-fab svg { filter: saturate(1.5) brightness(.88) drop-shadow(0 3px 8px rgba(7, 107, 152, .45)) drop-shadow(0 0 2px rgba(7, 107, 152, .35)); }
:root[data-theme="light"] .qa-fab:hover svg { filter: saturate(1.6) brightness(.85) drop-shadow(0 4px 12px rgba(7, 107, 152, .6)); }

/* ============================================================
   18. PASS 15 (7 Sep 2026)
   ============================================================ */

/* --- 18a. Header: three clusters, one height ---
   [unit | window]  ·  [WHAT-IF  ADMIN]  ·  [home guide theme alerts bell profile]
   Every control is 34px tall with the same gap; a hairline divider separates
   the clusters. LIVE DATASET becomes a small status pill at the end. */
.topbar-controls { gap: 12px !important; }
.header-toggle-group { gap: 6px; }
.segmented-control { height: 34px; box-sizing: border-box; padding: 2px !important; }
.segmented-option { padding: 5px 11px !important; font-size: 11px !important; }
.header-icon-group { gap: 6px !important; padding-left: 12px; border-left: 1px solid var(--line-strong); }
#headerIconGroup > * { height: 34px !important; box-sizing: border-box; }
#headerIconGroup > a.icon-btn[href="/"] { margin-left: 8px; position: relative; }
#headerIconGroup > a.icon-btn[href="/"]::before { content: ""; position: absolute; left: -8px; top: 5px; bottom: 5px; width: 1px; background: var(--line-strong); }
#headerIconGroup .v21-btn { display: inline-flex !important; align-items: center; padding: 0 11px !important; border-radius: 8px !important; font-size: 11px !important; letter-spacing: .08em; }
#headerIconGroup .v21-icon-btn { width: 34px; padding: 0 !important; justify-content: center; }
#headerIconGroup .v21-icon-btn svg { width: 16px; height: 16px; }
.clock { display: inline-flex; align-items: center; }
.clock .live { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 11px; border: 1px solid var(--green-line); border-radius: 8px; background: var(--green-soft); font-size: 11px !important; letter-spacing: .1em !important; text-shadow: none !important; }
.brandmark .report-mark { width: 56px !important; height: 56px !important; }

/* --- 18b. Filter deck on one line ---
   The selects on the left; the view actions on the right as icon buttons
   with tooltips (SAVE, SHARE, EXPORT CSV, UNDO, PDF), then Saved views and
   RESET. The row break that made it two rows is gone. */
.filterbar { flex-wrap: nowrap !important; overflow: visible; }
.filterbar::after { display: none !important; }
.filterbar .flabel { flex: none; }
.filterbar .mc-select { flex: 0 1 auto; min-width: 0; }
.filterbar select.fselect { max-width: 190px; }
.filterbar #v20SavedViews { max-width: 120px; margin-left: auto; margin-top: 0 !important; }
.filterbar .v20-control, .filterbar .filter-share, .filterbar .filter-reset { margin-top: 0 !important; height: 36px; box-sizing: border-box; }
.filterbar .filter-share .share-label { display: none; }
/* ==========================================================================
   V20.14.157 -- THE UPPER-RIGHT ICON CLUSTER, STATED ONCE
   Reported: "remove boxes around upper right corner icons, make them bigger",
   and separately "all upper right icons same size and aligned".
   They were already the same size and aligned -- measured 32x32, all at the
   same y. What made them look unequal was that they were TWO FAMILIES wearing
   different clothes side by side: `.v20-control` buttons had a filled plate
   and 6px corners, `.filter-share` buttons were transparent with 8px corners,
   and five stylesheets between them set border, background or radius on one
   family or the other -- 67 declarations for eight buttons.
   Borderless, because the glyph is the affordance once a control has no words.
   Bigger where it matters: the box goes 32 -> 36, but the GLYPH goes 15 -> 20,
   which is the number that was actually making them look small -- a 15px mark
   in a 32px button fills under half of it.
   Competitors are narrowed at source (see `:not(.v20-icon)` above and the
   light-theme block in pulse-light-revamp.css) rather than out-weighted here,
   so this stays the only rule with an opinion.
   ========================================================================== */
.filterbar .filter-share, .filterbar .v20-control.v20-icon {
  position: relative;
  width: 36px; padding: 0 !important; justify-content: center;
  background: transparent !important;
  border: 0 !important;
  border-radius: 11px !important;
  box-shadow: none !important;
  color: var(--text-mid);
  transition: color .2s ease, background-color .2s ease, transform .2s cubic-bezier(.2,.8,.2,1);
}
/* V20.14.158 -- the GLYPH is its own animated layer, separate from the button.
   "I do not like the upper right icons at all, please revamp it but make
   animative." Moving the button moves the hit area and the hover plate with
   it, which is why a single transform on the button reads as a twitch. The
   button holds the plate; the mark inside it is what performs. */
.filterbar .filter-share svg, .filterbar .v20-control.v20-icon svg {
  transition: transform .3s cubic-bezier(.2,.8,.2,1), filter .3s ease;
  transform-origin: 50% 50%;
}
/* The plate: a soft capsule that grows out of the centre rather than switching
   on. Drawn as a pseudo-element so its scale never touches the glyph. */
.filterbar .filter-share::before, .filterbar .v20-control.v20-icon::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  background: var(--cyan-soft);
  box-shadow: 0 0 0 1px var(--cyan-line) inset;
  opacity: 0; transform: scale(.6);
  transition: opacity .2s ease, transform .26s cubic-bezier(.2,.8,.2,1);
  pointer-events: none;
}
.filterbar .filter-share:hover::before, .filterbar .v20-control.v20-icon:hover::before,
.filterbar .filter-share:focus-visible::before, .filterbar .v20-control.v20-icon:focus-visible::before {
  opacity: 1; transform: scale(1);
}
.filterbar .filter-share:hover, .filterbar .v20-control.v20-icon:hover,
.filterbar .filter-share:focus-visible, .filterbar .v20-control.v20-icon:focus-visible {
  color: var(--cyan) !important;
}
.filterbar .filter-share:hover svg, .filterbar .v20-control.v20-icon:hover svg {
  filter: drop-shadow(0 0 6px rgba(0, 217, 255, .45));
}
/* Pressed: the whole control gives, which is the one moment the BUTTON should
   move rather than the mark. */
.filterbar .filter-share:active, .filterbar .v20-control.v20-icon:active { transform: scale(.92); }
.filterbar .filter-share:focus-visible, .filterbar .v20-control.v20-icon:focus-visible {
  outline: 2px solid var(--cyan); outline-offset: 3px;
}

/* ==========================================================================
   V20.14.164 -- THE HOUSING, AND MOTION YOU CAN ACTUALLY SEE
   ==========================================================================
   Asked directly what was wrong with the cluster, the answers were: the glyphs
   are unclear, it is too plain / lacks presence, and the motion is too subtle.
   The glyphs are answered in pulse-hud-icons.js. These are the other two.

   PRESENCE WITHOUT PUTTING THE BOXES BACK. V20.14.157 removed a plate from
   every button and was right to: eight bordered plates in a row is a fence.
   What was missing was never a box PER BUTTON, it was one housing for the
   GROUP -- so the run now sits in a single recessed rail (v164-instrument-rail
   .js builds the element, because eight buttons mounted by five modules have
   no container to style). Recessed rather than raised: these are instruments
   set into a console, and a raised bar would compete with the panels below it
   on a page whose job is numbers.
   ========================================================================== */
.filterbar .v164-rail {
  /* The cluster's place in the bar, which used to be spread over four `order`
     values on individual buttons. The rail carries the one that matters. */
  order: 6; margin-top: 4px;
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px 5px;
  border-radius: 13px;
  /* The depth is three declarations doing three different jobs: a darker floor,
     an inner shadow at the top edge that makes it read as cut INTO the bar, and
     a one-pixel highlight at the bottom edge where light would catch the far
     lip. Any one alone reads as a flat grey box. */
  background: linear-gradient(180deg, rgba(0, 0, 0, .34), rgba(0, 0, 0, .16));
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, .5),
    inset 0 -1px 0 rgba(255, 255, 255, .06),
    inset 0 0 0 1px rgba(0, 229, 255, .10);
}
/* A hairline at each end, so the run reads as a fitted unit rather than as a
   stripe that happens to stop. Drawn on the rail, not between buttons: eight
   dividers would be the fence again. */
/* And the per-button `order` values are switched off INSIDE the rail.
   I wrote a comment here first saying they "mean nothing" in the rail. They
   mean everything: the rail is itself a flex container, `.filterbar #v20SaveView`
   still matches its child, and `order: 5` on that child beat the sequence
   v164-instrument-rail.js had just arranged. The result looked almost right,
   which is the worst way for it to be wrong -- two owners for one property,
   found by comparing the rendered rail against the order the module reported.
   One owner now: the module decides, DOM order carries it. */
.filterbar .v164-rail > * { order: 0 !important; }

.filterbar .v164-rail::before,
.filterbar .v164-rail::after {
  content: ''; width: 1px; height: 16px; flex: none;
  background: linear-gradient(180deg, transparent, var(--cyan-line), transparent);
  opacity: .55;
}
:root[data-theme="light"] .filterbar .v164-rail {
  background: linear-gradient(180deg, rgba(0, 60, 90, .07), rgba(0, 60, 90, .02));
  box-shadow:
    inset 0 2px 4px rgba(0, 60, 90, .13),
    inset 0 -1px 0 rgba(255, 255, 255, .9),
    inset 0 0 0 1px rgba(0, 132, 184, .14);
}

/* ---- each mark moves the way its own tool does ------------------------- */
/* Motion that describes the action is the difference between "animated" and
   "decorated": the undo arrow winds back, the export leaves the page, the view
   drops into its slot. Someone who cannot read the tooltip can still tell
   these apart.

   V20.14.164 -- the amplitudes are roughly doubled, and more of the motion is
   now INSIDE the glyph. That second part is what actually answers "too
   subtle": a mark that tilts by six degrees is a mark that moved, while a mark
   whose payload travels while its frame holds still is a mark that DID
   something. The icon grammar exists for exactly this -- .hud-frame is the
   object, .hud-live is the action, .hud-accent is the direction. */
#v20SaveView:hover svg      { transform: translateY(3px) scale(1.10); }
#v20UndoFilter:hover svg    { transform: rotate(-54deg) scale(1.06); }
#v20ExportPdf:hover svg     { transform: translateY(-3px) rotate(-8deg) scale(1.10); }
#exportTabBtn:hover svg     { transform: translateY(4px) scale(1.10); }
#valueSearchBtn:hover svg   { transform: scale(1.26) rotate(-12deg); }
#shareViewBtn:hover svg     { transform: rotate(-34deg) scale(1.14); }
#pw86Launch:hover svg       { transform: translateY(-3px) scale(1.12); }
#v105TrustButton:hover svg  { transform: scale(1.18); }

/* The payload performs the verb. The frame is what stops this reading as the
   whole icon wobbling -- it never moves, so the eye reads a part travelling
   through an object rather than an object shaking. */
.filterbar .v164-rail .hud-live {
  transition: transform .34s cubic-bezier(.2,.8,.2,1), opacity .34s ease;
  transform-box: view-box; transform-origin: 50% 50%;
}
#v20SaveView:hover .hud-live      { transform: translateY(2.2px); }   /* kept */
#v20ExportPdf:hover .hud-live     { transform: translateY(3.4px); opacity: .25; }  /* leaves the page */
#exportTabBtn:hover .hud-live     { transform: translateY(3.4px); opacity: .25; }  /* leaves the table */
#v20UndoFilter:hover .hud-live    { transform: rotate(38deg); }       /* the return arc swings back */
#shareViewBtn:hover .hud-live     { transform: scale(1.3); }          /* the far nodes reach out */
#pw86Launch:hover .hud-live       { transform: translateY(-2.4px); }  /* the contents rise */

/* ---- at rest: alive, not busy ----------------------------------------- */
/* V20.14.158 drifted the whole mark 1.5px. That was measured to be too quiet,
   and simply raising it would have made a row of eight glyphs bob above a page
   of figures -- which is the one thing motion here must not do.
   So the drift stays small and a SECOND, separate signal carries the life: the
   payload of each mark breathes on its own cycle. Two slow motions of
   different periods read as considerably more alive than one larger one, and
   neither of them moves the text underneath. */
@keyframes v158ToolDrift { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes v164LivePulse {
  0%, 100% { opacity: .95; transform: translateY(0) scale(1); }
  50%      { opacity: .55; transform: translateY(-.7px) scale(1.06); }
}
@keyframes v164Sweep { to { transform: rotate(360deg); } }
.filterbar .filter-share svg, .filterbar .v20-control.v20-icon svg {
  animation: v158ToolDrift 3.8s ease-in-out infinite;
}
.filterbar .v164-rail .hud-live {
  transform-box: view-box; transform-origin: 50% 50%;
  animation: v164LivePulse 4.6s ease-in-out infinite;
}
/* The reticle keeps turning -- V20.14.146 chose it deliberately and V20.14.148
   set it going; this build carries that into the shared set rather than
   dropping it. Driven here so ONE rule set owns the cluster's motion: the same
   keyframe name used to be declared in both v104-value-features.css and
   pulse-v151-user-revision.css, with different durations, and which one turned
   the sweep depended on stylesheet order. */
.filterbar .v164-rail .hud-sweep {
  transform-box: view-box; transform-origin: 10.8px 10.8px;
  opacity: .6;
  animation: v164Sweep 3.1s linear infinite;
}
.filterbar .v164-rail :is(.filter-share, .v20-control.v20-icon):hover .hud-sweep { animation-duration: 1.05s; opacity: .9; }
/* Stagger by POSITION IN THE RAIL. The old rule counted `:nth-of-type` among
   the filter bar's children, which after the rail exists counts nothing useful
   -- and counted the selects too, so several buttons shared a delay. */
.filterbar .v164-rail > :nth-child(2) :is(svg, .hud-live) { animation-delay: .22s; }
.filterbar .v164-rail > :nth-child(3) :is(svg, .hud-live) { animation-delay: .44s; }
.filterbar .v164-rail > :nth-child(4) :is(svg, .hud-live) { animation-delay: .66s; }
.filterbar .v164-rail > :nth-child(5) :is(svg, .hud-live) { animation-delay: .88s; }
.filterbar .v164-rail > :nth-child(6) :is(svg, .hud-live) { animation-delay: 1.1s; }
.filterbar .v164-rail > :nth-child(7) :is(svg, .hud-live) { animation-delay: 1.32s; }
.filterbar .v164-rail > :nth-child(8) :is(svg, .hud-live) { animation-delay: 1.54s; }
/* Hover takes the mark off the drift so the two never fight over transform. */
.filterbar .filter-share:hover svg, .filterbar .v20-control.v20-icon:hover svg,
.filterbar .filter-share:focus-visible svg, .filterbar .v20-control.v20-icon:focus-visible svg {
  animation: none;
}
.filterbar :is(.filter-share, .v20-control.v20-icon):is(:hover, :focus-visible) .hud-live { animation: none; }

/* DATA TRUST: the state goes ON the mark, not beside it.
   The dot was a sibling of the label, which in the icon-only bar left it
   sitting alone in a 7px-wider cell -- so a row of eight controls read as
   eight glyphs and a stray green light, and the rail's end hairline was pushed
   off the edge. As a badge on the shield it says the same thing about the same
   object, and the cell is 36px like every other. v105-operations.css still owns
   the dot's size and colour; this only places it. */
.filterbar .v164-rail #v105TrustButton { position: relative; }
.filterbar .v164-rail #v105TrustButton .v105-trust-dot {
  position: absolute; right: 6px; bottom: 6px;
  outline: 2px solid var(--bg-panel);
}
@keyframes v164TrustBadge { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.35); } }
.filterbar .v164-rail #v105TrustButton .v105-trust-dot { animation: v164TrustBadge 3.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .filterbar .v164-rail #v105TrustButton .v105-trust-dot { animation: none !important; }
}

/* Pressed: a flash in the cell the finger is on. The button already gives
   under the press; without something in the housing, the give happens in front
   of a rail that does not acknowledge it. */
@keyframes v164Strike { from { opacity: .85; transform: scale(.82); } to { opacity: 0; transform: scale(1.25); } }
.filterbar .v164-rail :is(.filter-share, .v20-control.v20-icon):active::before {
  animation: v164Strike .34s ease-out;
}

/* A reader who asks for less motion gets less motion -- all of it, including
   the parts data-motion-always exempts from the BUDGET. Those are different
   questions: the budget is about how busy the page is, this is about what a
   person has told their operating system they want. */
@media (prefers-reduced-motion: reduce) {
  .filterbar .filter-share svg, .filterbar .v20-control.v20-icon svg,
  .filterbar .v164-rail .hud-live,
  .filterbar .v164-rail .hud-sweep,
  .filterbar .v164-rail :is(.filter-share, .v20-control.v20-icon):active::before {
    animation: none !important;
  }
  .filterbar .v164-rail .hud-live { opacity: 1 !important; transform: none !important; }
}

/* ---- the label ---------------------------------------------------------- */
/* The native `title` tooltip takes about a second to appear, cannot be styled,
   and on a row of eight unlabelled glyphs that second is the whole cost of the
   control. This one is instant and belongs to the design. `data-tip` is
   normalised for every button in the cluster by v20-enhancements.js, so the
   text has one source whichever layer built the button. */
.filterbar :is(.filter-share, .v20-control.v20-icon)[data-tip]::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + 9px); left: 50%;
  /* The tab strip below this bar is z-index 701, so a hand-picked small number
     puts the label UNDER the thing it overlaps -- which is how the first
     attempt at this printed a tooltip behind "DRIVERS". pulse-tokens.css
     already keeps a layer scale for exactly this; a tooltip belongs on the
     tooltip layer, not on a number that happened to look big enough.
     Deliberately no z-index on the button itself: that would create a stacking
     context and trap this label inside it, back under the tab strip. */
  z-index: var(--z-tooltip, 1400);
  width: max-content; max-width: 210px;
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px solid var(--cyan-line);
  background: var(--bg-panel);
  color: var(--text-hi);
  font: 500 11px/1.45 var(--font-mono);
  letter-spacing: .02em;
  text-align: left; white-space: normal;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .34);
  opacity: 0; transform: translate(-50%, -5px);
  pointer-events: none;
  transition: opacity .16s ease, transform .22s cubic-bezier(.2,.8,.2,1);
}
.filterbar :is(.filter-share, .v20-control.v20-icon)[data-tip]:hover::after,
.filterbar :is(.filter-share, .v20-control.v20-icon)[data-tip]:focus-visible::after {
  opacity: 1; transform: translate(-50%, 0);
}
/* The last controls sit against the right edge; their label is pulled back in
   rather than being allowed to hang off the page. */
.filterbar > :nth-last-child(-n+3) :is(.filter-share, .v20-control.v20-icon)[data-tip]::after,
.filterbar :is(.filter-share, .v20-control.v20-icon):nth-last-of-type(-n+3)[data-tip]::after {
  left: auto; right: 0; transform: translate(0, -5px);
}
.filterbar > :nth-last-child(-n+3) :is(.filter-share, .v20-control.v20-icon)[data-tip]:hover::after,
.filterbar :is(.filter-share, .v20-control.v20-icon):nth-last-of-type(-n+3)[data-tip]:hover::after {
  transform: translate(0, 0);
}

/* Motion is a preference, not a given -- and the scroll-suspension class in
   pulse-performance.css still parks the drift while the page is moving, which
   is why none of this carries `data-motion-always`. */
@media (prefers-reduced-motion: reduce) {
  .filterbar .filter-share, .filterbar .v20-control.v20-icon,
  .filterbar .filter-share::before, .filterbar .v20-control.v20-icon::before,
  .filterbar .filter-share svg, .filterbar .v20-control.v20-icon svg,
  .filterbar :is(.filter-share, .v20-control.v20-icon)[data-tip]::after {
    transition: none !important; animation: none !important;
  }
  .filterbar .filter-share:hover svg, .filterbar .v20-control.v20-icon:hover svg { transform: none; }
}
/* V20.14.148 -- `flex: none`, and the reason it has to be here.
   These buttons are 32px wide and hold their icon in a flex row. A flex item
   with no `flex` of its own may be shrunk below its stated size, so anything
   ELSE inside the button takes the space first and the icon collapses to zero.
   That is exactly what happened to command search: it is the only button on
   this bar that also carries a keyboard hint, the hint took 25 of the 32px,
   and the icon measured 0px wide. Two builds redrew that icon (110, 146) and
   neither could ever have been visible -- reported both times as "no change".
   The width was never the instruction it looked like; `flex: none` is.
   Stated once for every button on the bar rather than per button: workspace86
   had already patched its own launcher this way, which is the same fault
   fixed in one place instead of five. */
/* V20.14.157 -- 15px -> 20px. This is the "make them bigger" number: the glyph
   is what you actually see, and 15px inside a 32px button filled 47% of it. */
.filterbar .filter-share svg, .filterbar .v20-control.v20-icon svg { width: 20px; height: 20px; flex: none; }
/* The shortcut hint cannot fit in a 32px square beside the icon, and it is the
   icon that names the control. The hint is in the button's title text and on
   the dialog's own footer, so nothing is lost by dropping it here. */
.filterbar .filter-share kbd { display: none; }
.filterbar .filter-reset { padding: 0 10px !important; white-space: nowrap; margin-left: 4px !important; }
/* V20.14.148 -- PORTFOLIO keeps the global tools and drops the scope controls.
   Written as "everything that is not a global tool" rather than as a list of
   the controls to hide, so the rule cannot fall behind the bar's contents --
   a control added to this bar next year is hidden here by default, and a tool
   that should survive says so on itself with data-global-tool. */
.filterbar.is-global-only > *:not([data-global-tool]) { display: none !important; }
.filterbar.is-global-only { justify-content: flex-end; }
@media (max-width: 1280px) { .filterbar { flex-wrap: wrap !important; } .filterbar #v20SavedViews { margin-left: 0; } }

/* --- 18c. Brand rail: logos alone ---
   No chip, no border, no plate. Unselected logos are translucent and
   desaturated; the selected one is fully drawn with its own brand glow
   behind it. PORTFOLIO follows the same rule with its wordmark. */
.brand-switcher { gap: 4px !important; align-items: center; }
.brand-btn.logo-only, .brand-btn.portfolio-btn {
  border: 0 !important; background: transparent !important; box-shadow: none !important; border-radius: 10px !important;
  opacity: .32; filter: saturate(.2) contrast(.9);
}
.brand-btn.logo-only:hover, .brand-btn.portfolio-btn:hover { opacity: .8; filter: saturate(.8); transform: translateY(-2px); background: transparent !important; border-color: transparent !important; }
.brand-btn.logo-only.active, .brand-btn.portfolio-btn.active {
  opacity: 1; filter: none; background: transparent !important; box-shadow: none !important; border: 0 !important;
}
.brand-btn.logo-only.active .brand-logo { filter: drop-shadow(0 0 14px rgba(var(--brand-glow, 0, 229, 255), .75)) drop-shadow(0 4px 10px rgba(0, 0, 0, .45)) !important; transform: scale(1.06); }
.brand-btn.portfolio-btn.active { color: var(--purple) !important; text-shadow: 0 0 14px rgba(157, 139, 255, .7); }
:root[data-theme="light"] .brand-btn.logo-only:not(.active), :root[data-theme="light"] .brand-btn.portfolio-btn:not(.active) { opacity: .38; }
:root[data-theme="light"] .brand-btn.logo-only.active, :root[data-theme="light"] .brand-btn.portfolio-btn.active { opacity: 1; filter: none; }
:root[data-theme="light"] .brand-btn.logo-only.active .brand-logo { filter: drop-shadow(0 0 10px rgba(var(--brand-glow, 7, 143, 197), .55)) drop-shadow(0 2px 4px rgba(10, 30, 60, .35)) !important; }
.brand-btn.logo-only .brand-logo { transition: filter .22s ease, transform .22s ease; }

/* --- 18d. PULSE AGENT mark: the live-signal meter ---
   Nine bars rising and falling in place inside a soft cyan halo. The launcher
   in the brand rail and the drawer head share it. */
.qa-fab .qa-fab-orb.has-agent-mark, .qa-head .qa-fab-orb.has-agent-mark { display: grid; place-items: center; width: 48px !important; height: 48px !important; }
.mc-agent-mark { position: relative; display: flex; align-items: center; justify-content: center; gap: 3px; width: 46px; height: 46px; border-radius: 12px; }
.mc-agent-halo { position: absolute; inset: 0; border-radius: 12px; background: radial-gradient(60% 60% at 50% 50%, rgba(0, 229, 255, .28), rgba(0, 229, 255, 0) 72%); animation: mcAgentHalo 3s ease-in-out infinite; }
.mc-agent-mark i { position: relative; width: 3px; height: 26px; border-radius: 3px; transform: scaleY(.22); transform-origin: center; background: linear-gradient(180deg, var(--gold) 0%, var(--cyan) 55%, rgba(0, 229, 255, .35) 100%); box-shadow: 0 0 6px rgba(0, 229, 255, .45); animation: mcAgentBar 1.7s ease-in-out infinite; }
.mc-agent-mark i:nth-child(2), .mc-agent-mark i:nth-child(10) { height: 16px; }
.mc-agent-mark i:nth-child(3), .mc-agent-mark i:nth-child(9) { height: 20px; }
.mc-agent-mark i:nth-child(4), .mc-agent-mark i:nth-child(8) { height: 24px; }
.mc-agent-mark i:nth-child(6) { height: 28px; }
@keyframes mcAgentBar { 0%, 100% { transform: scaleY(.22); opacity: .5; } 50% { transform: scaleY(1); opacity: 1; } }
@keyframes mcAgentHalo { 0%, 100% { opacity: .6; transform: scale(.92); } 50% { opacity: 1; transform: scale(1.06); } }
.qa-fab:hover .mc-agent-mark i { animation-duration: .9s; }
.qa-head .qa-fab-orb.has-agent-mark { width: 36px !important; height: 36px !important; }
.qa-head .mc-agent-mark { width: 34px; height: 34px; gap: 2px; } .qa-head .mc-agent-mark i { width: 2px; }
:root[data-theme="light"] .mc-agent-mark i { background: linear-gradient(180deg, #b8860b 0%, #078fc5 55%, rgba(7, 143, 197, .35) 100%); box-shadow: 0 0 5px rgba(7, 143, 197, .35); }
:root[data-theme="light"] .mc-agent-halo { background: radial-gradient(60% 60% at 50% 50%, rgba(7, 143, 197, .22), rgba(7, 143, 197, 0) 72%); }
:root[data-theme="light"] .qa-fab svg { filter: none; }
@media (prefers-reduced-motion: reduce) { .mc-agent-mark i, .mc-agent-halo { animation: none; transform: none; } }

/* --- 18e. Light theme: one bracket recipe for every shape ---
   Thin (1.5px), short (14px), drawn just OUTSIDE the box edge (3px out) so
   they sit against the shape without touching its own hairline border --
   the way the guide's cards read. Replaces the two earlier recipes (22x2 marks
   painted inside the box on cards; 22x2.5 marks outside on the hub boxes).
   Each shape must have a free pseudo-element and must not clip it: ::before
   on panels and boxes; ::after on KPI cards (their ::before is the brand
   accent line) and on the brief (its ::before is the cyan rail). The cursor
   spotlight that lived on .kpi-card::after is retired -- a frame is worth more
   than a glow that follows the mouse. */
:root[data-theme="light"] {
  /* V20.14.353 -- the light frame is the HUD's bracket, in the slate cyan */
  --mc-frame: var(--mc-bracket);
  --mc-frame-len: 22px;
  --mc-frame-w: 2px;
}
:root[data-theme="light"] .panel, :root[data-theme="light"] .kpi-card, :root[data-theme="light"] .v46-brief, :root[data-theme="light"] .filterbar,
:root[data-theme="light"] .launch-map, :root[data-theme="light"] .section-workspace, :root[data-theme="light"] .application-group,
:root[data-theme="light"] .global-panel, :root[data-theme="light"] .system-map-panel, :root[data-theme="light"] .chart-box,
:root[data-theme="light"] .settings-form, :root[data-theme="light"] .health-banner, :root[data-theme="light"] .launch-map-status {
  position: relative; overflow: visible !important;
  background-image: none !important;
  border-width: 1px !important; border-color: var(--line-strong) !important;
}
/* V20.14.58 -- the three overlays take the same light surface, but NOT the
   `position` and `overflow` above. Each already positions itself (the notice
   and assigned-to-you popovers `absolute` against their header button, the
   agent drawer and the hub's What's New `fixed`), and each already scrolls its
   own content. Forcing `position: relative` dropped the popovers back into the
   header's flex row, where a 350-400px panel shoved every icon to its right
   sideways the moment it opened, and left the agent drawer and What's New
   panel in the document flow in light theme only. Forcing `overflow: visible`
   removed their scrolling. They get no bracket frame either way -- their
   ::before is display:none in section 19b -- so neither declaration ever
   bought them anything. */
:root[data-theme="light"] .qa-drawer, :root[data-theme="light"] .whats-new-panel, :root[data-theme="light"] .pulse-notice-panel {
  background-image: none !important;
  border-width: 1px !important; border-color: var(--line-strong) !important;
}
:root[data-theme="light"] .panel::before, :root[data-theme="light"] .v46-brief::after, :root[data-theme="light"] .kpi-card::after,
:root[data-theme="light"] .filterbar::before,
:root[data-theme="light"] .launch-map::before, :root[data-theme="light"] .section-workspace::before, :root[data-theme="light"] .application-group::before,
:root[data-theme="light"] .global-panel::before, :root[data-theme="light"] .system-map-panel::before, :root[data-theme="light"] .chart-box::before,
:root[data-theme="light"] .settings-form::before, :root[data-theme="light"] .health-banner::before, :root[data-theme="light"] .launch-map-status::before,
:root[data-theme="light"] .qa-drawer::before, :root[data-theme="light"] .whats-new-panel::before, :root[data-theme="light"] .pulse-notice-panel::before {
  content: "" !important; position: absolute !important; inset: -3px !important; z-index: 0; pointer-events: none;
  width: auto !important; height: auto !important; left: -3px !important; right: -3px !important; top: -3px !important; bottom: -3px !important;
  border-radius: 0 !important; opacity: 1 !important; transform: none !important; animation: none !important;
  mask-image: none !important; -webkit-mask-image: none !important; box-shadow: none !important; filter: none !important;
  background:
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)),
    linear-gradient(var(--mc-frame), var(--mc-frame)), linear-gradient(var(--mc-frame), var(--mc-frame)) !important;
  background-repeat: no-repeat !important;
  background-size: var(--mc-frame-len) var(--mc-frame-w), var(--mc-frame-w) var(--mc-frame-len), var(--mc-frame-len) var(--mc-frame-w), var(--mc-frame-w) var(--mc-frame-len), var(--mc-frame-len) var(--mc-frame-w), var(--mc-frame-w) var(--mc-frame-len), var(--mc-frame-len) var(--mc-frame-w), var(--mc-frame-w) var(--mc-frame-len) !important;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100% !important;
}
/* The KPI card's ::after was the mouse spotlight; it is now the frame, so it
   must not fade in and out with hover. */
:root[data-theme="light"] .kpi-card:hover::after { opacity: 1 !important; }
/* The panel's top accent line on the Control Panel lived on ::before; the
   frame takes that slot there too, so the accent moves to a box-shadow. */
:root[data-theme="light"] .cp-sticky-shell ~ * .panel, :root[data-theme="light"] body.control-panel .panel { box-shadow: inset 0 2px 0 rgba(0, 126, 168, .45), 0 12px 32px rgba(20, 50, 90, .10) !important; }
/* Surfaces keep a flat white fill (the brackets used to be part of the
   background image, which is now gone). */
/* V20.14.353 -- the flat fill is the slate panel (#f5f9fc), not white */
:root[data-theme="light"] .panel, :root[data-theme="light"] .kpi-card, :root[data-theme="light"] .v46-brief, :root[data-theme="light"] .filterbar { background-color: var(--bg-panel) !important; }
/* Panels no longer clip (the frame sits outside them). The Stores table can
   no longer widen its panel either: it is table-layout:fixed at 100% since
   pass 14, and its wrap is a scroll container, whose automatic minimum width
   is zero. The both-theme sweep asserts the document never scrolls sideways. */

/* --- 18f. The guide's icon chip, everywhere an icon names a thing ---
   The guide draws each card's icon inside a round tinted chip (conic cyan ->
   gold wash, hairline cyan ring). Panel titles, KPI cards, the hub's section
   tiles and counts, and the Control Panel's tabs now use the same chip, so
   an icon looks the same wherever it appears. The tab rail and filter
   selects keep bare glyphs -- at 15px a chip would swallow them. */
.mc-chip-icon, .ptitle .pcard-icon, .kpi-specific-icon, .section-tab .mc-tab-glyph, .launch-map-status .lms-icon, .mc-cp-tab .hud-icon, .cp-sticky-shell .tabnav button .hud-icon, .rec-icon, .v46-insight .v46-kind-icon {
  display: inline-flex !important; align-items: center; justify-content: center; flex: none;
  border-radius: 50%; color: var(--cyan) !important; opacity: 1 !important;
  background: conic-gradient(from 200deg, rgba(0, 229, 255, .18), rgba(255, 176, 32, .18));
  border: 1px solid rgba(0, 229, 255, .3); box-sizing: border-box;
}
.ptitle .pcard-icon { width: 28px !important; height: 28px !important; margin-right: 4px; }
.ptitle .pcard-icon svg { width: 15px !important; height: 15px !important; }
.kpi-specific-icon { width: 26px !important; height: 26px !important; }
.kpi-specific-icon svg { width: 14px !important; height: 14px !important; }
.section-tab .mc-tab-glyph { width: 30px !important; height: 30px !important; }
.section-tab .mc-tab-glyph svg { width: 16px !important; height: 16px !important; }
.launch-map-status .lms-icon { width: 24px !important; height: 24px !important; }
.launch-map-status .lms-icon svg { width: 13px !important; height: 13px !important; }
.launch-map-status .lms-icon.is-live { color: var(--green) !important; border-color: rgba(52, 211, 153, .35); background: conic-gradient(from 200deg, rgba(52, 211, 153, .2), rgba(0, 229, 255, .14)); }
.launch-map-status .lms-icon.is-pending { color: var(--gold) !important; border-color: rgba(255, 176, 32, .38); background: conic-gradient(from 200deg, rgba(255, 176, 32, .2), rgba(0, 229, 255, .12)); }
.rec-icon { width: 34px !important; height: 34px !important; }
.rec-icon svg { width: 17px !important; height: 17px !important; }
:root[data-theme="light"] .mc-chip-icon, :root[data-theme="light"] .ptitle .pcard-icon, :root[data-theme="light"] .kpi-specific-icon, :root[data-theme="light"] .section-tab .mc-tab-glyph, :root[data-theme="light"] .launch-map-status .lms-icon, :root[data-theme="light"] .rec-icon {
  /* V20.14.353 -- the chip in the slate cyan and gold */
  color: var(--cyan) !important; border-color: var(--cyan-line); background: conic-gradient(from 200deg, rgba(0, 126, 168, .14), rgba(138, 98, 0, .14));
}

/* --- 18g. Control Panel: compact, and dressed like PULSE ---
   Every tab used to open with a 90px "PULSE administration workspace" band
   (kicker, 20px title, sentence, three scope tiles) before any content. It is
   now a single 40px strip. Panels, tiles, tables and toolbars tighten so the
   first screen of every tab shows its content. The header takes the same
   icon rail as the report (34px controls, hairline dividers). */
.cp-guide-context { grid-template-columns: minmax(0, 1fr) auto !important; gap: 12px !important; margin: 0 0 10px !important; padding: 7px 14px !important; border-radius: 8px !important; min-height: 0; }
.cp-guide-context::after { display: none !important; }
.cp-guide-kicker { display: none !important; }
.cp-guide-copy { display: flex; align-items: baseline; gap: 12px; min-width: 0; }
.cp-guide-copy h1 { font-size: 14px !important; letter-spacing: .04em !important; text-transform: uppercase; white-space: nowrap; }
.cp-guide-copy p { margin: 0 !important; font-size: 11px !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cp-guide-scope div { min-width: 0 !important; padding: 3px 10px !important; display: flex; align-items: baseline; gap: 6px; }
.cp-guide-scope span { font-size: 11px !important; }
.cp-guide-scope b { margin-top: 0 !important; font-size: 11px !important; }
.cp-sticky-shell .topbar { padding-top: 8px !important; padding-bottom: 8px !important; }
.cp-sticky-shell .topbar-right { gap: 8px !important; }
.cp-sticky-shell .topbar-right .icon-btn { width: 34px; height: 34px; border-radius: 8px !important; }
.cp-sticky-shell .topbar-right .cp-pulse-link { color: var(--cyan) !important; border-color: var(--cyan-line) !important; background: var(--cyan-soft) !important; }
.cp-sticky-shell .tabnav button { padding: 8px 12px !important; font-size: 11px !important; }
.cp-workspace-body .panel { padding: 12px 14px !important; margin-bottom: 10px !important; }
.cp-workspace-body .panel > h2, .cp-workspace-body .cp-section-title { font-size: 13px !important; margin: 0 0 8px !important; }
.cp-workspace-body .kpi-card, .cp-workspace-body .stat-card, .cp-workspace-body .cp-tile { padding: 9px 12px !important; min-height: 0 !important; }
.cp-workspace-body .kpi-card .kvalue, .cp-workspace-body .stat-value { font-size: 20px !important; }
.cp-workspace-body .kpi-row { gap: 8px !important; margin-bottom: 10px !important; }
.cp-workspace-body table.dtable th, .cp-workspace-body table.dtable td { padding: 5px 8px !important; font-size: 11px !important; }
.cp-workspace-body .toolbar, .cp-workspace-body .cp-command-toolbar { padding: 6px 0 !important; margin: 0 0 8px !important; gap: 6px !important; }
.cp-workspace-body .health-banner { padding: 10px 14px !important; margin-bottom: 10px !important; }
.cp-workspace-body .health-banner b, .cp-workspace-body .health-banner .hb-title { font-size: 13px !important; }
.cp-workspace-body .empty-state { padding: 14px !important; }
.cp-workspace-body .settings-form { padding: 12px 14px !important; }
.cp-workspace-body .settings-form label, .cp-workspace-body .field label { font-size: 11px !important; }
/* V20.14.198 -- "the check box of the employees in control panel looks high and
   old fashion". It was 15px wide and 30px TALL, measured, because this rule
   gave every `input` in the console a 30px minimum height with !important.
   That height is a TEXT FIELD's: it is what stops a one-line input looking
   cramped next to a button. A checkbox is a square, and a minimum height
   applied to one stretches it into a tall rounded-cornered rectangle -- the
   "old fashion" look, which is really just a square control that is no longer
   square.
   A checkbox and a radio opt out. They are sized by v132-access-pills.css,
   which is the file that draws them. */
.cp-workspace-body input:not([type="checkbox"]):not([type="radio"]), .cp-workspace-body select, .cp-workspace-body textarea { min-height: 30px !important; font-size: 11px !important; }
.cp-workspace-body .app-flow-node, .cp-workspace-body .system-node { padding: 10px 12px !important; }
.cp-workspace-body .quick-actions .btn, .cp-workspace-body .btn { padding: 6px 11px !important; font-size: 11px !important; }

/* Release history ledger. */
.release-workspace.rel2 { padding: 0 !important; overflow: visible !important; }
.rel2-bar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.rel2-head { display: flex; align-items: baseline; gap: 10px; margin-right: 6px; }
.rel2-head b { font: 700 14px var(--font-display); color: var(--text-hi); letter-spacing: .02em; }
.rel2-head span { font: 500 11px var(--font-mono); color: var(--text-dim); letter-spacing: .04em; }
.rel2-head strong { color: var(--gold); font-weight: 700; }
.rel2-search { min-height: 32px !important; flex: 1 1 260px; max-width: 420px; }
.rel2-filters { display: flex; gap: 4px; flex-wrap: wrap; }
.rel2-filter { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border: 1px solid var(--line-strong); border-radius: 999px; background: transparent; color: var(--text-mid); font: 700 11px var(--font-mono); letter-spacing: .08em; text-transform: uppercase; cursor: pointer; }
.rel2-filter:hover { color: var(--text-hi); border-color: var(--cyan-line); }
.rel2-filter.active { color: var(--cyan); border-color: var(--cyan); background: var(--cyan-soft); }
.rel2 .release-count { margin-left: auto; }
.rel2-lines { display: grid; gap: 8px; padding: 10px 14px 14px; }
.rel2-line { border: 1px solid var(--line-strong); border-radius: 8px; background: var(--mc-glass); overflow: hidden; }
.rel2-line > summary { display: grid; grid-template-columns: auto minmax(0, 1fr) auto 18px; align-items: center; gap: 12px; padding: 8px 12px; list-style: none; cursor: pointer; background: linear-gradient(90deg, var(--cyan-soft), transparent 55%); }
.rel2-line > summary::-webkit-details-marker { display: none; }
.rel2-line-name { font: 700 11px var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--cyan); }
.rel2-line-meta { font: 500 11px var(--font-mono); color: var(--text-dim); letter-spacing: .03em; }
.rel2-line-dots, .rel2-sig { display: inline-flex; gap: 4px; align-items: center; }
/* V20.14.194 -- two rows on a phone, not four desktop columns squeezed.
   ("the release-history summary grid compresses metadata into columns measured
   at approximately 132 / 50 / 29 / 18 px", deferred out of V20.14.193.)

   The four columns are a series name, a release range, a row of signal dots and
   a chevron -- fine side by side at 1200px, and at 390 the range wraps into a
   tall stack while the name is truncated. The pairing that survives the fold is
   name-with-chevron on one line and range-with-dots on the next: the two things
   you identify the group by, then the two you scan it by. Named areas rather
   than source order, so the markup is untouched and assistive tech still reads
   name, range, dots, control. */
@media (max-width: 760px) {
  .rel2-line > summary {
    /* `auto` rather than 18px: the second column holds the chevron on row one
       and the signal dots on row two, so it has to be as wide as the wider of
       the two. Pinned to the chevron's width it squeezed the dots into 18px,
       which is the same mistake in a smaller box. */
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name chev" "meta dots";
    gap: 3px 10px; padding: 9px 12px 10px;
  }
  .rel2-line-name { grid-area: name; }
  .rel2-chev { grid-area: chev; align-self: start; margin-top: 3px; }
  .rel2-line-meta { grid-area: meta; }
  .rel2-line-dots { grid-area: dots; justify-content: flex-end; }
  .rel2-lines { padding: 8px 10px 12px; }
}
.rel2-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; background: var(--text-dim); box-shadow: 0 0 6px currentColor; }
.rel2-dot.tone-green { background: var(--green); color: var(--green); } .rel2-dot.tone-gold { background: var(--gold); color: var(--gold); }
.rel2-dot.tone-cyan { background: var(--cyan); color: var(--cyan); } .rel2-dot.tone-purple { background: var(--purple); color: var(--purple); }
.rel2-dot.tone-pink { background: #f472b6; color: #f472b6; } .rel2-dot.tone-dim { background: var(--text-dim); box-shadow: none; }
.rel2-chev { width: 7px; height: 7px; border-right: 1.5px solid var(--cyan); border-bottom: 1.5px solid var(--cyan); transform: rotate(45deg); justify-self: center; transition: transform .16s ease; }
.rel2-line[open] > summary .rel2-chev, .rel2-row[aria-expanded="true"] .rel2-chev { transform: rotate(-135deg); }
.rel2-rows { border-top: 1px solid var(--line); }
.rel2-item + .rel2-item { border-top: 1px solid var(--line); }
.rel2-row { display: grid; grid-template-columns: 138px minmax(160px, .9fr) minmax(0, 1.4fr) auto 18px; align-items: center; gap: 12px; width: 100%; min-height: 36px; padding: 6px 12px; border: 0; background: transparent; color: inherit; text-align: left; cursor: pointer; font: inherit; }
.rel2-row:hover, .rel2-item.is-open .rel2-row { background: var(--bg-hover); }
.rel2-ver { display: inline-flex; align-items: center; gap: 6px; font: 700 11px var(--font-mono); color: var(--gold); letter-spacing: .02em; white-space: nowrap; }
.rel2-ver em { font: 700 11px var(--font-mono); font-style: normal; letter-spacing: .08em; text-transform: uppercase; color: var(--green); padding: 2px 5px; border-radius: 999px; background: var(--green-soft); }
.rel2-title { font: 600 11.5px var(--font-body); color: var(--text-hi); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rel2-sum { text-align: left; font: 400 11px var(--font-body); color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rel2-item.is-current .rel2-row { box-shadow: inset 3px 0 0 var(--green); }
.rel2-body { padding: 4px 14px 14px 150px; background: linear-gradient(90deg, var(--cyan-soft), transparent 60%); }
.rel2-notes { columns: 2; column-gap: 28px; font-size: 11px; line-height: 1.55; color: var(--text-mid); }
.rel2-notes h1, .rel2-notes h2 { column-span: all; color: var(--text-hi); font: 700 12px var(--font-display); margin: 8px 0 4px; }
.rel2-notes ul, .rel2-notes ol { margin: 4px 0; padding-left: 16px; } .rel2-notes li { break-inside: avoid; margin-bottom: 3px; }
.rel2-notes p { margin: 4px 0; }
/* V20.14.131 -- the tags the note renderer can now emit. `###` and `----` used
   to arrive as literal text; they arrive as markup now, so they need somewhere
   to land. h3/h4 deliberately do NOT span the columns the way h1/h2 do: a
   subheading every few paragraphs that breaks the two-column flow turns a tidy
   ledger into a staircase. */
.rel2-notes h3, .rel2-notes h4 { color: var(--text-hi); font: 700 11px var(--font-display); letter-spacing: .02em; margin: 7px 0 3px; break-after: avoid; break-inside: avoid; }
.rel2-notes h4 { font-size: 11px; color: var(--text-mid); }
.rel2-notes hr { column-span: all; height: 0; margin: 9px 0; border: 0; border-top: 1px solid var(--line); }
.rel2-notes blockquote { margin: 5px 0; padding: 4px 10px; border-left: 2px solid var(--cyan); background: var(--bg-panel-hi); color: var(--text-mid); break-inside: avoid; }
.rel2-notes pre.rel2-pre { break-inside: avoid; margin: 6px 0; padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--bg-panel-hi); overflow-x: auto; }
.rel2-notes pre.rel2-pre code { padding: 0; background: none; white-space: pre; font-size: 11px; line-height: 1.5; }
.rel2-notes code { padding: 1px 4px; border-radius: 4px; background: var(--bg-panel-hi); color: var(--text-hi); font: 11px/1.4 var(--font-mono, monospace); overflow-wrap: anywhere; }
@media (max-width: 1000px) { .rel2-row { grid-template-columns: 128px minmax(0, 1fr) auto 18px; } .rel2-sum { display: none; } .rel2-notes { columns: 1; } .rel2-body { padding-left: 14px; } }
:root[data-theme="light"] .rel2-line { background: #fbfdff; }
:root[data-theme="light"] .rel2-title { color: #10294a; }

/* --- 18h. Hub: the profile button is one of the icons, not a tile ---
   It was 58px to its neighbours' 40px. Same box now; the photo fills it. */
.hub-profile-button { width: 40px !important; height: 40px !important; border-radius: 8px !important; }
.hub-profile-button img, .hub-profile-button .hub-profile-photo { width: 100% !important; height: 100% !important; border-radius: 7px !important; object-fit: cover; }
.hub-profile-button svg { width: 18px; height: 18px; }
.hub-title { text-transform: uppercase; letter-spacing: .06em; }
/* Application flow: with fourteen applications the middle column is tall and
   the identity / portal / observability nodes were centred against it, out of
   view at the top of the panel. Anchor the flow to the top and tile the
   applications three across, so the whole map reads in one screen. */
@media (min-width: 900px) {
  .system-flow { align-items: start !important; min-height: 0 !important; }
  .system-flow .system-stage, .system-flow .system-connector { margin-top: 44px; }
  .system-apps { grid-template-columns: repeat(3, minmax(120px, 1fr)) !important; gap: 8px !important; }
  .system-node { min-height: 0 !important; padding: 9px 11px !important; }
}
/* Header dropdowns (notifications, profile) must overlay the brand rail,
   filter deck and tab rail beneath them. Those rows share the topbar's
   z-index inside the frozen deck, and a later sibling at the same level
   paints on top -- so the panel was sliding under the equaliser and the
   RESET button. The topbar sits one step above its sibling rows. */
.pulse-sticky-header .topbar { z-index: 710 !important; }
.pulse-notice-panel, .profile-dropdown { z-index: 1210 !important; }

/* ============================================================
   19. PASS 16 (7 Sep 2026) -- the discipline pass
   ============================================================ */

/* --- 19a. Animation budget ---
   Kept: the telemetry meter and the agent mark (the same meter), the
   exception pulse, the session LED, the hub's own mark, and anything that
   only moves on an event (hover, theme switch, tab change). Retired: the
   ambient spotlight drift, the header sweep, the travelling light on hub
   tiles, the rail shine, the WHAT-IF conic border, the KPI glows. */
.mc-spotlight::before { animation: none !important; transform: none !important; }
.header-scan { display: none !important; }
:root[data-theme="light"] .section-tab::after, :root[data-theme="light"] .route-report-node::after { animation: none !important; display: none !important; }
:root[data-theme="light"] body > .topbar::after, :root[data-theme="light"] .pulse-sticky-header::after, :root[data-theme="light"] .cp-sticky-shell::after { animation: none !important; }
.v21-scenario-btn::before, .v21-scenario-btn::after, .v21-scenario-pulse::before, .v21-scenario-pulse::after { animation: none !important; }
.v21-suggest-btn { animation: none !important; box-shadow: none !important; }
/* Measured on the Overview (visible, infinite animations only): 42 before
   this block, 33 after. What goes: the chart aura that pulsed behind every
   chart, the suggest-button glow, the agent button's scan sweep, and the
   WHAT-IF blip. What stays: the meter (15 bars), the agent mark (9 bars +
   halo + orbit), the session LED, the live ping, the exception pulse and
   the map focus ring, which only runs while a callout is focused. */
.chart::after { animation: none !important; }
.v21-suggest-btn::after, #v21SuggestBtn::after, .icon-btn.suggest-btn::after { animation: none !important; box-shadow: none !important; }
.qa-fab::before { animation: none !important; }
.v21-scenario-dot, .v21-scenario-blip { animation: none !important; }
/* Light theme: pulse-light-orbit.css animated the border colour and box
   shadow of every chart box and agent panel on a 9-11s loop (a box-shadow
   animation repaints the whole element every frame). Retired -- but retired
   HERE, by writing `animation: none !important` on the elements themselves,
   which is a different statement from "the edge signal is retired". It says
   these elements may never animate at all, and it said it with !important.
   V20.14.166 then gave the KPI cards an arrival animation and the light theme
   threw it away without a trace: "KPI cards are not animating and floating in
   light theme".
   V20.14.172 removes the signal at the three places it was DECLARED, in
   pulse-light-orbit.css, so there is nothing left here to suppress and the
   `animation` property has one owner per element again. The resting colours are
   unchanged -- the keyframe's first frame was already the resting rule. */
.kpi-card .kvalue, .kpi-card.tone-pos .kvalue, .kpi-card.tone-neg .kvalue, .launch-map-status b, .launch-map-head span, .route-category-head span, .login-eyebrow, .login-headline .accent, .clock .live, .mc-tel-brand, .v46-brief-kicker, #tabNav .tab-btn.active { text-shadow: none !important; }
#tabNav .tab-btn.active .mc-tab-icon { filter: none !important; }
.mc-tel-brand .hud-icon, .mc-tel-logo { filter: none !important; }

/* --- 19b. Brackets on the outer frames only ---
   Panels and the hub's boxes keep their frame. KPI cards, the brief, the
   filter deck, application groups, the counts box, the drawers and the
   notification panel lose theirs -- on those the marks were noise. Both
   themes; the dark theme's inside marks follow the same rule. */
.kpi-card, .v46-brief, .mc-hud, .login-card { background-image: none !important; }
:root[data-theme="light"] .kpi-card::after, :root[data-theme="light"] .v46-brief::after, :root[data-theme="light"] .filterbar::before,
:root[data-theme="light"] .application-group::before, :root[data-theme="light"] .launch-map-status::before, :root[data-theme="light"] .chart-box::before,
:root[data-theme="light"] .settings-form::before, :root[data-theme="light"] .health-banner::before,
:root[data-theme="light"] .qa-drawer::before, :root[data-theme="light"] .whats-new-panel::before, :root[data-theme="light"] .pulse-notice-panel::before { display: none !important; }
:root[data-theme="light"] .application-group { background-image: none !important; }
.application-group { background-image: none !important; }

/* --- 19c. Typography ---
   11px floor (tokens), monospace reserved for numbers, kickers in the
   display face with wide tracking. The classes below are every recurring
   label, kicker and control caption in the portal. Numbers -- KPI values,
   table figures, the clocks -- keep IBM Plex Mono. */
.klabel, .kpi-card .klabel, .flabel, .filterbar .flabel, .v46-brief-label, .v46-brief-kicker, .v46-kind, .v46-sev, .v46-basis, .v46-conf, .v46-brief-label em,
#tabNav .tab-btn, .segmented-option, .v20-control, .filter-share, .filter-reset, .v21-btn, .v38-context-action, .kpi-drill, .kpi-window, .v46-followup, .v46-act, .v46-more,
.mc-tel-item span, .mc-tel-page, .mc-tel-brand, .mc-tel-page small,
.hub-title-row::before, .section-tab small, .section-tab em, .application-group-name, .application-group-count, .route-report-node > div > span, .route-report-node i, .launch-map-status span, .launch-map-head span, .route-category-head span, .section-application > div > span,
.cp-guide-scope span, .cp-guide-scope b, .rel2-line-name, .rel2-line-meta, .rel2-filter, .rel2-ver em, .release-count, .cp-sticky-shell .tabnav button,
.store-table th, .store-table th .sort-button, .status-chip, .store-stat, .store-method-note, .plan-header-sub, .rec-num,
.qa-options > summary, .qa-mode-btn, .qa-head-btn, .pulse-notice-head, .pulse-notice-item small, .v20-term, .v21-scenario-scope, .v21-scenario-section-title, .v21-scenario-control small, .v21-scenario-metric span,
.landing-section-index, .landing-signal, .guide-digest-note, .mc-gateway span, .hub-foot, .foot, .whats-new-eyebrow {
  font-family: var(--font-display) !important; font-size: 11px !important; letter-spacing: .08em !important;
}
.kpi-card .kvalue, .kdelta b, .store-table td.num, .dtable td.num, .mc-tel-item b, #mcTelKsa, .launch-map-status b, .cp-guide-scope b, .rel2-ver, .v46-sr-big, .v21-sr-big, .v21-scenario-value, .v21-scenario-metric b, .store-stat b, .kpi-card .ksub, .v46-pri-text small { font-family: var(--font-mono) !important; }
.kpi-card .ksub { font-size: 11px !important; letter-spacing: 0 !important; }
.section-tab small, .section-application > div > span, .route-report-node > div > span { letter-spacing: .06em !important; }
.psub, .kpi-foot .ksub, .v46-insight-body, .v46-brief-headline, .store-method-note { font-size: 11.5px !important; }
.mc-telemetry { font-size: 11px !important; }
.store-table { font-size: 11px !important; }
.store-table th, .store-table th .sort-button { font-size: 11px !important; letter-spacing: .04em !important; }
.status-chip { letter-spacing: .04em !important; }

/* --- 19d. Light theme depth --- (page tint from tokens; panels stay white) */
:root[data-theme="light"] .panel, :root[data-theme="light"] .kpi-card, :root[data-theme="light"] .v46-brief, :root[data-theme="light"] .filterbar, :root[data-theme="light"] .launch-map, :root[data-theme="light"] .section-workspace { background-color: var(--bg-panel) !important; box-shadow: 0 1px 2px rgba(20, 50, 90, .06), 0 8px 24px rgba(20, 50, 90, .06) !important; }
:root[data-theme="light"] .pulse-sticky-header { background: linear-gradient(180deg, #ffffff, #f7fafd) !important; }

/* --- 19e. Condensed deck ---
   The full deck (title, toggles, brand rail, filters, tabs) is shown at the
   top of the page. Once the reader has scrolled into the report the brand
   rail and filter deck fold away and a one-line summary takes their place
   beside the tabs, so the frozen area drops from ~320px to ~150px. The
   summary states the brand and the active filters; clicking it scrolls back
   to the top, where the full controls are. Applied by a scroll listener in
   dashboard.js with hysteresis so it never flickers at the threshold. */
.pulse-sticky-header.is-condensed .brand-switcher, .pulse-sticky-header.is-condensed .filterbar { display: none !important; }
.pulse-sticky-header .deck-summary { display: none; }
.pulse-sticky-header.is-condensed .deck-summary { display: flex; align-items: center; gap: 10px; margin: 6px 0 0; padding: 6px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--mc-glass); font-family: var(--font-display); font-size: 11px; letter-spacing: .06em; color: var(--text-mid); cursor: pointer; }
.pulse-sticky-header.is-condensed .deck-summary b { color: var(--text-hi); letter-spacing: .08em; text-transform: uppercase; }
.pulse-sticky-header.is-condensed .deck-summary .deck-summary-filters { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.pulse-sticky-header.is-condensed .deck-summary .deck-summary-filters span { padding: 2px 8px; border: 1px solid var(--cyan-line); border-radius: 999px; color: var(--cyan); background: var(--cyan-soft); }
.pulse-sticky-header.is-condensed .deck-summary .deck-summary-open { margin-left: auto; color: var(--cyan); }
:root[data-theme="light"] .pulse-sticky-header.is-condensed .deck-summary { background: #ffffff; }
.pulse-sticky-header.is-condensed .tabnav { margin-top: 6px !important; }

/* --- 19f. Mobile mode ---
   Under 760px the deck is a compact bar: title, then the tabs as a scrolling
   strip; the brand rail and filters live behind a FILTERS button and open as
   a sheet. The KPI row is two-up, panels stack. */
@media (max-width: 760px) {
  .pulse-sticky-header { padding: 0 12px 6px !important; }
  .pulse-sticky-header .topbar { flex-wrap: wrap; gap: 8px; }
  .brandmark h1 { font-size: 15px !important; }
  .brandmark .report-mark { width: 36px !important; height: 36px !important; }
  .topbar-controls { flex-wrap: wrap; gap: 6px !important; }
  .header-icon-group { border-left: 0; padding-left: 0; }
  .clock { display: none !important; }
  .header-logo { display: none !important; }
  .topbar-right, .topbar-controls { width: 100%; }
  .header-icon-group { width: 100%; flex-wrap: wrap; gap: 6px !important; }
  /* WHAT-IF and ADMIN are icon-only on phones: their words cost a whole row
     of a 390px header. The buttons keep their aria-labels and title text, so
     nothing is lost to a screen reader or a long press. */
  .v21-btn-label { display: none !important; }
  .v21-scenario-btn svg, .v21-admin-btn svg { margin-right: 0 !important; }
  /* With the words gone, all nine header controls fit one row at 390px if
     they are the same square and the gaps tighten: 9 x 32 + 8 x 4 = 320
     inside a 338px group. Measured, not assumed -- at the previous 34-41px
     mixed widths the row wrapped and the header kept the height the labels
     had cost. */
  .header-icon-group { gap: 4px !important; }
  .header-icon-group > * { width: 32px !important; min-width: 32px !important; height: 32px !important; flex: 0 0 32px !important; }
  .header-icon-group > button, .header-icon-group > a, .header-icon-group > * > button, .header-icon-group > * > a { width: 32px !important; min-width: 32px !important; height: 32px !important; padding: 0 !important; justify-content: center !important; }
  .pulse-sticky-header .brand-switcher, .pulse-sticky-header .filterbar { display: none !important; }
  .pulse-sticky-header.is-mobile-open .brand-switcher, .pulse-sticky-header.is-mobile-open .filterbar { display: flex !important; flex-wrap: wrap !important; }
  .pulse-sticky-header .deck-mobile-toggle { display: inline-flex; align-items: center; gap: 8px; margin: 6px 0 0; padding: 7px 12px; border: 1px solid var(--cyan-line); border-radius: 8px; background: var(--cyan-soft); color: var(--cyan); font: 700 11px var(--font-display); letter-spacing: .08em; text-transform: uppercase; cursor: pointer; }
  .pulse-sticky-header .tabnav { overflow-x: auto; scrollbar-width: none; }
  .pulse-sticky-header .tabnav::-webkit-scrollbar { display: none; }
  #tabNav .tab-btn { padding: 7px 10px !important; }
  .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .kpi-card { overflow: hidden; min-width: 0; }
  .kpi-card .ksub, .kpi-card .kdelta { white-space: normal !important; overflow-wrap: anywhere; }
  .pulse-sticky-header.is-mobile-open .brand-switcher { overflow: visible !important; padding-right: 64px !important; }
  .pulse-sticky-header.is-mobile-open .brand-switcher .qa-fab { position: absolute !important; right: 8px; top: 8px; margin-left: 0; }
  .pulse-sticky-header.is-mobile-open .brand-switcher { position: relative; }
  .panel-grid { grid-template-columns: 1fr !important; }
  .pulse-sticky-header .deck-summary { display: none !important; }
}
@media (min-width: 761px) { .pulse-sticky-header .deck-mobile-toggle { display: none !important; } }

/* --- 19g. Pass-16 feature surfaces ---
   Run-rate landing strip and month notes (Overview), value lens (Overview),
   custom period comparison (Volume), store 360 (Stores). Same grammar as
   the rest of the report: 11px display labels, mono numbers, one accent. */
.rr-landing { display: flex; flex-wrap: wrap; gap: 10px 22px; align-items: flex-start; margin: 6px 0 4px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--mc-glass); }
.rr-landing-item { display: flex; flex-direction: column; gap: 2px; min-width: 120px; }
.rr-landing-item i { font: 700 11px var(--font-display); letter-spacing: .08em; color: var(--text-dim); font-style: normal; }
.rr-landing-item b { font: 700 18px var(--font-mono); color: var(--text-hi); line-height: 1.1; }
.rr-landing-item small { font-size: 11px; color: var(--text-mid); }
.rr-landing-note { flex: 1 1 260px; min-width: 200px; justify-content: flex-end; }
.rr-landing-note small { color: var(--text-dim); line-height: 1.4; }
.rr-notes { margin-top: 8px; }
.rr-notes-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.rr-notes-toggle { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: transparent; color: var(--text-mid); font: 700 11px var(--font-display); letter-spacing: .08em; cursor: pointer; }
.rr-notes-toggle:hover { color: var(--text-hi); border-color: var(--cyan-line); }
.rr-notes-count:not(:empty) { padding: 1px 7px; border-radius: 999px; background: var(--gold-soft, rgba(255, 201, 60, .16)); color: var(--gold); font-family: var(--font-mono); }
.rr-notes-form { display: flex; flex: 1 1 420px; gap: 6px; align-items: center; }
.rr-notes-form select { max-width: 110px; }
.rr-notes-form input { flex: 1 1 200px; min-width: 120px; padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-panel); color: var(--text-hi); font-family: var(--font-body); font-size: 12px; }
.rr-notes-form input:focus { outline: none; border-color: var(--cyan); }
.rr-notes-list { display: none; margin-top: 8px; border-top: 1px solid var(--line); }
.rr-notes.is-open .rr-notes-list { display: block; }
.rr-note { display: grid; grid-template-columns: 64px 1fr auto auto; gap: 10px; align-items: center; padding: 7px 4px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--text-mid); }
.rr-note-month { font: 700 11px var(--font-mono); color: var(--gold); letter-spacing: .04em; }
.rr-note-text { color: var(--text-hi); }
.rr-note-meta { font-size: 11px; color: var(--text-dim); white-space: nowrap; }
.rr-note-del { border: 0; background: none; color: var(--red); cursor: pointer; font-size: 12px; padding: 2px 6px; }
.rr-note-empty { grid-template-columns: 1fr; color: var(--text-dim); }
/* V20.14.76 -- the stat strip above a chart is a caption for the chart, and   a caption that starts hard against the left edge of a centred panel reads   as a stray line of text. Centred as a group, with the trailing note   dropping to its own centred line rather than being pushed to the far   right where nothing else is. */
.value-lens { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; text-align: center; gap: 8px 28px; margin: 0 auto 14px; padding: 10px 18px; border: 1px solid var(--line); border-radius: 10px; background: var(--mc-glass); }
.value-lens-kicker { align-items: center; }
.value-lens-item { align-items: center; }
.value-lens-kicker { display: flex; flex-direction: column; font: 700 11px var(--font-display); letter-spacing: .1em; color: var(--cyan); }
.value-lens-kicker small { font-size: 11px; letter-spacing: .04em; color: var(--text-dim); font-weight: 500; }
.value-lens-item { display: flex; flex-direction: column; gap: 2px; }
.value-lens-item i { font: 700 11px var(--font-display); letter-spacing: .08em; color: var(--text-dim); font-style: normal; }
.value-lens-item b { font: 700 18px var(--font-mono); color: var(--text-hi); line-height: 1.1; }
.value-lens-note { flex: 1 1 100%; font-size: 11px; color: var(--text-dim); line-height: 1.4; text-align: center; }
/* V20.14.78 -- the excise basis switch. Sits above everything it governs, and
   stays visible even when the snapshot cannot answer the second lens: hiding it
   would leave no way to discover that the figures on screen are one of two
   possible readings of the same sale. */
.value-lens-switch { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 14px; padding: 9px 14px; border: 1px solid var(--cyan-line); border-radius: 10px; background: var(--cyan-soft); }
.value-lens-switch-label { font: 700 11px var(--font-mono); letter-spacing: .12em; color: var(--text-dim); }
/* V20.14.79 -- this is a SEGMENTED CONTROL, not a primary button.
   It was styled as one: the selected side took --cyan as a solid fill with
   --btn-primary-text on top. In the light theme --cyan is #006e98, so choosing
   a basis dropped a heavy dark slab into the middle of a pale strip -- legible,
   but it read as something switching off rather than on, which is what
   "looks dark once press" was describing.
   A segmented control says "selected" by LIFTING the chosen side out of the
   track: a raised surface, the accent as the text and the ring, a dot in front
   of the live one. That reads as chosen in both themes and never inverts the
   page's own light/dark relationship. */
.value-lens-btn { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line-strong); background: transparent; color: var(--text-mid); border-radius: var(--radius-pill); font: 700 11px var(--font-mono); letter-spacing: .08em; padding: 5px 12px; cursor: pointer; transition: color .14s ease, border-color .14s ease, background-color .14s ease, box-shadow .14s ease; }
/* The state dot: hollow when the basis is available but not chosen, filled and
   glowing when it is live. It is the fastest read in the control, and it keeps
   the selected state legible for anyone who cannot separate the two greys. */
.value-lens-btn::before { content: ""; width: 6px; height: 6px; border-radius: 50%; border: 1.5px solid currentColor; background: transparent; flex: none; }
.value-lens-btn:hover:not(:disabled) { color: var(--cyan); border-color: var(--cyan); background: var(--bg-hover); }
.value-lens-btn.active {
  background: var(--bg-panel-hi);
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: 0 0 0 1px var(--cyan) inset, 0 1px 3px rgba(0, 0, 0, .18);
}
.value-lens-btn.active::before { background: currentColor; box-shadow: var(--glow-cyan); }
.value-lens-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.value-lens-btn:disabled, .value-lens-btn.is-unavailable { opacity: .45; cursor: not-allowed; }
.value-lens-btn:disabled::before, .value-lens-btn.is-unavailable::before { border-style: dashed; }
.value-lens-switch-note { flex: 1 1 220px; font: 400 11px var(--font-body); color: var(--text-dim); line-height: 1.4; }
@media (prefers-reduced-motion: reduce) { .value-lens-btn { transition: none; } }
/* The basis, printed under the column head it governs, so a copied table is
   unambiguous on its own. */
.vtable th small, .value-table th small { display: block; margin-top: 2px; font: 500 11px var(--font-mono); letter-spacing: .07em; color: var(--text-dim); text-transform: none; }
.value-lens.is-filtered .value-lens-item b { opacity: .8; }
:root[data-theme="light"] .rr-landing, :root[data-theme="light"] .value-lens { background: #ffffff; }
.pc-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 4px 0 10px; }
.pc-group { display: inline-flex; align-items: center; gap: 6px; }
.pc-tag { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 6px; font: 700 11px var(--font-mono); font-style: normal; }
.pc-tag-a { background: var(--cyan-soft); color: var(--cyan); border: 1px solid var(--cyan-line); }
.pc-tag-b { background: var(--mc-glass); color: var(--text-mid); border: 1px solid var(--line); }
.pc-to { font: 700 11px var(--font-display); letter-spacing: .08em; color: var(--text-dim); }
.pc-presets { display: inline-flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }
.pc-preset { padding: 6px 10px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--text-mid); font: 700 11px var(--font-display); letter-spacing: .06em; cursor: pointer; }
.pc-preset:hover { color: var(--cyan); border-color: var(--cyan-line); }
.pc-summary { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 0 0 6px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--mc-glass); }
:root[data-theme="light"] .pc-summary { background: #ffffff; }
.pc-stat { display: flex; flex-direction: column; gap: 2px; min-width: 150px; }
.pc-stat i { font: 700 11px var(--font-display); letter-spacing: .08em; color: var(--text-dim); font-style: normal; }
.pc-stat b { font: 700 18px var(--font-mono); color: var(--text-hi); line-height: 1.1; }
.pc-stat small { font-size: 11px; color: var(--text-mid); }
.pc-stat.good b { color: var(--green); }
.pc-stat.alert b { color: var(--red); }
.store-table tr.store-row { cursor: pointer; }
.store-table tr.store-row:hover td { background: var(--cyan-soft); }
.store-table tr.store-row:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }
.store360-backdrop { position: fixed; inset: 0; z-index: 1250; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(6, 12, 22, .62); }
.store360 { width: min(880px, 100%); max-height: 90vh; overflow: auto; padding: 20px 22px 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--bg-panel); box-shadow: 0 24px 60px rgba(0, 0, 0, .5); }
:root[data-theme="light"] .store360 { background: #ffffff; }
.s360-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
.s360-kicker { font: 700 11px var(--font-display); letter-spacing: .1em; color: var(--text-dim); }
.s360-head h2 { margin: 4px 0 4px; font: 700 18px var(--font-display); letter-spacing: .02em; color: var(--text-hi); }
.s360-ids { font-size: 12px; color: var(--text-mid); }
.s360-ids b { font-family: var(--font-mono); color: var(--text-hi); }
.s360-chips { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.s360-close { width: 30px; height: 30px; border: 1px solid var(--line); border-radius: 8px; background: transparent; color: var(--text-mid); cursor: pointer; font-size: 14px; }
.s360-close:hover { color: var(--text-hi); border-color: var(--cyan-line); }
.s360-path { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 10px 0 12px; font: 700 11px var(--font-display); letter-spacing: .06em; color: var(--text-mid); }
.s360-path span { padding: 3px 9px; border: 1px solid var(--line); border-radius: 999px; }
.s360-path i { color: var(--text-dim); font-style: normal; }
.s360-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; margin-bottom: 12px; }
.s360-fact { padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--mc-glass); }
.s360-fact i { display: block; font: 700 11px var(--font-display); letter-spacing: .08em; color: var(--text-dim); font-style: normal; margin-bottom: 3px; }
.s360-fact b { font: 700 16px var(--font-mono); color: var(--text-hi); }
.s360-fact b.negative-value { color: var(--red); }
.s360-chart-head .ptitle { margin-top: 4px; }
@media (max-width: 760px) {
  .rr-note { grid-template-columns: 56px 1fr; }
  .rr-note-meta { grid-column: 2; }
  .value-lens-note { text-align: center; }
  .pc-presets { margin-left: 0; }
  .store360 { padding: 14px; }
}

/* --- 20. Pre-deployment contrast pass ---
   Measured from rendered pixels, not eyeballed. The light accents were nudged
   one step in the token block above; these are the shapes that needed their
   own rule.

   The branch-map callout labels were 8.5-9.5px in a dim tone on a light card:
   below this portal's own 11px type floor AND below WCAG AA. Both are the same
   fix. The active segmented toggle carried near-black text on the cyan fill,
   which the darkened cyan pushed under AA -- white on that fill reads 5.7:1. */
.v21-map-callout-grid span { font-size: 11px !important; }
.v21-map-callout-grid strong { font-size: 11px !important; }
.v21-map-callout .v21-map-gain { font-size: 11px !important; }
/* Light theme only. The dark theme's active fill is the bright cyan (#00e5ff),
   which needs DARK text -- forcing white there took a 4.2:1 pairing down to
   1.54:1, a worse result than the problem being fixed. */
:root[data-theme="light"] .segmented-option.active,
:root[data-theme="light"] .v21-toggle-group button.active { color: #ffffff !important; }

/* --- 21. One frame in both themes ---
   The two themes had drifted apart. Dark draws a 22x2px mark at each corner,
   sitting on the box edge, over a border so soft it reads as the frame's own
   shadow. Light drew 14x1.5px marks 3px OUTSIDE the box, on top of a much
   firmer border -- so a light panel read as "a bordered box with small marks"
   while a dark one read as "a bracketed frame". Same geometry now; switching
   theme changes the colour and nothing else. */
:root[data-theme="light"] {
  --mc-frame-len: 22px;
  --mc-frame-w: 2px;
}
:root[data-theme="light"] .panel::before, :root[data-theme="light"] .v46-brief::after, :root[data-theme="light"] .kpi-card::after,
:root[data-theme="light"] .filterbar::before,
:root[data-theme="light"] .launch-map::before, :root[data-theme="light"] .section-workspace::before, :root[data-theme="light"] .application-group::before,
:root[data-theme="light"] .global-panel::before, :root[data-theme="light"] .system-map-panel::before, :root[data-theme="light"] .chart-box::before,
:root[data-theme="light"] .settings-form::before, :root[data-theme="light"] .health-banner::before, :root[data-theme="light"] .launch-map-status::before,
:root[data-theme="light"] .qa-drawer::before, :root[data-theme="light"] .whats-new-panel::before, :root[data-theme="light"] .pulse-notice-panel::before {
  /* On the box edge, exactly as dark, rather than floating 3px off it. */
  inset: 0 !important; left: 0 !important; right: 0 !important; top: 0 !important; bottom: 0 !important;
}
/* The border steps back so the corners carry the frame. Dark's is
   rgba(0,229,255,.16); this is the same weight in the light accent. */
:root[data-theme="light"] .panel, :root[data-theme="light"] .kpi-card, :root[data-theme="light"] .v46-brief, :root[data-theme="light"] .filterbar,
:root[data-theme="light"] .launch-map, :root[data-theme="light"] .section-workspace, :root[data-theme="light"] .application-group,
:root[data-theme="light"] .global-panel, :root[data-theme="light"] .system-map-panel, :root[data-theme="light"] .chart-box,
:root[data-theme="light"] .settings-form, :root[data-theme="light"] .launch-map-status {
  /* V20.14.353 -- the HUD's soft line, in the slate cyan */
  border-color: var(--line) !important;
}
/* Same comparison, second difference: light drew the plot area itself as a
   rounded, tinted, inner-shadowed card sitting inside the panel, while dark
   draws the plot straight onto the panel. Two nested boxes where dark has one
   is most of why the light panel reads as busier. The plot ground is flattened
   to match; the panel keeps its own surface, the chart no longer has a second
   one. Composite charts (.chart-box) are untouched -- those are a different
   component with their own frame. */
:root[data-theme="light"] .chart, :root[data-theme="light"] [id^="c-"], :root[data-theme="light"] #apmChart {
  background: none !important;
  box-shadow: none !important;
  border-color: transparent !important;
  outline: none !important;
}

/* --- 22. LIVE DATASET: the dot back inside the pill ---
   The dot is positioned absolutely at left:0 with the base rule reserving
   16px of padding-left for it. Pass 15 (section 18a above) re-declared the
   pill's padding as `0 11px`, which took that reservation away: the dot then
   sat ON the left border with the label pushed hard against it, and 14px of
   empty pill to the right of the text -- the whole content visibly off-centre.
   Putting the dot back in flow lets the pill's own flex gap space it, and the
   content sits where the padding says it should. The ::after ping still needs
   a positioned ancestor, hence relative rather than static. */
.clock .live { padding: 0 10px 0 11px !important; }
.live-dot { position: relative !important; left: auto !important; flex: none; }

/* --- 23. Filter applied / reset: the confirmation line is back ---
   The sweep under the filter bar is drawn on .filterbar::after. Section 18b
   above put `display:none !important` on that same pseudo-element to kill an
   unrelated flex row-break, and took the confirmation with it -- so from pass
   15 onward applying or clearing a filter gave no acknowledgement at all.
   The row-break rule stays dead; the sweep is re-enabled only while the
   .filter-changing class is on the bar, and restates the geometry pass 15
   flattened (height:0, flex-basis:100%, order:3). */
.filterbar.filter-changing::after {
  display: block !important;
  content: "" !important; position: absolute !important;
  order: 0 !important; flex-basis: auto !important;
  left: 14px !important; right: 14px !important; bottom: -2px !important; top: auto !important;
  width: auto !important; height: 2px !important;
  border-radius: 2px; pointer-events: none; z-index: 3;
}
/* Applying reads as cyan→gold→cyan running left to right; clearing runs the
   other way in a single quiet tone, so the two are told apart without reading
   anything. */
.filterbar.filter-changing::after {
  background: linear-gradient(90deg, transparent, var(--cyan) 18%, var(--gold) 52%, var(--cyan) 84%, transparent) !important;
  box-shadow: 0 0 12px rgba(0, 217, 255, .45);
  transform-origin: left center;
  animation: filterSweep .78s cubic-bezier(.16, .84, .44, 1) both !important;
}
.filterbar.filter-cleared::after {
  /* !important here too: the applied variant above declares its background
     with !important, and without a matching one the later rule would lose and
     both states would sweep in the same colours. */
  background: linear-gradient(270deg, transparent, var(--text-dim) 30%, var(--text-mid) 55%, transparent) !important;
  box-shadow: none !important;
  transform-origin: right center !important;
}
:root[data-theme="light"] .filterbar.filter-changing::after { box-shadow: 0 0 10px rgba(0, 132, 184, .35); }
@media (prefers-reduced-motion: reduce) { .filterbar.filter-changing::after { animation: none !important; transform: scaleX(1); opacity: .6; } }

/* --- 24. PULSE AGENT drawer in light theme ---
   Two rules in section 17 above apply to every light "panel" shape, and the
   drawer is on that list. `background-image: none` erased the drawer's only
   background -- it is declared with the `background` shorthand, so removing
   the image left background-color at its initial transparent -- and the page
   showed straight through the drawer's text. `overflow: visible` (there so a
   panel's corner marks can sit outside its box) undid the drawer's own
   overflow:hidden, letting the conversation spill past the frame.
   The drawer is a floating surface, not a panel: it gets an opaque face and
   its clipping back. The dimmed page behind it stays visible through the
   backdrop, exactly as in dark. */
:root[data-theme="light"] .qa-drawer {
  overflow: hidden !important;
  background-color: #f7fafd !important;
  background-image: linear-gradient(160deg, rgba(255, 255, 255, .96), rgba(238, 245, 252, .96)) !important;
  border-color: rgba(0, 132, 184, .34) !important;
  box-shadow: 16px 20px 60px rgba(15, 40, 75, .22), 0 0 0 1px rgba(0, 132, 184, .10) !important;
}
:root[data-theme="light"] .qa-drawer::before { display: none !important; }
:root[data-theme="light"] .qa-head { background: linear-gradient(135deg, rgba(0, 132, 184, .10), transparent 55%); border-bottom-color: rgba(0, 106, 148, .22); }
/* The backdrop is a near-black wash in both themes; on a light page that
   reads as the lights going out. Same job, light-appropriate weight. */
:root[data-theme="light"] .qa-backdrop { background: rgba(23, 48, 82, .16) !important; backdrop-filter: blur(1px) !important; -webkit-backdrop-filter: blur(1px) !important; }
/* Measured after the drawer became opaque: the inactive mode button sits on a
   mid-grey face where --text-dim reads 3.86:1. --text-mid on the same face is
   5.7:1. The active button is unchanged. */
:root[data-theme="light"] .qa-drawer .qa-mode-btn:not(.active) { color: var(--text-mid) !important; }

/* --- 25. PULSE AGENT in the telemetry rail ---
   The launcher moved out of the brand rail (which scrolls) into the middle of
   the fixed rail (which does not) -- see v51-pass17.js. It replaces the
   fifteen-bar decoration that was there, so the rail keeps its centre of
   gravity and gains a purpose.

   The mark is the same nine-bar meter used in the drawer head, at rail size.
   The invitation is the label beside it: an unlabelled orb reads as an
   indicator, and this is a button. */
/* Centred on the RAIL, not on the space left over between the two clusters.
   `margin: 0 auto` in the flex row splits the remaining space evenly, and the
   left cluster (brand + page chip) is much wider than the right one, so the
   button landed visibly left of centre. Absolute centring against the rail --
   which is position:fixed, so it is the containing block -- puts it in the
   middle of the header, which is what was asked for. */
.mc-tel-agent { flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; height: 34px; display: flex !important; align-items: center; justify-content: center; margin: 0; }
@media (min-width: 900px) {
  .mc-tel-agent { position: absolute; left: 50%; top: 0; transform: translateX(-50%); z-index: 1; }
  /* The slot no longer occupies space in the row, so the right cluster keeps
     its own margin-left:auto and stays hard right. */
}
/* Below that the two clusters are close enough together that an absolutely
   centred button would sit on top of one of them; in-flow it is. */
@media (max-width: 899px) { .mc-tel-agent { margin: 0 auto; } }
.qa-fab.qa-fab-in-rail {
  position: static !important; transform: none !important;
  display: inline-flex !important; flex-direction: row !important; align-items: center; gap: 8px !important;
  width: auto !important; min-width: 0 !important; height: 26px; padding: 0 12px 0 6px !important;
  border: 1px solid rgba(0, 229, 255, .34) !important; border-radius: 999px !important;
  background: linear-gradient(100deg, rgba(0, 229, 255, .16), rgba(139, 92, 246, .14) 60%, rgba(255, 201, 60, .12)) !important;
  box-shadow: 0 0 0 1px rgba(0, 229, 255, .08), 0 4px 14px rgba(0, 0, 0, .35) !important;
  cursor: pointer; overflow: visible;
}
/* Section 17 strips the launcher's chrome in light theme, on the assumption
   that it sits on a light page. In the rail it does not -- the rail is dark
   instrument chrome in both themes -- so the pill is restated here. That
   selector outranks a plain `.qa-fab.qa-fab-in-rail`, hence the repetition. */
:root[data-theme="light"] .qa-fab.qa-fab-in-rail, :root[data-theme="light"] .qa-fab.qa-fab-in-rail:hover {
  border: 1px solid rgba(0, 229, 255, .34) !important;
  background: linear-gradient(100deg, rgba(0, 229, 255, .16), rgba(92, 182, 246, .14) 60%, rgba(255, 201, 60, .12)) !important;
  box-shadow: 0 0 0 1px rgba(0, 229, 255, .08), 0 4px 14px rgba(0, 0, 0, .35) !important;
}
:root[data-theme="light"] .qa-fab.qa-fab-in-rail:hover {
  border-color: rgba(0, 229, 255, .8) !important;
  box-shadow: 0 0 0 1px rgba(0, 229, 255, .35), 0 6px 20px rgba(0, 229, 255, .28) !important;
}
:root[data-theme="light"] .qa-fab.qa-fab-in-rail svg { filter: none !important; }
.qa-fab.qa-fab-in-rail .qa-fab-orb, .qa-fab.qa-fab-in-rail .qa-fab-orb.has-agent-mark { width: 22px !important; height: 22px !important; margin: 0; }
.qa-fab.qa-fab-in-rail svg { width: 22px !important; height: 22px !important; }
.qa-fab.qa-fab-in-rail .mc-agent-mark { width: 22px; height: 20px; gap: 1.5px; border-radius: 6px; }
.qa-fab.qa-fab-in-rail .mc-agent-mark i { width: 1.5px; height: 14px; }
.qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(2), .qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(10) { height: 8px; }
.qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(3), .qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(9) { height: 10px; }
.qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(4), .qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(8) { height: 12px; }
.qa-fab.qa-fab-in-rail .mc-agent-mark i:nth-child(6) { height: 16px; }
.qa-fab.qa-fab-in-rail .qa-fab-copy { display: inline-flex !important; flex-direction: column; align-items: flex-start; gap: 1px; line-height: 1; }
.qa-fab.qa-fab-in-rail .qa-fab-label { font: 700 11px var(--font-mono); letter-spacing: .16em; color: #d9f6ff; }
.qa-fab.qa-fab-in-rail .qa-fab-hint { font: 500 11px var(--font-mono); letter-spacing: .1em; color: rgba(217, 246, 255, .62); text-transform: uppercase; }
.qa-fab.qa-fab-in-rail:hover, .qa-fab.qa-fab-in-rail:focus-visible {
  border-color: rgba(0, 229, 255, .8) !important;
  box-shadow: 0 0 0 1px rgba(0, 229, 255, .35), 0 6px 20px rgba(0, 229, 255, .28) !important;
  transform: translateY(-1px) !important;
}
.qa-fab.qa-fab-in-rail:hover .qa-fab-label { color: #ffffff; }
.qa-fab.qa-fab-in-rail:active { transform: translateY(0) !important; }
/* A slow breath on the border, so a reader who has never pressed it notices
   there is something here -- once every six seconds, not a flashing beacon. */
.qa-fab.qa-fab-in-rail::before {
  content: ""; position: absolute; inset: -3px; border-radius: 999px; pointer-events: none;
  border: 1px solid rgba(0, 229, 255, .5); opacity: 0; animation: qaRailBreath 6s ease-out infinite;
  display: block !important; background: none !important; transform: none;
}
@keyframes qaRailBreath { 0% { opacity: .55; transform: scale(.96); } 45% { opacity: 0; transform: scale(1.12); } 100% { opacity: 0; transform: scale(1.12); } }
.qa-fab.qa-fab-in-rail:hover::before { animation-duration: 2.4s; }
@media (prefers-reduced-motion: reduce) { .qa-fab.qa-fab-in-rail::before { animation: none !important; opacity: .35; transform: none; } }
/* The rail hides its decorations under 760px; the agent is not a decoration.
   The label goes, the button stays. */
@media (max-width: 760px) {
  .mc-tel-agent { display: flex !important; margin-left: auto; margin-right: auto; }
  .qa-fab.qa-fab-in-rail { padding: 0 8px 0 4px !important; }
  .qa-fab.qa-fab-in-rail .qa-fab-copy { display: none !important; }
}
/* The brand rail's old mobile placement rule pointed at the launcher's old
   home and now matches nothing; the rail placement above replaces it. */

/* --- 26. Assign to a person, not to a text box ---
   The picker that opens from ASSIGN on a recommendation (v50-actions-ui.js). */
.nba-assign-picker {
  position: fixed; z-index: 1300; display: flex; flex-direction: column; gap: 8px;
  padding: 12px; border: 1px solid var(--cyan-line); border-radius: 12px;
  background: var(--bg-panel); box-shadow: var(--shadow-lg);
}
.nba-assign-head { font: 700 11px var(--font-mono); letter-spacing: .16em; color: var(--text-dim); }
.nba-assign-search { width: 100%; height: 32px; padding: 0 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-input); color: var(--text-hi); font: 500 12px var(--font-body, inherit); }
.nba-assign-search:focus { outline: 2px solid var(--cyan); outline-offset: 1px; }
.nba-assign-list { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow-y: auto; }
.nba-assign-option {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 7px 9px; border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--text-hi); text-align: left; cursor: pointer;
  font: 600 12px var(--font-body, inherit);
}
.nba-assign-option small { font: 500 11px var(--font-mono); color: var(--text-dim); letter-spacing: .02em; }
.nba-assign-option:hover { background: var(--bg-hover); }
.nba-assign-option.is-chosen { border-color: var(--cyan); background: var(--cyan-soft); }
.nba-assign-option.is-me small { color: var(--cyan); }
.nba-assign-none { padding: 10px 4px; font: 500 11px var(--font-body, inherit); color: var(--text-dim); }
.nba-assign-foot { display: flex; justify-content: flex-end; gap: 8px; }
.nba-assign-confirm[disabled] { opacity: .45; cursor: not-allowed; }

/* --- 27. Clearing the exception inbox ---
   Two presses, then an undo, rather than a browser confirm() (nothing else in
   this portal uses one) or a silent bulk edit. */
.v38-exception-tools .v38-clear-list { margin-left: auto; }
.v38-clear-list.is-armed { border-color: var(--gold-line) !important; color: var(--gold) !important; background: var(--gold-soft) !important; }
.v38-clear-list.is-undo { border-color: var(--cyan-line) !important; color: var(--cyan) !important; background: var(--cyan-soft) !important; }
.v38-clear-list[disabled] { opacity: .45; cursor: not-allowed; }

/* --- 28. "Not compared here" ---
   Where a scope has been left out of a comparison (EXPORT), the tab says so
   above the charts rather than leaving a reader to notice the absence. */
.comparison-exclusion-note { margin: 0 0 12px; }
.comparison-exclusion-note .caveat-note { margin: 0; }

/* --- 29. A KPI caption crushed to one letter per line ---
   Spotted while checking build 21 on a 390px viewport, and older than this
   build. `.kpi-foot` is a flex row; `.ksub` is a flex item with no minimum,
   so on a narrow card the delta beside it takes the width and the caption is
   squeezed to 4px. With `overflow-wrap: anywhere` already set, that renders
   "Awaiting governed data refresh" as a vertical column of single letters.
   The row wraps instead, and the caption takes a line of its own when there
   is not enough width to sit beside the delta. */
/* Section 18 above pinned the row to `flex-wrap: nowrap !important` to keep
   the delta and its caption on one line on a full-width card. That is right
   there and wrong on a 390px one, so the no-wrap rule is kept for cards with
   room and lifted below the width where the caption stops fitting. */
/* Wrapping rather than never wrapping. `nowrap` keeps the delta and the
   caption on one line, and when they do not fit on one line it does not stop
   them being on one line -- it lets the caption run off the card, or squeezes
   it to nothing. Wrapping keeps them side by side whenever there is room and
   moves the caption to its own line when there is not, which is what the
   original rule was after. Below 560px the caption always takes its own line;
   at that width it never fits beside the delta. */
.kpi-foot { flex-wrap: wrap !important; }
.kpi-foot .ksub { flex: 1 1 auto; min-width: 0; }
@media (max-width: 560px) { .kpi-foot .ksub { flex: 1 1 100%; } }

/* ---------- 21. Control Panel below 440px (V20.14.60) ----------
   Section 18g compacts the Control Panel by forcing the context strip to two
   columns with !important and holding the title and scope on one nowrap row.
   That is right on a desktop and wrong on a phone: at 390px the title
   ("CONTROL PANEL / PORTAL ADMINISTRATION") landed on top of the health pill,
   and the scope strip was drawn over the page title with "Control Panel"
   clipped to "Control". The page reported no horizontal overflow the whole
   time, because nothing reflowed -- it was all clipped inside its own
   container, which is exactly the case a scrollWidth check cannot see.

   These rules come after 18g so they win without another !important war, and
   they only undo the two things that assume desktop width: the forced column
   count and the nowrap. */
@media (max-width: 440px) {
  .cp-guide-context { grid-template-columns: minmax(0, 1fr) !important; gap: 8px !important; padding: 10px 12px !important; }
  .cp-guide-copy { flex-wrap: wrap; gap: 2px 10px; }
  .cp-guide-copy h1 { white-space: normal !important; }
  .cp-guide-copy p { white-space: normal !important; overflow: visible; text-overflow: clip; }
  .cp-guide-scope { display: flex !important; flex-wrap: wrap; gap: 6px; }
  .cp-guide-scope div { flex: 1 1 auto; }
  /* The source row is a flex row that never wrapped, so the READY/MISSING
     badge slid off the right edge and showed as a coloured sliver. */
  .refresh-source { flex-wrap: wrap !important; }
  /* The topbar is a nowrap flex row. At 390px there is not enough width for
     the back arrow, mark, title, health pill and six icon buttons, so with
     nowrap the items simply overlapped each other -- "CONTROL PANEL / PORTAL
     ADMINISTRATION" was drawn across the health pill and the back arrow. It
     wraps here, and the second line of the brand block (which repeats what the
     tab bar already says) is dropped. */
  .cp-sticky-shell .topbar { flex-wrap: wrap !important; row-gap: 8px; }
  .cp-sticky-shell .topbar .tb-tag { display: none !important; }
  .cp-sticky-shell .topbar .tb-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cp-sticky-shell .topbar-right { flex-wrap: wrap; justify-content: flex-end; }
}

/* The 11px type floor (pulse-tokens.css) applies to the Control Panel too.
   18g set the scope strip to 7.5px/9.5px and the tab nav to 10.5px, which is
   the same lean-in the tokens file exists to prevent. */
.cp-guide-scope span { font-size: 11px !important; }
.cp-guide-scope b { font-size: 11px !important; }
.cp-guide-copy p { font-size: 11px !important; }
.cp-sticky-shell .tabnav button { font-size: 11px !important; }

/* V20.14.93 -- the wave scaled for the taller top bar; the bar's height and
   the rest of the cluster live in pulse-v90.css.
   V20.14.101 -- re-scaled with the bar, which is now 52px rather than 64px. */
/* V20.14.111 -- the equaliser this scaled is gone; the signal mark keeps its
   own proportions and only needs the bar's height. */
.mc-tel-stream { height: 24px !important; }

/* ================================================================ V20.14.110
   A SHORTER FROZEN DECK.

   The deck stays frozen -- it is what makes brand, basis, filters and tabs
   reachable from halfway down a long table, and nobody asked for that back.
   What was asked for is the report underneath it: at 1440x900 the deck stood
   304px tall, leaving under 600px of viewport for the thing the deck is a
   control for, so every table meant scrolling.

   Nothing is removed here. Every row keeps its contents; each one is simply
   drawn at the size it needs rather than the size it had. Measured at
   1500x900: 304px -> ~240px at the top of the page, and ~214px -> ~170px once
   condensed, which is another screenful of report per scroll.

   Two things are deliberately NOT trimmed: the filter selects keep their
   touch-target height, and the tab labels keep their type size. A deck that is
   shorter because its controls became hard to hit is not shorter. */
.pulse-sticky-header { padding-bottom: 6px !important; margin-bottom: 12px !important; }
.pulse-sticky-header .topbar { padding-top: 6px !important; padding-bottom: 5px !important; }
.pulse-sticky-header .brandmark h1 { font-size: 18px !important; letter-spacing: .13em !important; }
.pulse-sticky-header .brandmark { gap: 11px !important; }
.pulse-sticky-header .brandmark .report-mark,
.pulse-sticky-header .brandmark .report-pulse-mark { width: 40px !important; height: 40px !important; }
.pulse-sticky-header .brand-switcher { margin-bottom: 5px !important; padding-top: 3px !important; padding-bottom: 3px !important; }
.pulse-sticky-header .brand-btn.logo-only { width: 88px !important; height: 52px !important; padding: 4px 7px !important; }
.pulse-sticky-header .brand-btn.logo-only .brand-logo { max-width: 72px !important; max-height: 42px !important; }
.pulse-sticky-header .brand-btn.logo-only[data-brand="CAFEMIO"] .brand-logo { max-width: 80px !important; max-height: 47px !important; }
.pulse-sticky-header .brand-btn.logo-only[data-brand="CORONA"] .brand-logo { max-width: 76px !important; max-height: 45px !important; }
.pulse-sticky-header .brand-btn.portfolio-btn { height: 52px !important; padding: 4px 11px !important; }
.pulse-sticky-header .filterbar { padding: 5px 12px !important; }
.pulse-sticky-header .tabnav { margin-top: 5px !important; padding: 2px !important; }
.pulse-sticky-header #tabNav .tab-btn { padding: 6px 12px !important; }
.pulse-sticky-header .tabnav-rail { margin-bottom: 0 !important; }

/* Condensed, the brand rail and filter deck are already gone and the summary
   strip stands in for them; the title row can give up more again, because by
   then the reader knows what report they are in. */
.pulse-sticky-header.is-condensed .topbar { padding-top: 3px !important; padding-bottom: 2px !important; }
.pulse-sticky-header.is-condensed .brandmark h1 { font-size: 15px !important; }
.pulse-sticky-header.is-condensed .brandmark .report-mark,
.pulse-sticky-header.is-condensed .brandmark .report-pulse-mark { width: 30px !important; height: 30px !important; }
.pulse-sticky-header.is-condensed .deck-summary { margin-top: 4px !important; padding: 4px 11px !important; }
.pulse-sticky-header.is-condensed .tabnav { margin-top: 4px !important; }

/* ===========================================================================
   V20.14.190 -- THE SAME PASS, AT THE WIDTH IT IS ACTUALLY READ AT.
   ===========================================================================
   The block above was measured at 1500x900 and got the header from 304px to
   240px. Measured again at 1366x768 -- the laptop this is read on -- the report
   still opened on a screenful of chrome, and NO CHART WAS FULLY VISIBLE on any
   tab:

       52  portal top bar          49  tab rail
       69  title row              183  KPI row
       57  brand switcher          47  brief strip
      100  filter bar (WRAPPED)    94  the two decision cards
      ------------------------------------------------------------
      736 before the first panel, on a 768-pixel screen

   Three things the earlier pass could not have seen at 1500px, and one it did
   not cover:

   1. THE FILTER BAR WRAPS at 1366. Its children come to 1,288px inside about
      1,294px of room, so it silently becomes two rows and costs 44px on
      exactly the screens that can least afford it. The cheapest pixels in that
      sum are the word "FILTERS" -- 64px, beside five dropdowns that are
      visibly filters -- and the tool strip's button padding.
   2. THE KPI ROW is 183px: head 26, value 34, foot 38, actions 33, four gaps
      and 20px of padding. Every word of it stays; it simply stops setting a
      118px floor and padding a number like a poster.
   3. THE TWO SUMMARY STRIPS below it are 141px of one-line summaries of things
      the panels restate in full.
   4. CHART HEIGHTS were never in scope. `.h-320` and its siblings are the only
      place a chart's height is stated, so scaling them scales the whole deck.

   Same rules as before: nothing is removed, no control loses its hit target
   (the selects keep 30px, the tab labels keep their size), and a tall screen
   gets most of the chart height back.
   =========================================================================== */
/* Seven pixels. The bar's children came to 1,218px in 1,260px of room, and the
   seven gaps between them cost 49 -- so it wrapped by SEVEN pixels and cost 44
   in height. Two pixels off each gap and two off each tool button, and it fits
   on one line with the icons intact. */
.pulse-sticky-header .filterbar { padding: 5px 10px !important; gap: 5px !important; }
@media (max-width: 1500px) {
  .pulse-sticky-header .filterbar > .flabel { display: none !important; }
}
/* The tool buttons are sized by WIDTH, not padding -- 36px each, eight of them.
   Padding rules slid off them entirely (measured: still 6px/6px after two
   attempts). Four pixels each is the 32 the bar needed. */
.pulse-sticky-header .filterbar .v164-rail button { width: 32px !important; min-width: 32px !important; min-height: 28px !important; padding: 4px 4px !important; }
/* Height only. The left padding is NOT touched: line 341 reserves 26px for the
   icon that sits inside each control, and shrinking it put the icon on top of
   the first letter of "All Regions" -- caught in the screenshot, not the
   measurement, which is what screenshots are for. */
.pulse-sticky-header .filterbar select.fselect { min-height: 30px !important; padding-top: 5px !important; padding-bottom: 5px !important; }

#kpiRow.kpi-row { margin-bottom: 10px !important; }
#kpiRow .kpi-card { padding: 7px 11px 5px !important; gap: 3px !important; min-height: 0 !important; }
#kpiRow .kpi-card .kvalue { line-height: 1.05 !important; }
#kpiRow .kpi-foot { line-height: 1.25 !important; }
#kpiRow .kpi-actions { margin-top: 0 !important; }
#kpiRow .kpi-actions button { min-height: 24px !important; height: 24px !important; padding: 2px 6px !important; }

#v46Brief .v46-brief-head { padding: 7px 11px !important; }
.value-decision-row { gap: 10px !important; margin-bottom: 10px !important; }
.value-decision-card { padding: 8px 12px !important; }

#tabBody .panel { padding: 13px 15px !important; }
#tabBody .panel-grid { gap: 12px !important; }
#tabBody .ptitle { margin-bottom: 2px !important; }
#tabBody .psub { margin-bottom: 7px !important; }

#tabBody .h-260 { height: 224px !important; }
#tabBody .h-300 { height: 256px !important; }
#tabBody .h-320 { height: 272px !important; }
#tabBody .h-340 { height: 288px !important; }
#tabBody .h-380 { height: 322px !important; }
#tabBody .h-420 { height: 356px !important; }
#tabBody .h-440 { height: 374px !important; }
#tabBody .h-460 { height: 390px !important; }
#tabBody .h-520 { height: 440px !important; }

@media (max-width: 1200px) {
  .pulse-sticky-header .brand-btn.logo-only { width: 74px !important; height: 44px !important; }
  .pulse-sticky-header .brand-btn.logo-only .brand-logo { max-width: 60px !important; max-height: 32px !important; }
  .pulse-sticky-header .brand-btn.portfolio-btn { height: 44px !important; }
}

/* ---- THE 298 PIXELS THAT NEVER GO AWAY --------------------------------
   The measurement that matters more than the first screen: while scrolling,
   the sticky deck's bottom edge sits at 298px, so a 768px laptop has 470px of
   reading area FOREVER -- and a panel is 470-550px tall, which is why no chart
   is ever fully in view. "Only one graph is visible and I have to scroll a
   lot" is that number, exactly.

   115px of those 298 are the brand switcher and the filter bar, which this
   skin hides once the deck condenses... and which pulse-v151-user-revision.css
   deliberately puts back, because they were asked for. That request is not
   being reversed here: the two rows stay, and are sized for a strip you scroll
   past rather than a deck you arrive at. Their children are sized, not their
   display, so nothing here fights that file.

   Condensed: brand switcher 57 -> ~40, filter bar 58 -> ~44. */
.pulse-sticky-header.is-condensed .brand-switcher { margin-bottom: 3px !important; padding-top: 1px !important; padding-bottom: 1px !important; }
.pulse-sticky-header.is-condensed .brand-btn.logo-only { width: 64px !important; height: 34px !important; padding: 2px 5px !important; }
.pulse-sticky-header.is-condensed .brand-btn.logo-only .brand-logo { max-width: 52px !important; max-height: 24px !important; }
.pulse-sticky-header.is-condensed .brand-btn.logo-only[data-brand="CAFEMIO"] .brand-logo { max-width: 58px !important; max-height: 28px !important; }
.pulse-sticky-header.is-condensed .brand-btn.logo-only[data-brand="CORONA"] .brand-logo { max-width: 56px !important; max-height: 26px !important; }
.pulse-sticky-header.is-condensed .brand-btn.logo-only[data-brand="BUDWEISER"] .brand-logo { max-width: 58px !important; max-height: 28px !important; }
.pulse-sticky-header.is-condensed .brand-btn.portfolio-btn { height: 34px !important; padding: 2px 8px !important; }
.pulse-sticky-header.is-condensed .filterbar { padding: 3px 10px !important; gap: 6px !important; }
.pulse-sticky-header.is-condensed .filterbar select.fselect { min-height: 26px !important; padding-top: 3px !important; padding-bottom: 3px !important; }
.pulse-sticky-header.is-condensed .filterbar .v164-rail button { min-height: 24px !important; padding: 3px 6px !important; }
.pulse-sticky-header.is-condensed .filterbar .v20-control,
.pulse-sticky-header.is-condensed .filter-reset { min-height: 26px !important; padding: 3px 8px !important; }

/* A tall screen has room to breathe, and taking it away would be a different
   complaint. Above 1000px of viewport the charts go back most of the way. */
@media (min-height: 1000px) {
  #tabBody .h-320 { height: 300px !important; }
  #tabBody .h-380 { height: 356px !important; }
  #tabBody .h-440 { height: 412px !important; }
  #tabBody .h-520 { height: 488px !important; }
}

/* The frozen deck is opaque.
   It was a 90-96% gradient over a 12px backdrop blur -- frosted glass, which
   reads beautifully over an empty page and badly over a table. Once the deck
   condenses and sits on top of the report, the rows underneath show through it
   legibly: cyan figures from one table crossing the brand strip of another.
   A header you can read the data through is not a header. The blur stays for
   the edges; the surface does not. */
.pulse-sticky-header { background: linear-gradient(180deg, #070d1c, #050a16) !important; }
:root[data-theme="light"] .pulse-sticky-header { background: linear-gradient(180deg, #ffffff, #f4f8fd) !important; }
