:root {
  /* Compat aliases (--bg / --header / --panel / --panel2 / --surface / --border /
     --border2 / --text-metadata / --sans / --mono) removed 2026-07-01 — every call
     site now references the canonical obsidian-tokens.css token directly. --accent
     (Hyperliquid mint #97fce4) also inherits from obsidian-tokens.css. */
  --accent-bg:var(--accent-tint-12); --accent-bg2:var(--accent-tint-08);
  --active-item:var(--accent-tint-08);
  --positive-bg:var(--positive-tint-10);
  --negative-bg:var(--negative-tint-10);
  --neutral-bg:var(--neutral-tint-10);
  --sidebar-w:210px; --header-h:74px; --tab-bar-h:40px;
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
html{background-color:var(--bg-base);}
/* Body must be transparent so the fixed #hx-bg-grid (z-index:-1) shows through; the
   base color lives on html. Overrides obsidian-tokens.css `html,body{background:...}`
   (this sheet loads after it). */
body{background-color:transparent;}
html,body{height:100%;color:var(--text-primary);font-family:var(--font-plex);font-size:13px;overflow-x:hidden;}
/* Animated page-background grid (v2 / hl.eco-style) — a faint mint line-grid + slow
   twinkling mint squares. Fixed BEHIND all content (z-index:-1); opaque panels cover
   it, so it only reads in the page margins + gaps. Squares are created + repositioned
   each cycle by a small inline script in index.html. Respects reduced-motion. */
#hx-bg-grid{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;background-image:linear-gradient(to right,var(--dot-grid) 1px,transparent 1px),linear-gradient(to bottom,var(--dot-grid) 1px,transparent 1px);background-size:40px 40px;-webkit-mask-image:radial-gradient(ellipse 120% 100% at 50% 30%,black 70%,transparent 100%);mask-image:radial-gradient(ellipse 120% 100% at 50% 30%,black 70%,transparent 100%);}
#hx-bg-grid .hx-sq{position:absolute;width:39px;height:39px;background:var(--mint-soft);opacity:0;will-change:opacity;animation:hx-twinkle 4.8s ease-in-out infinite;}
@keyframes hx-twinkle{0%,100%{opacity:0}42%,58%{opacity:.14}}
@media (prefers-reduced-motion:reduce){#hx-bg-grid .hx-sq{animation:none;opacity:.03;}}
::-webkit-scrollbar{width:4px;height:4px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:4px;}

/* ── TOP HEADER ── */
#header{position:fixed;top:0;left:0;right:0;z-index:300;height:var(--header-h);background:var(--bg-elevated);border-bottom:1px solid var(--border-default);display:flex;align-items:center;}
.header-logo{display:flex;align-items:center;gap:10px;padding:0 18px;width:var(--sidebar-w);flex-shrink:0;border-right:1px solid var(--border-default);height:100%;}
.logo-icon{width:26px;height:26px;border-radius:var(--radius-md);background:var(--accent);display:inline-flex;align-items:center;justify-content:center;font-size:17px;color:var(--bg-base);font-family:var(--font-display);flex-shrink:0;box-shadow:0 0 10px var(--accent-glow);}
.logo-text{font-family:var(--font-display);font-size:16px;color:var(--text-primary);letter-spacing:1px;line-height:1;}
.logo-sub{font-family:var(--font-plex);font-size:7px;color:var(--text-tertiary);letter-spacing:.12em;text-transform:uppercase;}
.header-ticker{flex:1;display:flex;align-items:center;padding:0 var(--space-4);gap:var(--space-5);overflow:hidden;}
.ht-item{display:flex;flex-direction:column;gap:1px;white-space:nowrap;}
.ht-label{font-family:var(--font-plex);font-size:8px;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.1em;}
.ht-val{font-size:13px;font-weight:500;color:var(--text-primary);font-family:var(--font-plex);letter-spacing:var(--tracking-tight);}
.ht-sub{font-size:var(--text-xs);color:var(--text-secondary);}
.header-right{display:flex;align-items:center;gap:var(--space-3);padding:0 var(--space-4);flex-shrink:0;}
.live-badge{display:flex;align-items:center;gap:5px;font-size:var(--text-xs);color:var(--accent);letter-spacing:var(--tracking-label);}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}
.countdown-txt{font-size:var(--text-xs);color:var(--text-tertiary);font-family:var(--font-plex);}

/* ── 3-DASHBOARD TAB BAR (below header) ── */
#dash-tabs{position:fixed;top:52px;left:0;right:0;z-index:290;height:40px;background:var(--bg-elevated);border-bottom:1px solid var(--border-default);display:flex;align-items:center;padding:0 0 0 var(--sidebar-w);}
.dash-tab{padding:0 var(--space-5);height:100%;display:flex;align-items:center;gap:7px;font-family:var(--font-plex);font-size:var(--text-base);font-weight:500;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color var(--duration-fast) var(--ease-out),border-color var(--duration-fast) var(--ease-out);white-space:nowrap;}
.dash-tab:hover{color:var(--text-primary);}
.dash-tab.active{color:var(--accent);border-bottom-color:var(--accent);}
.dash-tab .dt-icon{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.dash-tab-sep{width:1px;height:18px;background:var(--border-default);margin:0 var(--space-1);}

/* ── LAYOUT SHELL ── */
#shell{display:flex;padding-top:var(--header-h);}

/* ── SIDEBAR ── */
#sidebar{position:fixed;top:var(--header-h);left:0;bottom:0;width:var(--sidebar-w);background:var(--bg-inset);border-right:1px solid var(--border-default);overflow-y:auto;overflow-x:hidden;transition:width 0.2s ease;z-index:200;}
#sidebar.collapsed{width:0;}
.sidebar-nav-label{padding:14px 14px var(--space-1);font-family:var(--font-plex);font-size:var(--text-xxs);font-weight:500;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:var(--tracking-label);display:flex;align-items:center;justify-content:space-between;}
.sidebar-collapse-btn{background:none;border:none;cursor:pointer;color:var(--text-tertiary);font-size:var(--text-md);padding:2px var(--space-1);border-radius:var(--radius-sm);}
.sidebar-collapse-btn:hover{color:var(--text-primary);}
.sidebar-item{display:flex;align-items:center;gap:9px;padding:var(--space-2) 14px;cursor:pointer;font-family:var(--font-plex);color:var(--text-secondary);font-size:var(--text-base);font-weight:400;white-space:nowrap;position:relative;transition:background var(--duration-fast) var(--ease-out),color var(--duration-fast) var(--ease-out);border-radius:0;}
.sidebar-item:hover{background:var(--bg-hover);color:var(--text-primary);}
.sidebar-item.active{background:var(--active-item);color:var(--accent);font-weight:500;}
.sidebar-item.active::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accent);border-radius:0 2px 2px 0;}
.si-dot{width:4px;height:4px;border-radius:50%;background:var(--text-disabled);flex-shrink:0;}
.sidebar-item.active .si-dot{background:var(--accent);box-shadow:0 0 7px var(--accent-glow);}
.sidebar-expand-btn{display:none;position:fixed;top:50%;left:0;transform:translateY(-50%);z-index:250;background:var(--bg-elevated);border:1px solid var(--border-default);border-left:none;border-radius:0 6px 6px 0;color:var(--text-secondary);font-size:var(--text-md);padding:10px 5px;cursor:pointer;transition:color var(--duration-fast) var(--ease-out);}
.sidebar-expand-btn:hover{color:var(--text-primary);}

/* ── CONTENT AREA ── */
#content{margin-left:var(--sidebar-w);flex:1;min-width:0;transition:margin-left 0.2s ease;}
#content.full{margin-left:0;}
.content-topbar{background:var(--bg-elevated);border-bottom:1px solid var(--border-default);padding:0 20px;height:36px;display:flex;align-items:center;gap:12px;position:sticky;top:var(--header-h);z-index:100;}
.section-title{font-family:var(--font-display);font-size:16px;letter-spacing:1px;color:var(--text-primary);}
.section-sub{font-family:var(--font-plex);font-size:11px;color:var(--text-secondary);flex:1;}
.refresh-btn{background:none;border:1px solid var(--border-default);border-radius:4px;color:var(--text-secondary);font-size:var(--text-sm);padding:3px 10px;cursor:pointer;}
.refresh-btn:hover{color:var(--text-primary);border-color:var(--border-strong);}
.page-body{padding:16px 20px 32px;}
@media(min-width:1440px){.page-body{padding:20px 32px 32px;}}

/* ── TAB PANELS ── */
.tab-panel{display:none;}
.tab-panel.active{display:block;}

/* ── METRICS STRIP (Obsidian KPI card pattern — canonical GLOBAL def) ── */
.metrics-strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--space-3);background:transparent;border:0;overflow:visible;margin-bottom:var(--space-4);}
.ms-item{position:relative;overflow:visible;background:transparent;border:none;border-radius:0;padding:0 16px 0 0;display:flex;flex-direction:column;gap:0;cursor:default;}
.ms-item::before{display:none;}
.ms-item:hover{border-color:var(--border-strong);}
.ms-item:hover::before{background:var(--accent);}
.ms-item:hover .ms-val{color:var(--accent);}
.ms-item.active::before{background:var(--accent);}
.ms-item.active .ms-val{color:var(--accent);}
.ms-label{font-family:var(--font-plex);font-size:10px;font-weight:var(--weight-medium);letter-spacing:1.2px;text-transform:uppercase;color:var(--text-secondary);line-height:1.4;}
.ms-val{font-family:var(--font-plex);font-size:27px;font-weight:var(--weight-semibold);color:var(--text-primary);letter-spacing:-0.5px;line-height:1.04;margin:9px 0 6px;font-variant-numeric:tabular-nums;}
.ms-sub{font-family:var(--font-plex);font-size:11px;color:var(--text-tertiary);line-height:1.45;}
.ms-tag{display:inline-block;vertical-align:middle;margin-left:3px;font-family:var(--font-plex);font-size:8px;font-weight:var(--weight-semibold);letter-spacing:0.5px;padding:1px 6px;border-radius:var(--radius-pill);white-space:nowrap;}
.ms-tag-live{color:var(--accent);background:var(--accent-tint-12);border:1px solid var(--accent-tint-40);}
.ms-tag-warn{color:var(--warn);background:var(--warn-tint-10);border:1px solid var(--warn-tint-35);}
/* HYPE → Token Supply → Holder Distribution: dense in-panel concentration grid
   (13 stats, up to 5-across). Keep the compact value size — the 27px hero-KPI size
   is too heavy here — while using the canonical borderless .ms-item structure. */
#holder-distribution-panel .ms-val{font-size:17px;margin:2px 0 0;}
.ms-delta{font-family:var(--font-plex);font-size:11px;line-height:1.3;color:var(--text-tertiary);margin:0 0 2px;}
.ms-delta:empty{display:none;}
/* Borderless panel — KPI-only sections, so the cards aren't boxed inside a second card */
.panel-flat{background:transparent;border:0;border-radius:0;overflow:visible;}
/* v2 (hl.eco-style): un-box stats nested inside a panel into a clean text grid + tighten */
.panel .ms-item,.panel .cs-item{background:transparent;border:none;padding:0;overflow:visible;}
.panel .ms-item .ms-val,.panel .cs-item .cs-val{margin-top:auto;font-size:var(--text-2xl);}
.panel .metrics-strip,.panel .chart-stats-row{margin-bottom:var(--space-2);}

/* ── CARDS / PANELS ── */
.panel{background:var(--bg-elevated);border:1px solid var(--border-card);border-radius:var(--radius-lg);overflow:hidden;}
.panel-header{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--space-2);padding:14px 18px;border-bottom:1px solid var(--border-default);}
.panel-title{font-family:var(--font-plex);font-size:14px;font-weight:var(--weight-medium);color:var(--text-primary);letter-spacing:0;}
.panel-title-row{display:inline-flex;align-items:center;gap:var(--space-2);}
/* Info icon + hover/focus tooltip (panel-title explanation popover). Drops
   downward into the panel body so .panel{overflow:hidden} never clips it. */
.info-tip{position:relative;display:inline-flex;align-items:center;cursor:help;color:var(--text-secondary);font-size:11px;font-weight:400;margin-left:6px;}
.info-tip:hover,.info-tip:focus{color:var(--accent);outline:none;}
.info-tip .info-pop{
  position:absolute;top:calc(100% + 6px);left:0;z-index:80;
  width:max-content;max-width:360px;white-space:normal;text-align:left;
  background:var(--bg-base);border:1px solid var(--border-default);border-radius:var(--radius-md);
  padding:9px 11px;font-size:10px;line-height:1.55;color:var(--text-secondary);
  font-weight:400;font-family:var(--font-plex);box-shadow:var(--shadow-dropdown);
  opacity:0;visibility:hidden;transform:translateY(-3px);transition:opacity .12s ease,transform .12s ease;pointer-events:none;
}
.info-tip:hover .info-pop,.info-tip:focus .info-pop{opacity:1;visibility:visible;transform:translateY(0);}
.info-tip .info-pop strong{color:var(--text-primary);font-weight:600;}

/* ── Phase 2 (2026-07-06): on mobile, ⓘ info-tips are tap-to-toggle popovers ──
   Hover doesn't exist on touch and the absolute pop (max-width 360px, left:0)
   overflows a 390px screen when a tip sits right-of-centre. So on mobile: kill
   the hover/focus reveal, and let JS (js/nav.js) toggle .info-open — single
   open at a time, tap-outside / Esc closes. The pop goes position:fixed and
   spans the viewport width (JS sets its top from the tapped tip) so it can
   never overflow. Desktop is untouched — the JS handler no-ops above 768px. */
@media (max-width:768px){
  .info-tip:hover .info-pop,.info-tip:focus .info-pop{opacity:0;visibility:hidden;transform:translateY(-3px);pointer-events:none;}
  .info-tip .info-pop{position:fixed;left:12px;right:12px;top:auto;width:auto;max-width:none;z-index:305;}
  .info-tip.info-open .info-pop{opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto;}
}

/* Hyperliquid Strategies (PURR) treasury section — provenance label, null-state,
   and responsive stacking for the chart + adjusted-NAV two-column row. */
.hsi-prov{font-size:8px;color:var(--text-disabled);margin-top:3px;text-transform:uppercase;letter-spacing:.3px;}
.hsi-unavail{color:var(--text-disabled);font-style:italic;}
@media (max-width:760px){
  #hsi-treasury-panel .hsi-grid{grid-template-columns:1fr!important;}
  #hsi-treasury-panel #hsi-cards{grid-template-columns:repeat(2,1fr)!important;}
}
.panel-sub{font-family:var(--font-plex);font-size:11px;color:var(--text-secondary);margin-top:3px;}
.panel-body{padding:18px 20px 16px;}
/* v2 panel hero — big mint headline value promoted out of the KPI grid (panel-mockup anatomy).
   New display pattern (no existing equivalent); the promoted KPI keeps its id so render JS is untouched. */
.panel-hero{margin:0 0 var(--space-4);}
.panel-hero .ph-label{font-family:var(--font-plex);font-size:10px;font-weight:var(--weight-medium);letter-spacing:1.2px;text-transform:uppercase;color:var(--text-secondary);}
.panel-hero .ph-val{font-family:var(--font-plex);font-size:40px;font-weight:var(--weight-medium);color:var(--mint-soft);letter-spacing:-1px;line-height:1.02;margin-top:8px;font-variant-numeric:tabular-nums;}
.panel-hero .ph-sub{font-family:var(--font-plex);font-size:11px;color:var(--text-tertiary);margin-top:9px;letter-spacing:.2px;}
/* OI Dashboard: main history chart takes most of the width, composition donut on the side. */
.oid-body{display:flex;gap:24px;align-items:flex-start;margin-top:4px;}
.oid-chart-col{flex:1;min-width:0;}
.oid-side-col{flex:none;width:220px;display:flex;flex-direction:column;gap:10px;}
.oid-donut{width:100%;position:relative;}
@media (max-width:720px){
  .oid-body{flex-direction:column;}
  .oid-side-col{width:auto;}
  .oid-donut{max-width:220px;margin:0 auto;}
}
/* Volume Share panel: hero + KPIs on the left, HIP-3/Core donut on the right. */
.vshare-body{display:flex;align-items:center;gap:32px;}
.vshare-main{flex:1;min-width:0;}
.vshare-donut{flex:none;width:172px;height:172px;position:relative;}
@media (max-width:640px){
  .vshare-body{flex-direction:column;align-items:stretch;gap:18px;}
  .vshare-donut{width:150px;height:150px;align-self:center;}
}
/* Section eyebrow (Bebas display) + hero panel — canonical GLOBAL defs (un-scoped from the 24-tab block) */
.perps-eyebrow{display:flex;align-items:center;gap:var(--space-2);margin:2px 0 16px;}
.pe-sq{width:8px;height:8px;background:var(--accent);flex:none;}
.pe-tx{font-family:var(--font-display);font-size:17px;letter-spacing:4px;color:var(--text-primary);line-height:1;}
#main-chart-panel{border-top:1px solid var(--border-card);}
#main-chart-panel .panel-title::before{content:'';display:inline-block;width:7px;height:7px;border-radius:2px;background:var(--accent);margin-right:9px;vertical-align:middle;}
@media (max-width:768px){.pe-tx{font-size:15px;}}
.live-tag{font-size:var(--text-xxs);font-weight:500;color:var(--accent);background:var(--neutral-bg);padding:2px 6px;border-radius:var(--radius-sm);letter-spacing:0.3px;}
.live-pill{display:inline-block;padding:2px 6px;font-size:var(--text-xxs);font-weight:500;border-radius:6px;color:var(--accent);background:var(--neutral-bg);border:1px solid var(--border-default);letter-spacing:0.4px;}
.dune-tag{font-size:var(--text-xxs);font-weight:500;color:var(--negative);background:var(--neutral-bg);padding:2px 6px;border-radius:var(--radius-sm);letter-spacing:0.3px;}
/* Per-panel staleness indicator — only rendered when backend reports the
   panel's data source as not fresh. Kept visually parallel to .dune-tag
   so it reads as a sibling annotation, not a banner. */
.panel-stale-tag{font-size:var(--text-xxs);font-weight:500;color:var(--text-tertiary);background:var(--neutral-bg);padding:2px 6px;border-radius:var(--radius-sm);letter-spacing:0.3px;margin-left:6px;cursor:help;}
/* Neutral informational tag — used for data-gap / pending-backfill state. Not an error; muted. */
.gap-tag{display:inline-block;font-size:var(--text-xxs);font-weight:500;color:var(--text-tertiary);background:var(--neutral-bg);padding:2px 8px;border-radius:var(--radius-sm);letter-spacing:0.3px;margin-left:8px;vertical-align:middle;cursor:help;font-family:var(--font-plex);}
/* Panel freshness/source pill (T4 Phase 1). Small panel-header tag: status +
   source. Tone encodes source priority — canonical strong (accent),
   aggregator/delayed muted, model/projected amber, stale/unavailable red,
   pending warning-amber. Rendered by js/freshness-pill.js. */
.freshness-pill{display:inline-flex;align-items:center;gap:5px;font-size:var(--text-xxs);font-weight:500;font-family:var(--font-plex);padding:2px 7px;border-radius:6px;letter-spacing:0.3px;border:1px solid var(--border-default);white-space:nowrap;vertical-align:middle;cursor:help;}
.freshness-pill__dot{width:5px;height:5px;border-radius:50%;background:currentColor;flex:0 0 auto;}
.freshness-pill--ok{color:var(--accent);background:var(--neutral-bg);}
.freshness-pill--muted{color:var(--text-tertiary);background:var(--neutral-bg);}
.freshness-pill--model{color:var(--warn);background:var(--warn-tint-10);border-color:var(--warn-tint-35);}
.freshness-pill--warn{color:var(--warn);background:var(--warn-tint-10);border-color:var(--warn-tint-35);}
.freshness-pill--stale{color:var(--negative);background:var(--negative-tint-10);border-color:var(--negative-tint-30);}

/* ── HIP-4 (Live prediction markets — Phase 1+2) ──
   Read-only analytics. Kept scoped under #tab-hip4live to avoid leaks. */
.hip4-state-banner{padding:8px 14px;font-size:var(--text-xs);font-family:var(--font-plex);border-bottom:1px solid var(--border-default);}
.hip4-state-error{background:var(--negative-tint-08);color:var(--negative);}
.hip4-state-warn{background:var(--warn-tint-10);color:var(--warn);}
.hip4-state-empty{background:var(--neutral-bg);color:var(--text-tertiary);}
.hip4-table{width:100%;border-collapse:collapse;font-family:var(--font-plex);font-size:13px;font-variant-numeric:tabular-nums;}
.hip4-table th{padding:9px 14px;text-align:left;font-family:var(--font-plex);font-size:var(--text-xxs);font-weight:var(--weight-semibold);color:var(--text-secondary);text-transform:uppercase;letter-spacing:var(--tracking-label);border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-elevated);position:sticky;top:0;}
.hip4-table th.num{text-align:right;}
.hip4-table td{padding:9px 14px;border-bottom:1px solid var(--border-row);color:var(--text-primary);font-family:var(--font-plex);}
.hip4-table td.num{text-align:right;font-family:var(--font-plex);font-variant-numeric:tabular-nums;}
.hip4-table tr:last-child td{border-bottom:none;}
.hip4-table tr.hip4-row-empty td{border-bottom:none;}
.hip4-underlying{font-weight:600;color:var(--text-primary);}
.hip4-cell-yes{color:var(--positive);font-weight:500;}
.hip4-cell-no{color:var(--negative);font-weight:500;}
/* HIP-4 redesign — category chip, Overview stat tiles, Markets filter chips */
.hip4-cat-chip{display:inline-flex;align-items:center;gap:6px;font-size:var(--text-xxs);font-weight:500;padding:2px 9px;border-radius:999px;font-family:var(--font-plex);background:var(--neutral-bg);color:var(--text-secondary);border:1px solid var(--border-default);}
/* hl.eco-style: each category gets a distinct hue — colored dot + colored label; unknown → neutral gray */
.hip4-cat-chip::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--cat-color,var(--cat-other));flex:0 0 auto;}
.hip4-cat-chip[data-cat="sports"]{--cat-color:var(--cat-sports);color:var(--cat-sports);}
.hip4-cat-chip[data-cat="crypto"]{--cat-color:var(--cat-crypto);color:var(--cat-crypto);}
.hip4-cat-chip[data-cat="politics"]{--cat-color:var(--cat-politics);color:var(--cat-politics);}
.hip4-cat-chip[data-cat="economics"],.hip4-cat-chip[data-cat="macro"]{--cat-color:var(--cat-economics);color:var(--cat-economics);}
.hip4-cat-chip[data-cat="culture"],.hip4-cat-chip[data-cat="popculture"],.hip4-cat-chip[data-cat="pop"]{--cat-color:var(--cat-culture);color:var(--cat-culture);}
/* Probability bar in the % Chance column — mint fill = implied probability (prediction-market style) */
.hip4-prob{display:flex;align-items:center;gap:8px;justify-content:flex-end;}
.hip4-prob-track{flex:0 0 46px;height:4px;border-radius:999px;background:var(--bg-hover);overflow:hidden;}
.hip4-prob-fill{height:100%;background:var(--mint-soft);border-radius:999px;}
.hip4-prob-val{color:var(--mint-soft);font-variant-numeric:tabular-nums;min-width:40px;text-align:right;}
.hip4-stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;}
.hip4-stat{background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:10px;padding:14px 16px;}
.hip4-stat-label{font-size:var(--text-xxs);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.04em;}
.hip4-stat-val{font-size:22px;font-weight:600;color:var(--text-primary);margin-top:5px;font-family:var(--font-plex);font-variant-numeric:tabular-nums;}
.hip4-chip-row{display:flex;flex-wrap:wrap;gap:7px;padding:12px 14px;border-bottom:1px solid var(--border-default);}
.hip4-chip{cursor:pointer;font-family:var(--font-plex);font-size:var(--text-sm);letter-spacing:0.3px;padding:4px 11px;border-radius:var(--radius-md);border:1px solid var(--border-default);background:transparent;color:var(--text-primary);transition:all var(--duration-fast) var(--ease-out);}
.hip4-chip:hover{border-color:var(--border-strong);color:var(--text-primary);}
.hip4-chip.active{background:var(--accent-tint-12);border-color:var(--accent-tint-40);color:var(--accent);}
.hip4-mkt-count{font-size:11px;color:var(--text-tertiary);font-family:var(--font-plex);}
@media (max-width:640px){.hip4-stat-row{grid-template-columns:repeat(2,1fr);}}

/* HIP-4 full-page market detail (M2) — HL-style market view */
.hip4-md{position:fixed;inset:0;z-index:9000;background:var(--bg-base);overflow-y:auto;padding:18px 22px 28px;}
.hip4-md-topbar{display:flex;align-items:center;gap:16px;margin-bottom:14px;}
.hip4-md-back{cursor:pointer;font:inherit;font-size:12px;color:var(--text-secondary);background:transparent;border:1px solid var(--border-default);border-radius:7px;padding:6px 12px;}
.hip4-md-back:hover{border-color:var(--accent);color:var(--text-primary);}
.hip4-md-titlewrap{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
.hip4-md-question{font-size:17px;font-weight:600;color:var(--text-primary);}
.hip4-md-select{font:inherit;font-size:13px;font-weight:500;color:var(--accent);background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:7px;padding:5px 10px;cursor:pointer;}
.hip4-md-select option{color:var(--text-primary);background:var(--bg-elevated);font-weight:400;}
.hip4-md-leg{font-size:13px;font-weight:500;color:var(--accent);}
/* .hip4-md-statbar / .hip4-md-stat-label / .hip4-md-stat-val retired (T2):
   the KPI box now uses the canonical .chart-stats-row / .cs-item / .cs-label /
   .cs-val readout (pos/neg via the global .pos/.neg). */
.hip4-md-tabrow{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:4px;}
.hip4-md-tabs{display:flex;gap:4px;}
.hip4-md-tab{cursor:pointer;font:inherit;font-size:13px;font-weight:500;color:var(--text-tertiary);background:transparent;border:none;border-bottom:2px solid transparent;padding:6px 12px;}
.hip4-md-tab:hover{color:var(--text-primary);}
.hip4-md-tab.active{color:var(--text-primary);border-bottom-color:var(--accent);}
.hip4-md-intervals{display:flex;gap:5px;}
.hip4-md-legend{display:flex;flex-wrap:wrap;gap:14px;padding:6px 2px 0;font-size:11px;color:var(--text-secondary);min-height:6px;}
.hip4-md-leg-item{display:inline-flex;align-items:center;gap:6px;}
.hip4-md-leg-item b{color:var(--text-primary);font-weight:600;}
.hip4-md-dot{width:9px;height:9px;border-radius:50%;display:inline-block;}
.hip4-md-chart{height:380px;width:100%;margin:8px 0 18px;}
.hip4-md-loading,.hip4-md-msg{display:flex;align-items:center;justify-content:center;height:100%;min-height:60px;color:var(--text-tertiary);font-size:12px;}
.hip4-md-msg.sm{min-height:0;height:auto;justify-content:flex-start;padding:6px 0;}
.hip4-md-book{border-top:1px solid var(--border-default);padding-top:14px;}
.hip4-md-book-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;}
.hip4-md-sec-title{font-size:11px;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.04em;}
.hip4-md-bookage{font-size:11px;color:var(--text-tertiary);}
.hip4-md-ladders{display:flex;gap:24px;flex-wrap:wrap;}
.hip4-md-ladder{flex:1;min-width:200px;}
.hip4-md-ladder-h{font-size:11px;color:var(--text-secondary);margin-bottom:5px;}
.hip4-md-book-tbl{width:100%;border-collapse:collapse;}
.hip4-md-book-tbl th{font-size:10px;color:var(--text-secondary);text-align:left;font-weight:400;padding:2px 0;}
.hip4-md-book-tbl th.sz,.hip4-md-book-tbl td.sz{text-align:right;}
.hip4-md-book-tbl td{font-size:11px;padding:2px 0;font-family:var(--font-plex);font-variant-numeric:tabular-nums;}
.hip4-md-book-tbl td.px{padding-right:14px;}
.hip4-md-book-tbl td.sz{color:var(--text-secondary);}
.hip4-md-book-tbl tr.mid td{border-top:1px solid var(--border-default);height:1px;padding:0;}
.hip4-md-settled-banner{display:flex;flex-direction:column;gap:3px;border:1px solid;border-radius:8px;padding:10px 12px;margin-bottom:14px;font-size:13px;}
.hip4-md-settled-det{font-size:11px;color:var(--text-tertiary);}
.hip4-md-disclaimer{margin-top:18px;padding:7px 10px;border-left:3px solid var(--text-disabled);background:var(--neutral-bg);font-size:10.5px;color:var(--text-tertiary);}
@media (max-width:640px){.hip4-md{padding:14px 14px 24px;}.hip4-md-chart{height:300px;}.hip4-md-ladders{gap:14px;}}

.hip4-status-pill{display:inline-block;font-size:var(--text-xxs);font-weight:500;padding:2px 8px;border-radius:6px;letter-spacing:0.4px;font-family:var(--font-plex);text-transform:lowercase;border:1px solid var(--border-default);}
.hip4-status-ok{color:var(--positive);background:var(--positive-tint-10);border-color:var(--positive-tint-30);}
.hip4-status-warn{color:var(--warn);background:var(--warn-tint-10);border-color:var(--warn-tint-35);}
.hip4-status-critical{color:var(--negative);background:var(--negative-tint-10);border-color:var(--negative-tint-30);}
.hip4-status-unknown{color:var(--text-tertiary);background:var(--neutral-bg);}

/* HIP-4 collapsible operational panels (Expired markets, Collector health) —
   diagnostics tucked below the product data as tap-to-expand <details>. */
details.hip4-collapse{padding:0;}
details.hip4-collapse > summary{list-style:none;cursor:pointer;display:flex;align-items:flex-start;gap:10px;padding:14px 18px;}
details.hip4-collapse > summary::-webkit-details-marker{display:none;}
details.hip4-collapse > summary:hover{background:var(--bg-hover);}
.hip4-collapse-chevron{flex:0 0 auto;color:var(--text-tertiary);font-size:var(--text-xs);line-height:1.6;transition:transform 0.15s ease;}
details.hip4-collapse[open] .hip4-collapse-chevron{transform:rotate(90deg);}
.hip4-collapse-titles{flex:1 1 auto;min-width:0;}

/* HIP-4 Outcome Markets — over-time panel grid (6 metric cells, 2-per-row,
   collapses to 1 column on narrow screens). */
.hip4m-section-header{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--space-2);margin-bottom:12px;padding:2px 2px 0;}
.hip4m-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;}
.hip4m-kpi{font-family:var(--font-plex);font-size:15px;font-weight:600;color:var(--mint-soft);font-variant-numeric:tabular-nums;white-space:nowrap;}
.hip4m-chart{height:170px;position:relative;}
@media (max-width:680px){.hip4m-grid{grid-template-columns:1fr;}}

/* Obsidian-theme alignment for the HIP-4 custom .hip4-table — scoped to the two
   themed HIP-4 tabs (the global .hip4-table rules above stay unchanged so any
   other context is unaffected). Font -> Plex, headers/borders -> --p-* tokens;
   semantic cell colors (.hip4-cell-yes/no, status pills) are left intact. */
:is(#tab-hip4live, #tab-hip4competitors) .hip4-table td,
:is(#tab-hip4live, #tab-hip4competitors) .hip4-table td.num { font-family: var(--font-plex); }
:is(#tab-hip4live, #tab-hip4competitors) .hip4-table th { color: var(--text-secondary); background: var(--bg-elevated); border-bottom-color: var(--border-default); }
:is(#tab-hip4live, #tab-hip4competitors) .hip4-table td { border-bottom-color: var(--border-default); }

/* ── TWO-COL GRID ── */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3);margin-bottom:var(--space-3);}
.grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:12px;}
.grid-auto{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-bottom:12px;}

/* ── DATA SOURCE NOTES ── */
.ds-note{padding:5px 14px 7px;font-size:10px;color:var(--text-tertiary);border-top:1px solid var(--border-default);font-family:var(--font-plex);}
.ds-note-strip{font-size:10px;color:var(--text-tertiary);font-family:var(--font-plex);margin-top:-12px;margin-bottom:16px;padding:2px 2px;}

/* ── TABLES ── */
/* Data table — canonical GLOBAL def (Obsidian design); single authority (token-file block removed) */
.data-table{width:100%;border-collapse:collapse;font-family:var(--font-plex);font-size:13px;font-variant-numeric:tabular-nums;}
.data-table th{padding:9px 14px;text-align:left;font-family:var(--font-plex);font-size:var(--text-xxs);font-weight:var(--weight-semibold);color:var(--text-secondary);text-transform:uppercase;letter-spacing:var(--tracking-label);border-bottom:1px solid var(--border-default);white-space:nowrap;}
.data-table th.r{text-align:right;}
.data-table th.sortable{cursor:pointer;user-select:none;text-decoration:underline dotted var(--text-disabled);text-underline-offset:3px;}
.data-table th.sortable:hover{color:var(--text-primary);text-decoration-color:var(--text-secondary);}
.hip3-screener th,.hip3-screener td{padding:8px 11px;}
.hip3-screener thead th{font-size:var(--text-xxs);}
.data-table td{padding:9px 14px;border-bottom:1px solid var(--border-row);color:var(--text-primary);white-space:nowrap;}
.data-table td.num{text-align:right;font-family:var(--font-plex);font-variant-numeric:tabular-nums;}
.data-table td.sym{font-weight:var(--weight-medium);color:var(--accent);}
.data-table td.rank{color:var(--text-tertiary);font-family:var(--font-plex);font-size:var(--text-xs);width:24px;}
.data-table td.muted{color:var(--text-secondary);}
.data-table tr:last-child td{border-bottom:none;}
.data-table tr:hover td{background:var(--bg-hover);}
/* Center-align utility (checkmark / status columns). */
.data-table th.ctr,.data-table td.ctr{text-align:center;}
/* Compact density modifier for dense multi-column tables (peer/protocol/diagnostic
   grids). Replaces per-table inline font-size + padding overrides; base 13px is the
   default. Add `compact` alongside `data-table`. */
.data-table.compact{font-size:11px;}
.data-table.compact th,.data-table.compact td{padding:6px 10px;}
/* D3 utility & single-use component classes (.u-*, .audit-*, .tbl-*) live at the
   END of this file (see "D3 UTILITY & COMPONENT CLASSES (relocated to EOF)") so
   utilities follow ALL components and win same-specificity source-order ties. */

/* ── CHARTS ── */
.chart-wrap{position:relative;}

/* Inner chart card — opt-in via additional class on a .chart-wrap.
   Subtle two-tier inset: border + sunken background only. No padding,
   no margin, no sizing change → cannot disturb layout or canvas size
   by more than 1px (the border). Apply alongside .chart-wrap where
   visual separation between panel-body and chart helps. */
.chart-surface{
  background:var(--bg-sunken);
  border:1px solid var(--border-default);
  border-radius:var(--radius-md);
  box-sizing:border-box;
}

/* Chart overlay buttons (fullscreen + reset zoom) — appear on hover */
.chart-fs-btn,.chart-reset-btn{
  position:absolute;top:var(--space-1);z-index:10;
  background:var(--bg-hover);border:1px solid var(--border-default);
  color:var(--text-tertiary);cursor:pointer;border-radius:var(--radius-sm);
  padding:2px 7px;font-size:var(--text-xs);line-height:1.5;
  font-family:var(--font-plex);opacity:0;transition:opacity var(--duration-fast) var(--ease-out);
  pointer-events:auto;
}
.chart-fs-btn{right:var(--space-1);}
.chart-reset-btn{right:34px;display:none;}
.chart-wrap:hover .chart-fs-btn{opacity:1;}
.chart-wrap:hover .chart-reset-btn{opacity:1;}
.chart-fs-btn:hover,.chart-reset-btn:hover{background:var(--border-strong);color:var(--text-primary);}

/* Expanded-chart popup (floating card over the dimmed site — not a takeover) */
#fs-overlay{
  display:none;position:fixed;inset:0;z-index:9000;
  align-items:center;justify-content:center;padding:32px;
}
.fs-backdrop{position:absolute;inset:0;background:var(--backdrop);}
.fs-shell{
  position:relative;display:flex;flex-direction:column;
  width:min(1040px,100%);height:min(600px,88vh);
  background:var(--bg-elevated);border:1px solid var(--border-strong);
  border-radius:var(--radius-lg);padding:14px 18px 16px;
}
#fs-toolbar{
  display:flex;align-items:center;gap:12px;
  margin-bottom:10px;flex-shrink:0;
}
#fs-title{font-family:var(--font-plex);font-size:12px;color:var(--text-secondary);letter-spacing:0.3px;white-space:nowrap;}
#fs-controls{display:flex;align-items:center;gap:4px;flex-wrap:wrap;flex:1;}
#fs-toolbar button{
  background:var(--bg-hover);border:1px solid var(--border-default);
  color:var(--text-secondary);font-size:11px;cursor:pointer;border-radius:4px;
  padding:4px 12px;font-family:var(--font-plex);transition:all 0.1s;
}
#fs-toolbar button:hover{background:var(--border-strong);color:var(--text-primary);}
#fs-chart-holder{flex:1;position:relative;min-height:0;}
#fs-chart-holder .chart-wrap{height:100%!important;position:relative;}
#fs-chart-holder .chart-fs-btn{display:none;}

/* ── Phase 3 note (2026-07-06): the mobile full-screen chart-detail overlay was
   attempted and reverted. Even with the resize-fix plugin (charts.js) uncapping
   the canvas — which correctly makes INLINE mobile charts render full size — the
   FULLSCREEN chart stays at its inline height because openFullscreen() moves the
   live canvas and its resize() won't grow a moved canvas past ~inline size. So a
   full-screen holder just leaves a void. Making it fill needs an openFullscreen
   change (destroy+recreate the chart at the target size, or a post-layout forced
   resize) — chart-authority (js/charts.js / index.html) territory, tracked as a
   follow-up. Until then the existing centred-card overlay stands. The one line
   below only protects that overlay from the 1-redux 240px cap. */
@media (max-width:768px){
  #fs-chart-holder .chart-wrap{max-height:none!important;}   /* exempt fullscreen from the inline 240px cap */
}

/* ── Stat-card interaction (scrub sparkline + click to expand) ── */
.ms-item.ms-interactive{cursor:pointer;transition:border-color var(--duration-fast) var(--ease-out),transform var(--duration-fast) var(--ease-out);}
.flagship-row .mini-stack .ms-item.ms-interactive:hover,
.metrics-strip.h3-spark-cards .ms-item.ms-interactive:hover{border-color:var(--border-accent);}
.ms-spark .spark-cursor{pointer-events:none;}
#spark-tip{position:fixed;z-index:400;transform:translate(-50%,calc(-100% - 8px));pointer-events:none;display:none;white-space:nowrap;background:var(--bg-sunken);border:1px solid var(--border-strong);border-radius:var(--radius-md);padding:4px 9px;font-family:var(--font-plex);font-size:10px;}
#spark-tip .st-date{color:var(--text-tertiary);letter-spacing:.04em;margin-right:8px;}
#spark-tip .st-val{color:var(--text-primary);font-variant-numeric:tabular-nums;}

/* ── Enriched headline-KPI cards (delta chip + sparkline + click-to-popup) ── */
/* Fixed height + fixed sparkline height so cards stay uniform regardless of how
   many columns the strip has (5-up, 2-up, …) — the sparkline pins to the bottom. */
.ms-item.kpi-card{position:relative;overflow:hidden;background:var(--bg-elevated);border:1px solid var(--border-card);border-radius:var(--radius-lg);padding:13px 15px 0;height:132px;display:flex;flex-direction:column;}
.ms-item.kpi-card .ms-val{margin:6px 0 2px;font-size:23px;}
.ms-item.kpi-card .ms-delta{font-size:10.5px;font-family:var(--font-plex);font-variant-numeric:tabular-nums;letter-spacing:.02em;}
.ms-item.kpi-card .ms-spark{width:calc(100% + 30px);height:44px;margin:auto -15px 0;display:block;}
/* Keep the card opaque on hover (the generic .ms-item:hover goes transparent) —
   just highlight the border, like the site's other panels. */
.ms-item.kpi-card:hover{background:var(--bg-elevated);border-color:var(--border-hover);}
.ms-delta.up{color:var(--positive);}
.ms-delta.down{color:var(--negative);}

/* ── Stat-card expand modal ── */
#stat-modal{position:fixed;inset:0;z-index:500;display:none;align-items:center;justify-content:center;padding:32px;}
.stat-modal-backdrop{position:absolute;inset:0;background:var(--backdrop);}
.stat-modal-shell{position:relative;width:min(920px,100%);height:min(560px,88vh);display:flex;flex-direction:column;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:var(--radius-lg);padding:18px 20px 16px;}
.stat-modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:12px;}
.stat-modal-title{font-family:var(--font-plex);font-size:11px;font-weight:var(--weight-medium);letter-spacing:1.2px;text-transform:uppercase;color:var(--text-secondary);}
.stat-modal-val{font-family:var(--font-plex);font-size:30px;font-weight:var(--weight-semibold);color:var(--mint-soft);letter-spacing:-0.5px;margin-top:6px;font-variant-numeric:tabular-nums;}
.stat-modal-tools{display:flex;align-items:center;gap:8px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;}
.stat-modal-ranges{display:flex;align-items:center;gap:4px;}
.stat-modal-btn,.stat-modal-close{background:var(--bg-sunken);border:1px solid var(--border-default);color:var(--text-secondary);font-family:var(--font-plex);font-size:11px;padding:6px 12px;border-radius:var(--radius-md);cursor:pointer;white-space:nowrap;}
.stat-modal-btn:hover,.stat-modal-close:hover{background:var(--border-strong);color:var(--text-primary);}
.stat-modal-chart{flex:1;position:relative;min-height:0;}
.stat-modal-foot{margin-top:8px;font-family:var(--font-plex);font-size:10px;color:var(--text-tertiary);letter-spacing:.04em;}
.chart-controls{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:8px;}
.ctrl-btn{font-family:var(--font-plex);background:transparent;border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-primary);font-size:var(--text-sm);letter-spacing:0.3px;padding:4px 11px;cursor:pointer;position:relative;transition:all var(--duration-fast) var(--ease-out);}
.ctrl-btn:hover{color:var(--text-primary);border-color:var(--border-strong);}
.ctrl-btn.active{background:var(--accent-tint-12);border-color:var(--accent-tint-40);color:var(--accent);box-shadow:none;}
.sd-range-controls{display:flex;align-items:center;justify-content:flex-end;gap:6px;margin-top:6px;flex-wrap:wrap;}
.sd-filter-group{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.sd-filter-label{font-family:var(--font-plex);font-size:9px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.08em;white-space:nowrap;margin-right:2px;}
.sd-date-field{display:inline-flex;align-items:center;gap:5px;font-family:var(--font-plex);font-size:9px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.35px;}
.sd-date-field input{height:22px;min-width:118px;background:var(--bg-sunken);border:1px solid var(--border-default);border-radius:4px;color:var(--text-secondary);font:10px var(--font-plex);padding:2px 5px;color-scheme:dark;}
.sd-date-field input:hover{border-color:var(--border-strong);color:var(--text-primary);}
.sd-date-field input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 1px var(--accent-bg);}
.sd-navigator-wrap{height:34px;margin-top:5px;position:relative;border-top:1px solid var(--border-default);padding-top:4px;cursor:crosshair;}
.sd-navigator-wrap canvas{display:block;width:100%;height:100%;}
.sd-split-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;margin-top:10px;}
.sd-split-frame{min-width:0;border:1px solid var(--border-default);background:var(--bg-sunken);border-radius:var(--radius-lg);padding:10px 10px 8px;}
.sd-split-label{font-family:var(--font-plex);font-size:10px;line-height:1;text-transform:uppercase;letter-spacing:.12em;color:var(--text-secondary);margin:0 0 8px 2px;}
@media(max-width:900px){.sd-split-grid{grid-template-columns:1fr;}}
/* Chip variant — used by HIP-3 Daily OI deployer toggles. chip-off dims the
   button while keeping the color swatch visible so legend-to-chart mapping
   stays obvious when a series is hidden. */
.ctrl-btn.chip.chip-off{opacity:0.35;}
.ctrl-btn.chip.chip-off:hover{opacity:0.6;}
/* Segmented toggle — wrapper class for grouped .ctrl-btn timeframe selectors.
   Replaces inline style="display:flex;gap:4px;" with a named class. Buttons
   keep .ctrl-btn + .active + onclick handlers; no JS change required. */
.segmented-toggle{display:inline-flex;gap:4px;align-items:center;}
.ctrl-sep{width:1px;height:18px;background:var(--border-default);}
/* Inset divided stat readout — canonical GLOBAL def (Obsidian design) */
.chart-stats-row{display:flex;flex-wrap:wrap;gap:var(--space-3);background:transparent;margin-bottom:var(--space-4);}
.cs-item{position:relative;overflow:hidden;flex:1 1 0;min-width:140px;display:flex;flex-direction:column;gap:0;background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:var(--radius-lg);padding:16px 18px;transition:border-color var(--duration-fast) var(--ease-out);}
.cs-item::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:transparent;}
/* KPI-row hover = ONLY recolor the number — no top accent line, no bright border flash (2026-07-01) */
.cs-item:hover .cs-val{color:var(--accent);}
.cs-item.active::before{background:var(--accent);}
.cs-item.active .cs-val{color:var(--accent);}
.cs-label{font-family:var(--font-plex);font-size:10px;font-weight:var(--weight-medium);letter-spacing:1.2px;text-transform:uppercase;color:var(--text-secondary);}
.cs-val{font-family:var(--font-plex);font-size:27px;font-weight:var(--weight-semibold);color:var(--text-primary);margin-top:9px;letter-spacing:-0.5px;font-variant-numeric:tabular-nums;line-height:1.04;}
.cs-sub{font-size:11px;color:var(--text-tertiary);font-family:var(--font-plex);}
.cs-sub.cs-sub-sm{font-size:9px;margin-top:2px;}
/* Mobile: divided readout wraps 2-up (re-homed from the deleted scoped mobile rule) */
@media (max-width:768px){
  .cs-item{flex-basis:calc(50% - var(--space-3));min-width:0;}
}

/* ── FUNDING RATE COLORS ── */
.fund-pos{color:var(--positive);}
.fund-neg{color:var(--negative);}
.fund-neu{color:var(--text-tertiary);}
.badge{font-size:var(--text-xxs);font-weight:500;padding:2px 7px;border-radius:var(--radius-sm);letter-spacing:0.3px;}
.badge-pos{background:var(--positive-bg);color:var(--positive);}
.badge-neg{background:var(--negative-bg);color:var(--negative);}
.badge-neutral{background:var(--border-default);color:var(--text-tertiary);}

/* ── DUNE PLACEHOLDER ── */
/* Dashed --text-tertiary preserves "held-back / placeholder" visual signal without the amber warning tone. */
.dune-placeholder{background:var(--neutral-bg);border:1px dashed var(--text-tertiary);border-radius:6px;padding:24px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:8px;}
.dune-placeholder .dp-icon{font-size:28px;opacity:0.5;}
.dune-placeholder .dp-title{font-size:13px;font-weight:500;color:var(--negative);}
.dune-placeholder .dp-desc{font-size:11px;color:var(--text-tertiary);max-width:340px;line-height:1.5;}
.dune-placeholder .dp-badge{font-size:10px;font-weight:500;color:var(--negative);background:var(--neutral-bg);padding:3px 10px;border-radius:4px;}

/* ── PENDING CHART (premium neutral — replaces dune-placeholder for non-warning use) ── */
.pend-chart{background:var(--bg-sunken);border:1px solid var(--border-default);border-radius:6px;padding:24px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:8px;}
.pend-chart .pc-icon{font-size:26px;opacity:0.35;}
.pend-chart .pc-title{font-size:13px;font-weight:500;color:var(--text-secondary);}
.pend-chart .pc-desc{font-size:11px;color:var(--text-tertiary);max-width:340px;line-height:1.5;}
.pend-chart .pc-badge{font-size:10px;color:var(--text-disabled);background:var(--bg-hover);border:1px solid var(--border-default);padding:3px 10px;border-radius:4px;}

/* ── SEARCH BAR ── */
.search-bar{background:var(--bg-sunken);border:1px solid var(--border-default);border-radius:4px;color:var(--text-primary);font-size:12px;padding:5px 10px;outline:none;width:180px;}
.search-bar:focus{border-color:var(--accent);}

/* ── STAT CARDS ── */
.stat-card{position:relative;overflow:hidden;background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:4px;transition:border-color var(--duration-fast) var(--ease-out);}
.stat-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:transparent;}
.stat-card:hover{border-color:var(--border-strong);}
.stat-card.active::before{background:var(--accent);}
.stat-card.active .sc-val{color:var(--accent);}
.sc-label{font-family:var(--font-plex);font-size:9px;font-weight:500;color:var(--text-secondary);text-transform:uppercase;letter-spacing:1px;}
.sc-val{font-family:var(--font-plex);font-size:17px;font-weight:var(--weight-semibold);color:var(--text-primary);font-variant-numeric:tabular-nums;}
.sc-sub{font-size:10px;color:var(--text-tertiary);}

/* ── UNLOCK ROWS ── */
#tab-tokenomics .panel.unlock-schedule-panel > .panel-header{gap:18px;padding-bottom:12px;}
#tab-tokenomics .unlock-schedule-panel .panel-title{white-space:nowrap;flex:0 0 auto;}
#tab-tokenomics .unlock-schedule-panel .panel-sub{max-width:360px;line-height:1.4;}
.unlock-summary-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding:12px 16px 4px;}
.unlock-summary-grid .cs-item{background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:6px;padding:12px 12px;}
.unlock-summary-grid .cs-val{font-size:14px;}
.unlock-impact-val{color:var(--negative);}
.unlock-days-val{color:var(--text-tertiary);}
.unlock-table-head{display:grid;grid-template-columns:minmax(108px,0.8fr) minmax(180px,1.5fr) minmax(136px,0.85fr);gap:16px;padding:14px 16px 7px;color:var(--text-disabled);font-size:9px;font-weight:600;letter-spacing:0.7px;text-transform:uppercase;}
.unlock-row{display:grid;grid-template-columns:minmax(108px,0.8fr) minmax(180px,1.5fr) minmax(136px,0.85fr);gap:16px;align-items:center;margin:0 16px;padding:13px 0;border-bottom:1px solid var(--border-default);}
.unlock-row:last-child{border-bottom:none;}
.unlock-row.is-next{margin-top:2px;margin-bottom:2px;padding:12px 12px;border:1px solid var(--negative-tint-30);border-radius:6px;background:var(--negative-tint-05);}
.unlock-row.is-past:not(.is-next){opacity:0.62;}
.ur-datecell{min-width:0;}
.ur-date-main{display:flex;align-items:center;gap:8px;font-family:var(--font-plex);font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;}
.ur-dot{width:8px;height:8px;border-radius:50%;flex:0 0 8px;box-shadow:0 0 0 3px var(--negative-tint-08);}
.ur-status{margin-left:16px;margin-top:5px;font-size:10px;color:var(--text-tertiary);}
.ur-desc{min-width:0;}
.ur-desc-title{font-size:12px;line-height:1.35;color:var(--text-secondary);}
.ur-desc-meta{margin-top:4px;font-size:10px;line-height:1.35;color:var(--text-disabled);}
.ur-metrics{display:flex;flex-direction:column;align-items:flex-end;gap:5px;min-width:0;}
.ur-amount{font-size:12px;font-family:var(--font-plex);font-weight:600;color:var(--text-primary);white-space:nowrap;}
.ur-impact-stack{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap;}
.ur-impact-stack span{font-size:10px;color:var(--text-tertiary);background:var(--bg-sunken);border:1px solid var(--border-default);border-radius:999px;padding:3px 7px;white-space:nowrap;}
.unlock-row.is-next .ur-impact-stack span{border-color:var(--negative-tint-30);color:var(--negative);}
.ur-market{font-size:10px;color:var(--text-disabled);white-space:nowrap;}

/* ── COMPETITION BARS ── */
.vol-bar-row{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--border-default);transition:background var(--duration-fast) var(--ease-out);}
.vol-bar-row:last-child{border-bottom:none;}
.vol-bar-row:hover{background:var(--bg-hover);}
/* Hover tooltip — opt-in via data-tooltip attribute. Currently scoped to
   the Spot+DEX bar rows, which mix time bases (HL rolling-24H vs CEX
   latest-UTC-day) — making the per-row time basis + source visible on
   hover answers "why is this number framed differently than the others?"
   Pure-CSS via ::after, no JS. */
.vol-bar-row[data-tooltip]{position:relative;}
.vol-bar-row[data-tooltip]:hover::after{
  content:attr(data-tooltip);
  position:absolute;
  left:50%;
  bottom:calc(100% + 6px);
  transform:translateX(-50%);
  background:var(--bg-elevated);
  border:1px solid var(--border-default);
  border-radius:var(--radius-md);
  padding:6px 10px;
  white-space:pre-line;
  font-size:var(--text-xxs);
  font-family:var(--font-plex);
  line-height:1.5;
  color:var(--text-primary);
  z-index:100;
  pointer-events:none;
  min-width:240px;
  max-width:340px;
}
/* Subtle row hover for the dedicated rolling-24H + timeseries tables.
   These tables use ad-hoc inline styling rather than .data-table, so the
   hover is scoped by tbody id to avoid bleeding into other tables. */
#pv24-tbody tr,
#pvts-tbody tr{transition:background var(--duration-fast) var(--ease-out);}
#pv24-tbody tr:hover td,
#pvts-tbody tr:hover td{background:var(--bg-hover);}
.vbr-name{font-size:11px;font-weight:500;color:var(--text-primary);width:80px;flex-shrink:0;}
.vbr-bar{flex:1;height:8px;background:var(--bg-sunken);border-radius:4px;overflow:hidden;}
.vbr-fill{height:100%;border-radius:4px;transition:width 0.4s ease;}
.vbr-val{font-size:11px;font-family:var(--font-plex);color:var(--text-primary);width:70px;text-align:right;flex-shrink:0;}
.vbr-pct{font-size:10px;color:var(--text-tertiary);width:36px;text-align:right;flex-shrink:0;}

/* ── SPOT DASHBOARD ── */
.spot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px;margin-bottom:12px;}
.spot-token-card{background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:5px;padding:10px;display:flex;flex-direction:column;gap:3px;cursor:default;transition:border-color 0.15s;}
.stc-sym{font-size:12px;font-weight:500;color:var(--accent);}
.stc-price{font-size:13px;font-weight:500;font-family:var(--font-plex);color:var(--text-primary);}
.stc-chg{font-size:10px;}
.stc-vol{font-size:10px;color:var(--text-tertiary);}

/* ── MISC ── */
.section-gap{margin-bottom:18px;}
.up{color:var(--positive);}
.down{color:var(--negative);}
.ts-footer{padding:10px 20px;border-top:1px solid var(--border-default);font-size:10px;color:var(--text-tertiary);display:flex;gap:16px;flex-wrap:wrap;background:var(--bg-elevated);}

/* ═══════════════════════════════════════════════════════════════
   MOBILE RESPONSIVE — 390px baseline (iPhone), 768px tablet
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════
   MOBILE-FIRST RESPONSIVE SYSTEM
   Breakpoints: 390px (phone), 480px (large phone), 768px (tablet boundary)
   ═══════════════════════════════════════════════════════════════════════ */

/* ── PHONE BASE (≤768px) ── */
@media (max-width: 768px) {

  /* ── HEADER: compact single-bar layout ── */
  #header {
    display: flex !important;   /* override the desktop 3-col grid → compact single bar on mobile */
    height: 52px;
    flex-direction: row;
    align-items: center;
    padding: 0;
    position: fixed;
    top: 0;
  }
  .header-logo {
    width: auto;
    border-right: 1px solid var(--border-default);
    border-bottom: none;
    padding: 0 14px;
    height: 100%;
    flex-shrink: 0;
  }
  .logo-sub { display: none; }
  .header-ticker {
    flex: 1;
    padding: 0 10px;
    gap: 14px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    flex-wrap: nowrap;
    border-bottom: none;
    height: 100%;
    align-items: center;
  }
  .header-ticker::-webkit-scrollbar { display: none; }
  .ht-item { flex-shrink: 0; }
  .ht-label { font-size: 8px; }
  .ht-val { font-size: 12px; }
  .ht-sub { font-size: 9px; }
  .header-right { padding: 0 10px; flex-shrink: 0; border-bottom: none; }
  .countdown-txt { display: none; }

  /* ── DASH TABS: keep visible on mobile, scroll horizontally ──
     PR-UIQA-1: previously display:none with no replacement nav, leaving
     mobile users stranded on the default Perps tab. Re-enable as a
     horizontally-scrollable bar so all 7 dashboards remain reachable. */
  #dash-tabs {
    display: flex;
    flex: 1;
    min-width: 0;
    justify-content: flex-start !important;   /* left-align + scroll on mobile — beat the later desktop centered rule */
    padding-left: 0;
    padding-right: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    flex-wrap: nowrap;
  }
  #dash-tabs::-webkit-scrollbar { display: none; }
  .dash-tab { flex-shrink: 0; }
  .dash-tab-sep { flex-shrink: 0; }

  /* ── SHELL & SIDEBAR ── */
  #shell { padding-top: 52px; /* mobile header is a compact 52px single bar */ }
  #sidebar { display: none !important; }
  #sidebar-expand-btn { display: none !important; }
  #content { margin-left: 0 !important; }

  /* ── CONTENT TOPBAR: sticky section label ── */
  .content-topbar {
    top: 52px;
    padding: 0 12px;
    height: 34px;
    gap: 8px;
    position: sticky;
    z-index: 100;
  }
  .section-title { font-size: 12px; font-weight: 500; }
  .section-sub { display: none; }
  .refresh-btn { font-size: 10px; padding: 2px 8px; }

  /* ── PAGE BODY ── */
  /* PR-UIQA-2B-a: bottom-padding reduced 74px → 16px after #mobile-nav
     removal. The 74px reserved space for the 56px fixed bottom-nav. */
  .page-body { padding: 10px 10px 16px; }

  /* ── SECTION GAPS ── */
  .section-gap { margin-bottom: 10px; }

  /* ── METRICS STRIP: 2-col grid, larger tap targets ── */
  .metrics-strip {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 1px;
    margin-bottom: 10px;
  }
  .ms-item { padding: 10px 12px; min-height: 56px; justify-content: center; }
  .ms-label { font-size: 8px; letter-spacing: 0.3px; }
  .ms-val { font-size: 15px; line-height: 1.2; }
  .ms-sub { font-size: 9px; }

  /* ── GRIDS: always single column ── */
  .grid-2, .grid-3, .grid-auto {
    grid-template-columns: 1fr !important;
    gap: 10px;
  }

  /* ── PANELS ── */
  .panel-header { flex-wrap: wrap; gap: 6px; padding: 10px var(--space-3) var(--space-2); }
  .panel-title { font-size: var(--text-base); }
  .panel-sub { font-size: var(--text-xxs); line-height: 1.4; }
  .panel-body { padding: 10px var(--space-3); }
  .live-tag { font-size: 8px; padding: 2px 5px; }

  /* ── CHART STATS ROW: tighter mobile margin (base is now a flex divided card; grid-cols + gap dropped) ── */
  .chart-stats-row {
    margin-bottom: 10px;
  }
  .cs-label { font-size: 8px; }
  .cs-val { font-size: 12px; }
  .cs-sub { font-size: 9px; }

  /* ── CHARTS: cap height on phones (1-redux, 2026-07-06) ──
     The resize-fix plugin (js/charts.js uncapChartWrapCanvas) sets the canvas
     max-height:none inline so charts fill their wrap. Without a cap the tall
     .u-h* container classes (up to 360px) would dominate a 375px screen. So cap
     the WRAP height — NOT the canvas (the plugin defeats any canvas max-height).
     max-height only bites wraps taller than the cap; short charts are untouched.
     The fullscreen chart is exempted in the #fs-overlay mobile block below.
     (Replaces the old `.chart-wrap canvas{max-height:160px}` + `[style*=height]`
     rules, both dead: the cap is now plugin-defeated and the inline-height
     selectors never matched after the .u-h* utility migration.) */
  .chart-wrap { max-height: 240px; }

  /* ── CTRL BUTTONS: compact but tappable ── */
  .ctrl-btn { font-size: var(--text-xs); padding: var(--space-1) var(--space-2); min-height: 40px; display: inline-flex; align-items: center; justify-content: center; }  /* audit A4: ≥40px tap target */
  .chart-controls { flex-wrap: wrap; gap: var(--space-1); }

  /* ── TABLES: horizontal scroll with visual cue ── */
  .tbl-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    position: relative;
  }
  .data-table { min-width: 520px; font-size: 10px; }
  .data-table th { font-size: 8px; padding: 5px 6px; white-space: nowrap; }
  .data-table td { padding: 5px 6px; white-space: nowrap; }

  /* HIP-3 table: enforce scroll, show scroll indicator */
  #tab-buypress .tbl-scroll::after {
    content: '← scroll →';
    display: block;
    text-align: center;
    font-size: 9px;
    color: var(--text-disabled);
    padding: 4px;
    border-top: 1px solid var(--border-default);
  }

  /* Competition table: fewer columns via column hiding */
  #comp-table td:nth-child(5),
  #comp-table th:nth-child(5),
  #comp-table td:nth-child(7),
  #comp-table th:nth-child(7) { display: none; }

  /* ── COMPETITION BARS: tighter layout ── */
  .vol-bar-row { gap: 6px; padding: 6px 0; }
  .vbr-name { width: 72px; font-size: 10px; }
  .vbr-bar { height: 8px; }
  .vbr-val { width: 60px; font-size: 10px; text-align: right; }
  .vbr-pct { width: 32px; font-size: 9px; }

  /* ── STAT CARDS ── */
  .stat-card { padding: 10px 12px; }
  .sc-label { font-size: 8px; }
  .sc-val { font-size: 17px; }
  .sc-sub { font-size: 9px; }

  /* ── UNLOCK ROWS ── */
  .unlock-summary-grid { grid-template-columns: 1fr; padding: 10px 12px 2px; }
  .unlock-table-head { display: none; }
  .unlock-row,
  .unlock-row.is-next { grid-template-columns: 1fr; gap: 10px; margin: 0 12px; padding: 12px 0; }
  .unlock-row.is-next { padding: 12px; }
  .ur-metrics { align-items: flex-start; }
  .ur-impact-stack { justify-content: flex-start; }

  /* ── DUNE PLACEHOLDERS: compact ── */
  .dune-placeholder { padding: 18px 16px; gap: 8px; }
  .dp-icon { font-size: 24px; }
  .dp-title { font-size: 12px; }
  .dp-desc { font-size: 10px; line-height: 1.5; }
  .dp-badge { font-size: 9px; padding: 3px 8px; }

  /* ── SPOT GRID ── */
  .spot-grid { grid-template-columns: repeat(2, 1fr); gap: 6px; }

  /* ── SEARCH BAR ── */
  .search-bar { width: 100%; max-width: 100%; font-size: 13px; padding: 8px 10px; }

  /* ── FOOTER ── */
  .ts-footer { padding: 8px 12px; font-size: 9px; gap: 8px; margin-bottom: 56px; flex-wrap: wrap; }

  /* ── BADGE TAGS ── */
  .badge { font-size: 8px; padding: 2px 5px; }

  /* ── HYPE OVERVIEW: metrics strip override ── */
  #tab-hypeoverview .metrics-strip {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* ── COMPETITION METRICS STRIP ── */
  #tab-competition .metrics-strip {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* ── HIP3 METRICS STRIP ── */
  #tab-buypress .metrics-strip {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* ── TOKENOMICS METRICS STRIP ── */
  #tab-tokenomics .metrics-strip {
    grid-template-columns: repeat(3, 1fr) !important;
  }
  #tab-tokenomics .ms-val { font-size: 13px; }

  #tab-buypress .panel-header > div:last-child {
    width: 100%;
    justify-content: space-between;
  }

  /* ── HYPE PANEL OVERRIDES ── */
  #tab-hypeoverview .grid-2 { gap: var(--space-2); }

  /* ── INFO BARS ── */
  [style*="display:flex;align-items:center;gap:16px"] {
    flex-direction: column;
    align-items: flex-start !important;
    gap: 6px !important;
  }

  /* ── SUPPLY CHART PANEL: enforce min height ── */
  #tab-tokenomics .panel-body[style*="height:240px"] {
    height: 200px !important;
  }

  /* ── DEX RANKING integration info bar ── */
  [style*="DUNE_API_KEY"] { display: none; }
}

/* ── PHONE (≤480px): free up header-right space so the ticker is readable ──
   PR-UIQA-1: at ≤480px the .header-right block (LIVE pill + BUILD VERIFIED
   badge + density toggle + countdown) was stealing ~245px from the ticker,
   which collapsed to ~20px. Hide the two non-essential items; LIVE pill and
   search trigger remain reachable. */
@media (max-width: 480px) {
  .build-badge { display: none !important; }
  .density-btn { display: none !important; }
}

/* ── SMALL PHONE (≤430px): tighten further ── */
@media (max-width: 430px) {
  .header-logo { padding: 0 10px; }
  .logo-text { font-size: 12px; }
  .logo-icon { width: 22px; height: 22px; font-size: 10px; }
  .ht-val { font-size: 11px; }
  .ms-val { font-size: 13px; }
  .ms-item { padding: 8px 10px; min-height: 52px; }
  .page-body { padding: 8px 8px 16px; }
  .panel-body { padding: var(--space-2) 10px; }
  .panel-header { padding: var(--space-2) 10px 6px; }
  .ctrl-btn { font-size: var(--text-xxs); padding: 3px 7px; min-height: 40px; }  /* audit A4: ≥40px tap target */
  .vbr-name { width: 60px; }
  .chart-wrap canvas { max-height: 145px !important; }
}

/* ════════════════════════════════════════════════════════════════════
   PR-H — eliminate 390px horizontal clipping in five inline-styled,
   JS-built mini-grids the class-based mobile rules above can't reach
   (their grid-template-columns is set inline, which beats class CSS, so
   the over-wide column counts survive into narrow viewports). Scoped by
   panel id; mobile only; collapses over-wide strips and lets grid children
   shrink (min-width:0) so long values wrap instead of forcing the track
   wide. No desktop change, no clipping, no JS/markup change. Enforced by
   the full-panel smoke's 390px per-element overflow scan. */
@media (max-width: 768px) {
  /* HIP-3 → Volume by Category: inline repeat(7,1fr) KPI strip */
  #hip3-cat-vol-panel .chart-stats-row { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  #hip3-cat-vol-panel .chart-stats-row > .cs-item { min-width: 0; }

  /* HYPE → Token Supply → Holder Distribution: inline repeat(5,1fr) stat
     strip + a .grid-2 chart row whose children (524px) won't shrink. */
  #holder-distribution-panel div[style*="grid-template-columns:repeat(5"] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  #holder-distribution-panel .ms-item { min-width: 0; }
  #holder-distribution-panel .grid-2 > * { min-width: 0; }

  /* HYPE → Mkt Compare (funding-rate cards) · HYPE → Signals (divergence
     cards) · HIP-4 Competitors (BTC HL-vs-Polymarket cards): inline 1fr-track
     grids whose children's min-content forces the tracks past the viewport —
     min-width:0 lets the 1fr tracks resolve to real fractions and the values
     wrap. Column count is preserved. */
  #dyn-panel-funding-rate-comparison div[style*="grid-template-columns"] > *,
  #dyn-panel-funding-divergence div[style*="grid-template-columns"] > *,
  #hip4comp-btc div[style*="grid-template-columns"] > * { min-width: 0; }
}

/* ── TABLET (481px–768px): 2-col charts ── */
@media (min-width: 481px) and (max-width: 768px) {
  .metrics-strip { grid-template-columns: repeat(3, 1fr) !important; }
  .ms-val { font-size: 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   ELITE POLISH — Loading, Animation, Micro-interactions
   ═══════════════════════════════════════════════════════════════════════ */

/* ── SKELETON SHIMMER ── */
@keyframes shimmer {
  0%   { background-position: -400px 0; }
  100% { background-position: 400px 0; }
}
.skeleton {
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--bg-hover) 37%, var(--bg-sunken) 63%);
  background-size: 800px 100%;
  animation: shimmer 1.8s ease-in-out infinite;
  border-radius: 3px;
  color: transparent !important;
  pointer-events: none;
  user-select: none;
}
.skeleton * { visibility: hidden; }
.skeleton-val {
  display: inline-block;
  min-width: 60px;
  height: 1.1em;
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--bg-hover) 37%, var(--bg-sunken) 63%);
  background-size: 800px 100%;
  animation: shimmer 1.8s ease-in-out infinite;
  border-radius: 3px;
  vertical-align: middle;
}
.skeleton-bar {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--bg-hover) 37%, var(--bg-sunken) 63%);
  background-size: 800px 100%;
  animation: shimmer 1.8s ease-in-out infinite;
  border-radius: 4px;
}
.skeleton-row td {
  position: relative;
  overflow: hidden;
}
.skeleton-row td::after {
  content: '';
  display: block;
  width: 70%;
  height: 10px;
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--bg-hover) 37%, var(--bg-sunken) 63%);
  background-size: 800px 100%;
  animation: shimmer 1.8s ease-in-out infinite;
  border-radius: 3px;
}

/* ── CHART LOADING OVERLAY (premium) ── */
.chart-loading-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--overlay-scrim);
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  color: var(--text-disabled);
  font-family: var(--font-plex);
  pointer-events: none;
  text-align: center;
  padding: 0 var(--space-4);
  backdrop-filter: blur(2px);
  transition: opacity var(--duration-med) var(--ease-out);
  letter-spacing: 0.3px;
}
.chart-loading-overlay::before {
  content: '';
  display: block;
  width: 120px;
  height: 3px;
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--accent-tint-12) 50%, var(--bg-sunken) 75%);
  background-size: 240px 100%;
  animation: shimmer 1.8s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.chart-loading-overlay.fade-out {
  opacity: 0;
  pointer-events: none;
}
.chart-loading-overlay.fade-out::before {
  animation: none;
}
/* Error state: replaces shimmer with warning icon + retry button */
.chart-loading-overlay.error-state {
  pointer-events: auto;
  background: var(--overlay-scrim-strong);
  color: var(--text-tertiary);
}
.chart-loading-overlay.error-state::before {
  content: '⚠';
  width: auto;
  height: auto;
  background: none;
  animation: none;
  font-size: 18px;
  line-height: 1;
}
.chart-loading-overlay .retry-btn {
  margin-top: var(--space-1);
  padding: var(--space-1) 14px;
  font-size: var(--text-xs);
  font-family: var(--font-plex);
  background: var(--accent-tint-12);
  border: 1px solid var(--accent-tint-20);
  color: var(--text-tertiary);
  border-radius: var(--radius-md);
  cursor: pointer;
  letter-spacing: 0.3px;
  transition: background var(--duration-fast) var(--ease-out);
}
.chart-loading-overlay .retry-btn:hover {
  background: var(--accent-tint-20);
}

/* ── BASIS DOTS (audit D1) ──
   Wordless live-vs-closed indicator next to KPI labels whose twin on another
   tab uses a different basis (e.g. HIP-3 OI: daily close vs live snapshot).
   Filled accent dot = live; hollow dot = closed UTC day. Hover title carries
   the words. */
.basis-dot{display:inline-block;width:6px;height:6px;border-radius:50%;margin-left:6px;vertical-align:1px;}
.basis-dot--live{background:var(--accent);box-shadow:var(--shadow-glow);}
.basis-dot--closed{border:1px solid var(--text-tertiary);background:transparent;}

/* ── KPI LOADING SKELETON (audit D3/U2) ──
   LOADING state for KPI values: shimmer instead of the null dash, so "—"
   exclusively means "no data exists" — never "still fetching". Render fns
   remove .is-loading when the real value lands. Reuses @keyframes shimmer. */
.ms-val.is-loading, .cs-val.is-loading, .ph-val.is-loading{
  color:transparent !important; border-radius:var(--radius-sm); min-width:48px;
  background:linear-gradient(90deg, var(--bg-sunken) 25%, var(--accent-tint-08) 50%, var(--bg-sunken) 75%);
  background-size:400px 100%; animation:shimmer 1.6s ease-in-out infinite;
}

/* ── TABLE LOADING SKELETONS (mobile Phase 5) ──
   The table half of the same skeleton system as .is-loading above: shimmer
   rows while a markets table's data loads, cleared when the render fn fills
   the <tbody>. LOADING only — the "no rows match" empty state keeps plain text
   (honest states). Same shimmer recipe. Injected by js/mobile-tables.js
   (skelTableRows). */
.skel-row td { padding: 10px 14px; border-bottom: 1px solid var(--border-row); }
.skel-line {
  display: block; height: 11px; border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--accent-tint-08) 50%, var(--bg-sunken) 75%);
  background-size: 400px 100%; animation: shimmer 1.6s ease-in-out infinite;
}
.skel-row:nth-child(odd) .skel-line { width: 82%; }
.skel-row:nth-child(3n) .skel-line { width: 64%; }
@media (max-width:768px){
  /* in the mobile card layouts, a skeleton row is a simple shimmer card (no grid/chevron) */
  .mtbl-cards .data-table tr.skel-row,
  #hip4-markets-full-table tr.skel-row {
    display: block; background: var(--bg-elevated); border: 1px solid var(--border-card);
    border-radius: var(--radius-lg); padding: 15px 13px; margin-bottom: 8px;
  }
  .mtbl-cards .data-table tr.skel-row::after,
  #hip4-markets-full-table tr.skel-row::after { display: none; }
  .mtbl-cards .data-table tr.skel-row td,
  #hip4-markets-full-table tr.skel-row td { display: block; padding: 0; border: none; }
}

/* ── FADE IN ANIMATION ── */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.fade-in {
  animation: fadeIn 0.3s ease forwards;
}
.fade-in-up {
  animation: fadeInUp 0.35s ease forwards;
}

/* Value reveal — used when KPI values appear */
.val-reveal {
  animation: fadeIn 0.25s ease forwards;
}

/* ── TAB PANEL TRANSITIONS ── */
.tab-panel.active {
  display: block;
  animation: fadeIn 0.2s ease;
}

/* ── BUILD VERIFIED badge ── */
.build-badge {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border-default);
  font-size: var(--text-xxs);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  margin-right: var(--space-2);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
}

/* ── HOVER STATES — KPI cards (steady bg, border-only shift — design) ── */
.ms-item:hover {
  background: transparent;
}

/* ── HOVER STATES — Panels ── */
.panel {
  transition: border-color var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.panel:hover {
  border-color: var(--border-hover);     /* faint soft-mint edge — hl.eco .card:hover (2026-07-01) */
  background: var(--bg-hover-soft);       /* barely-there lift, not the big --bg-hover jump */
}
/* the flagship + HIP-3 stat cards get the same lift so they don't feel dead */
.flagship-row .mini-stack .ms-item,
.metrics-strip.h3-spark-cards .ms-item {
  transition: border-color var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.flagship-row .mini-stack .ms-item:hover,
.metrics-strip.h3-spark-cards .ms-item:hover {
  border-color: var(--border-hover);
  background: var(--bg-hover-soft);
}

/* ── HOVER STATES — Stat cards ── */
.stat-card {
  transition: border-color 0.15s ease, background 0.15s ease;
}
.stat-card:hover {
  border-color: var(--border-hover);
  background: var(--bg-hover-soft);
}

/* ── TABLE ROW HOVER — smoother ── */
.data-table tr {
  transition: background var(--duration-fast) var(--ease-out);
}

/* ── BUTTON POLISH ── (transition/position/active-style now in the canonical base ~L356) */
.ctrl-btn:active {
  transform: scale(0.96);
}

.refresh-btn {
  transition: all var(--duration-fast) var(--ease-out);
}
.refresh-btn:active {
  transform: scale(0.95);
}

/* ── DASH TAB POLISH ── */
.dash-tab {
  transition: color 0.15s ease, border-color 0.2s ease, background 0.15s ease;
}
.dash-tab:hover {
  background: var(--bg-hover);
}
.dash-tab.active {
  background: var(--accent-bg2);
}

/* ── SIDEBAR ITEM POLISH ── */
.sidebar-item {
  transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}

/* ── LIVE BADGE — refined pulse ── */
@keyframes livePulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 var(--accent-glow); }
  50%      { opacity: 0.7; box-shadow: 0 0 0 3px transparent; }
}
@keyframes livePulseFast {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 var(--accent-glow); }
  50%      { opacity: 0.7; box-shadow: 0 0 0 3px transparent; }
}
.live-dot {
  animation: livePulse 2s ease-in-out infinite;
}
.syncing-dot {
  animation: livePulseFast 600ms ease-in-out infinite;
}

/* ── LOADING BADGE — subtle pulse ── */
@keyframes loadPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}
.loading-badge {
  animation: loadPulse 1.5s ease-in-out infinite;
}

/* ── HEADER TICKER VALUES — transition for number updates ── */
.ht-val, .ms-val, .cs-val, .sc-val {
  transition: color 0.2s ease;
}

/* ── SPOT TOKEN CARD HOVER ── */
.spot-token-card {
  transition: border-color 0.15s ease;
}
.spot-token-card:hover {
  border-color: var(--border-strong);
}

/* ── SEARCH BAR ── */
.search-bar {
  transition: border-color 0.15s ease;
}
.search-bar:focus {
  border-color: var(--accent);
  outline: none;
}

/* ── CHART FULLSCREEN BUTTON — smoother reveal ── */
.chart-fs-btn, .chart-reset-btn {
  transition: opacity var(--duration-med) var(--ease-out), background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}

/* ── COMPETITION BAR FILLS — animated width ── */
.vbr-fill {
  transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── STALE INDICATOR — subtle warning ── */
.stale-indicator {
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-tertiary);
  margin-left: 4px;
  opacity: 0.7;
  vertical-align: middle;
}

/* ── DS-NOTE polish: slightly more recessed ── */
.ds-note {
  background: var(--bg-sunken);
  border-radius: 0 0 6px 6px;
}

/* ── SECTION GAP: consistent rhythm ── */
.section-gap { margin-bottom: 14px; }

/* Panel-header min-height removed — design has no floor; the canonical base (~L96) governs. */

/* ── PLACEHOLDER VALUES — style bare "--" to feel structured ── */
.ms-val:empty, .cs-val:empty, .ht-val:empty,
.sc-val:empty {
  min-width: 40px;
  display: inline-block;
}

/* ── COUNTDOWN/REFRESH TIMER ── */
.countdown-txt {
  opacity: 0.7;
  transition: opacity 0.2s ease;
}

/* ── DS-NOTE STRIP: reduce visual weight ── */
.ds-note-strip {
  opacity: 0.75;
  transition: opacity 0.2s ease;
}
.ds-note-strip:hover {
  opacity: 1;
}
.ds-note {
  transition: opacity 0.2s ease;
  opacity: 0.8;
}
.ds-note:hover {
  opacity: 1;
}

/* ── PANEL BODY: content area breathing room ── */
.panel-body {
  transition: opacity var(--duration-fast) var(--ease-out);
}

/* ── BADGE POLISH ── */
.badge {
  transition: background var(--duration-fast) var(--ease-out);
}

/* ── DUNE PLACEHOLDER: subtle animation ── */
.dune-placeholder {
  transition: border-color 0.2s ease;
}
.dune-placeholder:hover {
  /* Stronger border on hover — keeps muted/held-back read; no amber. */
  border-color: var(--border-strong);
}

/* ── PEND CHART: subtle hover ── */
.pend-chart {
  transition: border-color 0.2s ease;
}
.pend-chart:hover {
  border-color: var(--border-strong);
}

/* ── REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
  .skeleton, .skeleton-val, .skeleton-bar, .skeleton-row td::after { animation: none; }
  .fade-in, .fade-in-up, .val-reveal { animation: none; }
  .tab-panel.active { animation: none; }
  .spot-token-card:hover { transform: none; }
  .ctrl-btn:active { transform: none; }
  .refresh-btn:active { transform: none; }
  .live-dot { animation: pulse 2s infinite; }
}

/* ── UX Polish: sparkline, sticky chips, density toggle ── */
.sparkline { display: inline-block; vertical-align: middle; margin-right: 6px; }

.h3m-filter-sticky {
  position: sticky;
  top: var(--header-h);  /* below the fixed single-row header (tabs now live inside it) */
  z-index: 5;
  background: var(--bg-elevated);
  padding-top: 4px;
  padding-bottom: 4px;
  margin-left: -20px;
  margin-right: -20px;
  padding-left: 20px;
  padding-right: 20px;
}

.search-hint-wrap { position: relative; display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.search-hint-wrap .search-hint { font-size: 10px; color: var(--text-tertiary); font-family: var(--font-plex); user-select: none; white-space: nowrap; }
.search-hint-wrap:focus-within .search-hint { visibility: hidden; }

.density-btn {
  background: transparent; border: none;
  color: var(--text-tertiary);
  font-size: 14px; line-height: 1; cursor: pointer;
  padding: 2px 6px; font-family: var(--font-plex);
  transition: color var(--duration-fast) var(--ease-out);
}
.density-btn:hover { color: var(--text-secondary); }
body.density-compact .density-btn { color: var(--accent); }

body.density-compact table td { padding: 4px 8px !important; }
body.density-compact table th { padding: 4px 8px !important; }
body.density-compact table { font-size: 11px; }
body.density-compact .panel { padding: 12px 14px !important; }

/* ============================================================
   Flows by Chain — minimal external link card
   Used at the bottom of HYPE → Competition (tab-competition).
   Uses canonical tokens directly: --bg-elevated, --border-default,
   --text-primary, --text-tertiary, --accent, --accent-glow.
   ============================================================ */
.flows-card {
  display: block;
  text-decoration: none;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  padding: 14px 16px;
  background: var(--bg-elevated);
  transition: border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
  margin-top: var(--space-4);
}
.flows-card:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-glow);
  transform: translateY(-1px);
}
.flows-card:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.flows-title {
  font-family: var(--font-plex);
  font-size: 14px;
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 6px;
}
.flows-subtitle {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 4px;
}
.external-icon {
  font-size: 12px;
  color: var(--text-tertiary);
  line-height: 1;
}
.flows-card:hover .external-icon { color: var(--accent); }

/* ============================================================
   GLOBAL SEARCH — header pill + command-palette modal (PR-S1+S2)
   ============================================================ */

/* Header trigger pill */
.search-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 6px 10px;
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  font-family: var(--font-plex);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
  min-width: 200px;
}
.search-trigger:hover {
  border-color: var(--border-strong);
  color: var(--text-secondary);
  background: var(--bg-hover);
}
.search-trigger:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.search-trigger-icon { font-size: 11px; opacity: 0.8; }
.search-trigger-label { flex: 1; text-align: left; }
.search-trigger-kbd {
  font-family: var(--font-plex);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  background: var(--bg-base);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  letter-spacing: 0;
}

/* Hide on small screens — modal opens via keyboard or future mobile button */
@media (max-width: 640px) {
  .search-trigger { min-width: auto; padding: 6px 8px; }
  .search-trigger-label { display: none; }
  .search-trigger-kbd { display: none; }
}

/* Modal scrim */
.search-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--backdrop);   /* --bg-sunken @ 72% */
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 16px 16px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.search-modal.open { display: flex; }

.search-modal-shell {
  width: 100%;
  max-width: 640px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-modal), 0 0 0 1px var(--border-accent);
  display: flex;
  flex-direction: column;
  max-height: min(76vh, 720px);
  overflow: hidden;
}

/* Input row */
.search-input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-default);
  flex-shrink: 0;
}
.search-input-icon { font-size: 14px; color: var(--text-tertiary); }
.search-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  font-family: var(--font-plex);
  font-size: 15px;
  color: var(--text-primary);
  padding: 0;
}
.search-input::placeholder { color: var(--text-tertiary); }
.search-input::-webkit-search-cancel-button { display: none; }
.search-input-kbd {
  font-family: var(--font-plex);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
  flex-shrink: 0;
}

/* Results list */
.search-results {
  overflow-y: auto;
  padding: 6px 6px 8px;
  flex: 1 1 auto;
  min-height: 80px;
  scrollbar-width: thin;
}
/* PR-S3: section labels removed — flat list now. Old class kept as a
   no-op safety net if any older cached HTML still has the markup. */
.search-section-label { display: none; }

.search-result {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: var(--radius-md);
  cursor: pointer;
  user-select: none;
  transition: background var(--duration-fast) var(--ease-out);
}

/* Type badge on each result row — small uppercase pill, low contrast */
.search-result-badge {
  flex-shrink: 0;
  font-family: var(--font-plex);
  font-size: 9px;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-tertiary);
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
  line-height: 1.2;
}
.search-result.active .search-result-badge {
  color: var(--accent);
  border-color: var(--border-accent);
  background: var(--accent-tint-08);
}
.search-result:hover { background: var(--bg-hover); }
.search-result.active {
  background: var(--accent-tint-08);
  box-shadow: inset 2px 0 0 var(--accent);
}
.search-result-main { flex: 1 1 auto; min-width: 0; }
.search-result-title {
  font-family: var(--font-plex);
  font-size: 13px;
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-result-sub {
  font-size: 11px;
  color: var(--text-tertiary);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-result-ext { color: var(--text-tertiary); font-size: 11px; }
.search-result.active .search-result-ext { color: var(--accent); }

.search-empty {
  padding: 28px 16px;
  text-align: center;
  color: var(--text-tertiary);
  font-size: 12px;
}

/* Footer */
.search-footer {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 16px;
  border-top: 1px solid var(--border-default);
  background: var(--bg-sunken);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  flex-shrink: 0;
}
.search-footer kbd {
  display: inline-block;
  margin-right: 4px;
  font-family: var(--font-plex);
  font-size: 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
  color: var(--text-secondary);
}

/* Screen-reader-only live region */
.search-live {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Mobile: near-fullscreen */
@media (max-width: 640px) {
  .search-modal { padding: 0; }
  .search-modal-shell {
    max-width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
    border: 0;
  }
}

/* Search-flash — applied transiently to a panel after navigation lands.
   Subtle accent ring + tint that fades out cleanly. Used by search-ui.js
   `flashTarget()` for ~1.7s. */
@keyframes search-flash {
  0%   { box-shadow: 0 0 0 2px var(--accent), 0 0 18px var(--accent-glow); background-color: var(--accent-tint-08); }
  60%  { box-shadow: 0 0 0 1px var(--accent-tint-20), 0 0 8px transparent;   background-color: var(--accent-tint-08); }
  100% { box-shadow: 0 0 0 0 transparent,            0 0 0 transparent;     background-color: transparent; }
}
.search-flash {
  animation: search-flash 1.7s var(--ease-out);
  border-radius: var(--radius-lg);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .search-trigger,
  .search-result,
  .flows-card { transition: none; }

  /* Flash collapses to a brief, static accent ring — no animation */
  .search-flash {
    animation: none;
    box-shadow: 0 0 0 1px var(--accent);
  }
}

/* ═══════════════════════════════════════════════════════════════════
   ETF subtab (under HYPE section) — added in PR E
   Mobile-safe single-column under 760px; two-column otherwise.
   Reuses --bg-elevated / --border-default / --text-* tokens from main palette.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Per-fund comparison table (PR2) — metrics as rows, funds as columns ── */
.etf-cmp-wrap { overflow-x: auto; }
.etf-cmp-table { min-width: 520px; }
/* First column = metric label: left-aligned, not mono. */
.etf-cmp-table th.etf-cmp-metric { text-align: left; }
.etf-cmp-table td.etf-cmp-metric {
  text-align: left;
  font-family: inherit;
  color: var(--text-secondary);
  white-space: nowrap;
}
/* Clickable fund column headers (open the detail drawer). */
.etf-cmp-table th.etf-cmp-fund {
  cursor: pointer;
  user-select: none;
  color: var(--text-primary);
  font-variant-numeric: normal;
  text-transform: none;
  font-size: var(--text-xs);
}
.etf-cmp-table th.etf-cmp-fund:hover,
.etf-cmp-table th.etf-cmp-open { color: var(--accent); }
.etf-cmp-caret { color: var(--text-tertiary); font-size: var(--text-xxs); }
.etf-cmp-note { margin: 8px 0 0; color: var(--text-tertiary); font-size: 11px; line-height: 1.5; }

/* Per-fund detail drawer (opened from a fund column header). */
#etf-cmp-drawer:empty { display: none; }
.etf-cmp-drawer-panel {
  margin-top: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
}
.etf-cmp-drawer-head {
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 10px;
  font-size: var(--text-sm);
}
.etf-cmp-drawer-meta { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.etf-cmp-drawer-row { display: flex; justify-content: space-between; gap: 16px; font-size: var(--text-xs); }
.etf-cmp-drawer-k { color: var(--text-tertiary); white-space: nowrap; }
.etf-cmp-drawer-v { color: var(--text-secondary); text-align: right; }

.etf-card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}

@media (min-width: 760px) {
  .etf-card-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.etf-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.etf-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}

.etf-card-ticker {
  font-size: 22px;
  font-weight: 600;
  font-family: var(--font-plex);
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

.etf-card-name {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  margin-top: 2px;
}

.etf-card-chips {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.etf-chip {
  display: inline-block;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: 3px 7px;
  border: 1px solid var(--border-default);
  border-radius: 4px;
  color: var(--text-tertiary);
  background: var(--bg-elevated);
}

.etf-card-price-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  border-top: 1px solid var(--border-default);
  padding-top: 10px;
}

.etf-card-price {
  font-size: 26px;
  font-weight: 500;
  font-family: var(--font-plex);
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

.etf-card-change {
  font-size: 13px;
  font-family: var(--font-plex);
  font-weight: 500;
}

.etf-card-change.etf-up   { color: var(--positive); }
.etf-card-change.etf-down { color: var(--negative); }

.etf-card-sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-family: var(--font-plex);
  margin-top: -4px;
}

.etf-card-grid > .etf-card-grid { display: none; } /* defensive: avoid recursion if class collides */

.etf-card .etf-card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--border-default);
  border: 1px solid var(--border-default);
  border-radius: 6px;
  overflow: hidden;
}

@media (max-width: 540px) {
  .etf-card .etf-card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.etf-card-cell {
  background: var(--bg-elevated);
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 50px;
}

.etf-card-cell-label {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.etf-card-cell-val {
  font-size: 13px;
  font-family: var(--font-plex);
  color: var(--text-primary);
}

.etf-pending {
  color: var(--text-disabled);
  font-style: italic;
  font-size: 11px;
}

.etf-card-detail {
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.5;
  border-top: 1px solid var(--border-default);
  padding-top: 10px;
}

/* Issuer-declared HYPE backing row — the partial wedge unlocked by
   the 21Shares market-data API. Populated only when
   summary.implied_hype_backing != null (THYP today; never for
   swap-based products like TXXH). Distinct visual treatment so it
   doesn't read as on-chain-verified data. */
.etf-implied-backing {
  border: 1px solid var(--border-default);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.etf-implied-backing-label {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.etf-implied-backing-value {
  font-size: 16px;
  font-family: var(--font-plex);
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

.etf-implied-backing-note {
  font-size: 10px;
  color: var(--text-tertiary);
  font-style: italic;
}

.etf-card-detail-row {
  margin-bottom: 3px;
}

.etf-card-detail-label {
  color: var(--text-secondary);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  margin-right: 4px;
}

.etf-card-link {
  color: var(--accent);
  text-decoration: none;
}

.etf-card-link:hover {
  text-decoration: underline;
}

/* Holdings panel — the on-chain wedge (or its placeholder) */
.etf-holdings-panel {
  border: 1px solid var(--border-default);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.etf-holdings-panel.available {
  border-color: var(--positive);
}

.etf-holdings-title {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.etf-holdings-status {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
}

.etf-holdings-status.not-applicable { color: var(--text-disabled); }
.etf-holdings-status.pending        { color: var(--text-secondary); }
.etf-holdings-status.available      { color: var(--positive); }

.etf-holdings-reason {
  font-size: 11px;
  color: var(--text-tertiary);
}

/* On-chain backing caveats — careful-wording chips (BHYP). Additive; does
   not affect THYP/TXXH (no caveats block rendered for them). */
.etf-backing-caveats {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.etf-backing-caveat {
  font-size: 10px;
  color: var(--text-tertiary);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: 4px;
  padding: 1px 6px;
  white-space: nowrap;
}

/* ETF Over-Time — section headers + NAV/AUM/Net-Flows toggle wrapper.
   Range + toggle buttons now use the canonical .ctrl-btn (the bespoke
   .etf-ot-range-btn / .etf-ot-toggle-btn rules were retired in T2).
   Additive; scoped to .etf-ot-*. Sections stack on mobile (panels are
   full-width .panel blocks). */
.etf-ot-toggle { display: flex; gap: 4px; flex-wrap: wrap; }
.etf-ot-section { margin-top: 18px; }
.etf-ot-section-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-default);
  margin-bottom: 10px;
}
.etf-ot-section-title { font-size: 15px; font-weight: 600; color: var(--text-primary); }
.etf-ot-section-sub   { font-size: 11px; color: var(--text-tertiary); }

.etf-holdings-detail {
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.etf-holdings-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  font-family: var(--font-plex);
}

.etf-holdings-row > span:first-child {
  color: var(--text-tertiary);
}

.etf-holdings-row > span:last-child {
  color: var(--text-primary);
}

.etf-holdings-addresses {
  margin-top: 6px;
  border-top: 1px solid var(--border-default);
  padding-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.etf-holdings-addr {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-family: var(--font-plex);
}

.etf-holdings-addr-label {
  color: var(--text-secondary);
}

.etf-holdings-addr-val {
  color: var(--text-primary);
}

.etf-card-footer {
  font-size: 10px;
  color: var(--text-tertiary);
  font-family: var(--font-plex);
  border-top: 1px solid var(--border-default);
  padding-top: 8px;
  line-height: 1.5;
}

.etf-card-footer-label {
  color: var(--text-secondary);
  text-transform: uppercase;
  font-size: 9px;
  letter-spacing: var(--tracking-label);
  margin-right: 4px;
}

/* ── Sources & Methodology surface (footer link + modal) ──────────────── */
.srcm-link {
  color: var(--text-tertiary);
  text-decoration: none;
  border-bottom: 1px dotted var(--border-default, var(--border-default));
  cursor: pointer;
}
.srcm-link:hover { color: var(--text-secondary, var(--text-primary)); }

.srcm-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--backdrop);
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 8vh 16px 16px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.srcm-overlay.open { display: flex; }

.srcm-shell {
  width: 100%;
  max-width: 720px;
  background: var(--bg-elevated, var(--bg-elevated));
  border: 1px solid var(--border-default, var(--border-default));
  border-radius: var(--radius-xl, 14px);
  box-shadow: var(--shadow-modal);
  display: flex;
  flex-direction: column;
  max-height: min(82vh, 860px);
  overflow: hidden;
}
.srcm-header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--border-default, var(--border-default));
  flex-shrink: 0;
}
.srcm-title { font-size: 15px; font-weight: 600; color: var(--text-primary); }
.srcm-sub { font-size: 11px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.4; }
.srcm-close {
  margin-left: auto;
  background: var(--bg-sunken, transparent);
  border: 1px solid var(--border-default, var(--border-default));
  color: var(--text-tertiary);
  border-radius: var(--radius-sm, 6px);
  width: 28px; height: 28px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 12px;
}
.srcm-close:hover { color: var(--text-primary); }

.srcm-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border-default, var(--border-default));
  flex-shrink: 0;
}
.srcm-chip {
  font-family: var(--font-plex);
  font-size: 11px;
  color: var(--text-tertiary);
  background: var(--bg-sunken, transparent);
  border: 1px solid var(--border-default, var(--border-default));
  border-radius: 999px;
  padding: 3px 10px;
  cursor: pointer;
}
.srcm-chip:hover { color: var(--text-primary); border-color: var(--accent); }

.srcm-body { overflow-y: auto; padding: 4px 18px 12px; scrollbar-width: thin; }
.srcm-area { padding: 14px 0; border-bottom: 1px solid var(--border-default, var(--border-default)); scroll-margin-top: 8px; }
.srcm-area:last-child { border-bottom: 0; }
.srcm-area-title { font-size: 13px; font-weight: 600; color: var(--text-primary); margin: 0 0 8px; }

.srcm-cat { margin: 0 0 10px; }
.srcm-cat:last-child { margin-bottom: 0; }
.srcm-cat-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin-bottom: 3px;
}
.srcm-hl .srcm-cat-label { color: var(--positive); }
.srcm-ex .srcm-cat-label { color: var(--warn); }
.srcm-tp .srcm-cat-label { color: var(--accent); }
.srcm-me .srcm-cat-label { color: var(--text-tertiary); }
.srcm-list { margin: 0; padding-left: 16px; }
.srcm-list li { font-size: 11.5px; color: var(--text-secondary, var(--text-primary)); line-height: 1.5; margin: 2px 0; }
.srcm-me .srcm-list li { color: var(--text-tertiary); }

.srcm-footer {
  padding: 10px 18px;
  border-top: 1px solid var(--border-default, var(--border-default));
  font-size: 10px;
  color: var(--text-disabled, var(--text-tertiary));
  flex-shrink: 0;
}
.srcm-footer code { font-family: var(--font-plex); font-size: 9.5px; }

@media (max-width: 760px) {
  .srcm-overlay { padding: 0; }
  .srcm-shell { max-width: 100%; height: 100%; max-height: 100%; border-radius: 0; border: 0; }
  .srcm-body { padding: 4px 14px 12px; }
  .srcm-list li { font-size: 12px; }
}
/* ════════════════════════════════════════════════════════════════════════
   OBSIDIAN "terminal" theme — shared by PERPS (#tab-trading) + HIP-3 (#tab-buypress)
   ────────────────────────────────────────────────────────────────────────
   Originally the Perps-only redesign; extended to HIP-3 so both sections
   share one chrome theme. Every selector is scoped via
   :is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) — identical specificity to the original
   #tab-trading rules, so Perps renders byte-for-byte the same. Visual source
   of truth = the Claude Design ZIP: a fully IBM-Plex-Mono terminal, dark
   cards on a hairline border, generous bordered KPI cards, Bebas section
   eyebrow. CSS-only: no JS / data / chart-color / formula changes; all
   DOM/canvas IDs and control hooks preserved. Sections OTHER than Perps +
   HIP-3 are untouched. Chart canvas colours stay owned by js/charts.js.
   ════════════════════════════════════════════════════════════════════════ */

:is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) {
  /* Perps theme palette — now aliases the global design-system tokens (single source of truth) */
  --p-surface: var(--bg-elevated);
  --p-line:    var(--border-default);
  --p-row:     var(--border-row);
  --p-line2:   var(--border-strong);
  --p-text:    var(--text-primary);
  --p-muted:   var(--text-secondary);
  --p-faint:   var(--text-tertiary);
  --p-soft:    var(--accent-tint-12);
  --p-bdr:     var(--accent-tint-40);
  font-family: var(--font-plex);
  color: var(--p-text);
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

/* Section eyebrow (.perps-eyebrow / .pe-*) → now canonical in the GLOBAL base. Scoped removed. */

/* KPI strip (.metrics-strip / .ms-*) → now canonical in the GLOBAL base (~L84).
   Component-pass: un-scoped; scoped duplicate + status-pill rules removed. */

/* ── Panels / panel-header / hero (#main-chart-panel) ── */
/* All canonical in the GLOBAL base now (.panel ~L92, .panel-header ~L96, eyebrow + hero ~L124).
   Component-pass: scoped duplicates removed; the design applies on every tab. */

/* Segmented-control pills (.ctrl-btn / .ctrl-sep) → now canonical in the GLOBAL base (~L356). Scoped duplicate removed. */

/* Stat readout (.chart-stats-row / .cs-*) → now canonical in the GLOBAL base (~L375). Scoped duplicate removed. */

/* Data table (.data-table) → now canonical in the GLOBAL base (~L287). Scoped duplicate removed. */

/* ── Source / freshness note ── */
:is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .ds-note { font-family: var(--font-plex); font-size: 10px; color: var(--p-faint); background: transparent; border-top: 1px solid var(--p-line); }

/* ── Spacing rhythm ── */
:is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .section-gap { margin-bottom: 16px; }
:is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .grid-2 { gap: 16px; }

/* ── Mobile (≤768px): cards 2-up, readout wraps, no clip ── */
@media (max-width: 768px) {
  :is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .metrics-strip { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  :is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .grid-2 { grid-template-columns: 1fr !important; }
  /* .chart-stats-row + .cs-item mobile-wrap → re-homed to the un-scoped @media near the base (~L383). */
  /* .pe-tx mobile font-size → re-homed to the global @media near the eyebrow base (~L130). */
  :is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .ms-val { font-size: 23px; }
}
@media (max-width: 480px) {
  :is(#tab-trading, #tab-buypress, #tab-hip3binance, #tab-hip3stocks, #tab-hip4live, #tab-hip4competitors, #tab-hypeoverview, #tab-hypenomics, #tab-competition, #tab-tokenomics, #tab-users, #tab-unstakingqueue, #tab-hypevaluation, #tab-hypemarkets, #tab-hypeetf, #tab-hypeyield, #tab-hypedeepdive, #tab-spotoverview, #tab-spotmarkets, #tab-dexoverview, #tab-purrstrategy) .ms-val { font-size: 21px; }
}

/* ════════════════════ v2 FLAT CHROME ════════════════════
   Approved redesign — replaces the earlier liquid-glass chrome with solid
   surfaces in the same teal family as the panels: solid header + sidebar,
   centered icon + underline section tabs, crisper nav text (mint wordmark +
   brighter --text-nav labels). Keeps the in-header centered-nav structure but
   drops all translucency / blur / shadow → back in line with CLAUDE.md's
   no-glass / no-shadow rule. The base flat .dash-tab underline + .sidebar-item
   (accent-tint bg + 3px mint left-bar) styling is reused; this block restores
   the in-header layout and applies the crisper palette + roomier sizing. */

/* Header — solid, hairline bottom border, 3-col grid: brand · centered nav · search */
#header {
  background: var(--bg-inset);
  border-bottom: 1px solid var(--border-card);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: stretch;
  gap: 20px;
  padding: 0 26px;
}
.header-logo { width: auto; border-right: none; padding: 0; gap: 10px; justify-self: start; }
.logo-word {
  font-family: var(--font-display); font-size: 19px; letter-spacing: 2.5px;
  color: var(--accent); line-height: 1; white-space: nowrap;   /* crisper: mint wordmark */
}
.header-right { justify-self: end; display: flex; align-items: center; gap: var(--space-3); padding: 0; }
.header-right > * { white-space: nowrap; }
/* Keep the decluttered header — only search sits at the far right; the
   LIVE / BUILD / density / Synced·countdown status cluster stays hidden
   (JS still resolves #status-text / #h-last-sync / #countdown). */
.header-right .live-badge,
.header-right .build-badge,
.header-right .density-btn,
.header-right .countdown-txt { display: none; }

/* Search — flat inset field (no glass pill) */
.search-trigger {
  background: var(--bg-sunken);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.search-trigger:hover { border-color: var(--border-strong); background: var(--bg-sunken); }

/* Section tabs — centered inside the header, flat icon + underline, crisper labels */
#dash-tabs {
  position: static; height: 100%;
  display: flex; align-items: stretch; justify-content: center;
  gap: 12px; padding: 0;
  background: transparent; border-bottom: none;
}
.dash-tab {
  height: 100%; padding: 0 16px; font-size: 14px;
  color: var(--text-nav);
  background: transparent; border: none; border-bottom: 2px solid transparent;
  border-radius: 0; box-shadow: none; margin-bottom: 0;
}
.dash-tab:hover { color: var(--text-primary); background: transparent; }
.dash-tab.active {
  color: var(--accent); background: transparent;
  border: none; border-bottom: 2px solid var(--accent); box-shadow: none;
}
.dash-tab .dt-icon { width: 15px; height: 15px; stroke-width: 1.7; }
.dash-tab-sep { display: none; }

/* Sidebar — solid inset, hairline border. The base flat .sidebar-item
   (accent-tint bg + 3px mint left-bar when active) is reused as-is; only the
   crisper label color + rounding are applied here. */
#sidebar { background: var(--bg-inset); border-right: 1px solid var(--border-card); padding: 10px 8px; }
.sidebar-item { border-radius: var(--radius-md); margin: 1px 0; color: var(--text-nav); }
.sidebar-item.active { color: var(--accent); }

/* ════════════════ v2 FAMILY-TREE SUBNAV (option A — vertical glass tree) ════════════════
   Wraps the existing glass .sidebar-item pills with connector lines + a section root
   node + static group labels. Scoped to #sidebar; reuses the glass active/hover pill. */
#sidebar .tree-root {
  display: flex; align-items: center; gap: 9px;
  font-size: 13px; font-weight: 500; color: var(--accent);
  padding: 8px 12px 12px; letter-spacing: 0.02em;
}
#sidebar .tree-root .si-dot {
  width: 7px; height: 7px; background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}
#sidebar .tree-row { display: flex; align-items: center; }
#sidebar .tree-conn {
  color: var(--text-tertiary); white-space: pre; flex: none;
  font-family: var(--font-plex); font-size: 13px; line-height: 1; padding-left: 6px;
}
#sidebar .tree-group {
  color: var(--text-primary); font-weight: 500; font-size: 13px; padding: 6px 2px;
}
#sidebar .tree-row .sidebar-item {
  flex: 0 1 auto; margin: 1px 0; padding: 5px 11px;
}

/* ════════════════════ v2 TOP SUB-NAV (user-chosen 2026-06-30 — no sidebar, full-width) ════════════════════
   The left family-tree sidebar moves UP into a full-width horizontal sub-tab bar below the section tabs;
   content goes full-width (the sidebar was eating horizontal space). PURE CSS: reuses #sidebar + the
   #nav-* groups + the existing switchDash/switchView wiring (switchDash still show/hides the active
   #nav-* group via inline display) — only repositioned + restyled horizontal. Sub-tabs = flat Wrap row;
   connector = a subtle mint stem under the active section tab. Appended last so it wins. */

/* stack the sub-nav above content; content full-width + centered with a comfy max-width */
#shell { display: block; }
#content, #content.full { margin: 0 auto !important; max-width: 1480px; padding: 24px 28px 56px; flex: none; }

/* #sidebar → full-width horizontal sub-tab bar, sticky just under the fixed header */
#sidebar {
  position: sticky; top: var(--header-h); left: auto; bottom: auto;
  width: 100%; height: auto; overflow: visible;
  background: var(--bg-inset); border-right: none; border-bottom: 1px solid var(--border-card);
  padding: 13px 22px 15px; z-index: 250; display: block;
}
#sidebar.collapsed { width: 100%; }
.sidebar-nav-label, .sidebar-collapse-btn, .sidebar-expand-btn { display: none !important; }

/* the active section's nav group (display:block from switchDash) → centered inline sub-tabs */
#sidebar [id^="nav-"] { text-align: center; line-height: 2; }
#sidebar .tree-row { display: contents; }                  /* leaf becomes an inline child of the nav group */
#sidebar .tree-root, #sidebar .tree-conn, #sidebar .tree-group { display: none !important; }  /* hide tree chrome (Wrap) */

/* leaves → horizontal sub-tab pills */
#sidebar .tree-row .sidebar-item, #sidebar .sidebar-item {
  display: inline-flex; align-items: center; vertical-align: middle; margin: 3px 4px; padding: 7px 14px;
  border-radius: 8px; font-size: 13px; color: var(--text-nav); border: 1px solid transparent; white-space: nowrap;
}
#sidebar .sidebar-item .si-dot { display: none; }
#sidebar .sidebar-item:hover { background: var(--bg-hover); color: var(--text-primary); }
#sidebar .sidebar-item.active { background: var(--accent-tint-08); border-color: var(--accent-tint-20); color: var(--accent); }
#sidebar .sidebar-item.active::before { display: none; }

/* single-view dashboards (Perps/DEX/PURR/ETF/Notes): hide the whole band —
   a lone pill wastes the sticky strip; the section eyebrow already names it.
   Toggled by updateSubnavSolo() in js/nav.js. */
#sidebar.subnav-solo { display: none; }

/* the in-content section-title bar is redundant now (named by the active tab + the eyebrow) */
.content-topbar { display: none; }

/* ════════════════════ v2 FLAGSHIP + SMALL-PANELS ROW ════════════════════
   One big flagship panel (left) + a column of small stat cards (right) = the
   panel-mockup / hl.eco arrangement. The small cards reuse the existing
   .metrics-strip .ms-item elements (same IDs) so live data keeps flowing. */
.flagship-row { display: grid; grid-template-columns: 1.9fr 1fr; gap: 20px; align-items: stretch; }
.flagship-row > .panel { margin: 0; }
/* hl.eco-style metric cards: each card grows to fill the flagship height and
   pays for its size with a 30D sparkline of its OWN live series — no filler,
   the line is the headline number's own recent history. */
.flagship-row .mini-stack { display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; gap: 14px; margin: 0; }
.flagship-row .mini-stack .ms-item { background: var(--bg-elevated); border: 1px solid var(--border-card); border-radius: var(--radius-lg); padding: 15px 16px 0; display: flex; flex-direction: column; min-height: 150px; overflow: hidden; }
.flagship-row .mini-stack .ms-item::before { display: none; }
.flagship-row .mini-stack .ms-label { font-size: 10px; letter-spacing: 1px; line-height: 1.35; }
.flagship-row .mini-stack .ms-val { font-size: 27px; font-weight: 500; margin-top: 9px; color: var(--text-primary); line-height: 1.05; font-variant-numeric: tabular-nums; }
.flagship-row .mini-stack .ms-delta { margin-top: 6px; }
/* sparkline grows to fill the card's lower half — no dead middle zone, reads
   as a proper mini area-chart. Taller viewBox (240x96) keeps the stretch gentle. */
.flagship-row .mini-stack .ms-spark { width: calc(100% + 32px); flex: 1 1 auto; min-height: 60px; margin: 14px -16px 0; display: block; }
@media (max-width: 980px){
  .flagship-row { grid-template-columns: 1fr; }
  .flagship-row .mini-stack { grid-template-columns: 1fr 1fr; }
  .flagship-row .mini-stack .ms-item { min-height: 132px; }
  .flagship-row .mini-stack .ms-spark { min-height: 44px; }
}

/* HIP-3 top-stat sparkline cards — v2 metric-card treatment applied additively
   to the existing 3-up KPI strip (no panels removed). Same fill-to-bottom
   sparkline as the flagship cards, but full-width row instead of a side column. */
.metrics-strip.h3-spark-cards { gap: 14px; }
.metrics-strip.h3-spark-cards .ms-item { background: var(--bg-elevated); border: 1px solid var(--border-card); border-radius: var(--radius-lg); padding: 14px 16px 0; display: flex; flex-direction: column; min-height: 126px; overflow: hidden; }
.metrics-strip.h3-spark-cards .ms-item::before { display: none; }
.metrics-strip.h3-spark-cards .ms-label { font-size: 10px; letter-spacing: 1px; }
.metrics-strip.h3-spark-cards .ms-val { font-size: 26px; font-weight: 500; color: var(--text-primary); margin-top: 6px; line-height: 1.05; font-variant-numeric: tabular-nums; }
.metrics-strip.h3-spark-cards .ms-spark { width: calc(100% + 32px); flex: 1 1 auto; min-height: 42px; margin: 10px -16px 0; display: block; }
@media (max-width: 720px){
  .metrics-strip.h3-spark-cards { grid-template-columns: 1fr 1fr !important; }
}

/* ══════════════ D3 UTILITY & COMPONENT CLASSES (relocated to EOF) ══════════════
   Atomic utilities (u-*) + a few single-use component classes, extracted from
   repeated inline style=. MUST live at the end so that same-specificity ties
   (e.g. .u-p1p6 vs a later-defined .ctrl-btn) resolve in the utility's favour by
   source order — the whole point of retiring the (specificity-1000) inline styles.
   All token-based; no raw hex. */
.u-tsec{color:var(--text-secondary);}
.u-tter{color:var(--text-tertiary);}
.u-tdis{color:var(--text-disabled);}
.u-tneg{color:var(--negative);}
.u-tpos{color:var(--positive);}
.u-tpri{color:var(--text-primary);}
.u-flex{display:flex;}
.u-flex-g4{display:flex;gap:4px;}
.u-flex-g4-ac{display:flex;gap:4px;align-items:center;}
.u-flex-ac{display:flex;align-items:center;}
.u-flex-col-g6{display:flex;flex-direction:column;gap:6px;}
.u-flex-ac-g5{display:flex;align-items:center;gap:5px;}
.u-rowhead{display:flex;justify-content:space-between;align-items:baseline;padding:2px 2px 6px;}
.u-clk{cursor:pointer;user-select:none;}
.u-cap{font-size:9px;color:var(--text-tertiary);margin-top:2px;}
.u-chartbox{position:relative;}
.u-h200{height:200px;}.u-h210{height:210px;}.u-h220{height:220px;}.u-h240{height:240px;}.u-h260{height:260px;}.u-h280{height:280px;}.u-h300{height:300px;}.u-h320{height:320px;}.u-h340{height:340px;}.u-h360{height:360px;}
.u-fs9{font-size:9px;}.u-fs10{font-size:10px;}.u-fs11{font-size:11px;}.u-fs12{font-size:12px;}.u-fs13{font-size:13px;}.u-fs14{font-size:14px;}.u-fs18{font-size:18px;}
.u-fw500{font-weight:500;}.u-fw600{font-weight:600;}.u-fw600-uc{font-weight:600;letter-spacing:.03em;}
.u-tar{text-align:right;}.u-tac{text-align:center;}.u-tal{text-align:left;}
.u-uc{text-transform:uppercase;}.u-nowrap{white-space:nowrap;}.u-ls05{letter-spacing:0.5px;}.u-ls04{letter-spacing:.04em;}
.u-ovx{overflow-x:auto;}.u-ovy{overflow-y:auto;}
.u-bb{border-bottom:1px solid var(--border-default);}
.u-fwrap{flex-wrap:wrap;}.u-jc{justify-content:center;}
.u-gap8{gap:8px;}.u-gap12{gap:12px;}.u-fshrink0{flex-shrink:0;}
.u-mt2{margin-top:2px;}.u-mt3{margin-top:3px;}.u-mt4{margin-top:4px;}.u-mt6{margin-top:6px;}.u-mt8{margin-top:8px;}.u-mt12{margin-top:12px;}.u-mt24{margin-top:24px;}
.u-mb3{margin-bottom:3px;}.u-mb4{margin-bottom:4px;}.u-mb6{margin-bottom:6px;}.u-mb8{margin-bottom:8px;}.u-mb10{margin-bottom:10px;}.u-mb12{margin-bottom:12px;}.u-mb14{margin-bottom:14px;}
.u-mr4{margin-right:4px;}
.u-p12{padding:12px;}.u-p1620{padding:16px 20px;}.u-p1216{padding:12px 16px;}.u-p68{padding:6px 8px;}.u-p1p6{padding:1px 6px;}.u-p02{padding:0 2px;}
.u-grid{display:grid;}.u-g2{grid-template-columns:1fr 1fr;}.u-g3{grid-template-columns:repeat(3,1fr);}.u-g4{grid-template-columns:repeat(4,1fr);}.u-g5{grid-template-columns:repeat(5,1fr);}.u-g6{grid-template-columns:repeat(6,1fr);}.u-g7{grid-template-columns:repeat(7,1fr);}
.u-maxh400{max-height:400px;}
.u-gap6{gap:6px;}.u-jce{justify-content:flex-end;}.u-p0{padding:0;}.u-pl10{padding-left:10px;}.u-mt10{margin-top:10px;}.u-fs15{font-size:15px;}.u-flex00a{flex:0 0 auto;}.u-bt{border-top:1px solid var(--border-default);}.u-bl-dis{border-left:3px solid var(--text-disabled);}.u-vdiv{width:1px;height:16px;background:var(--border-default);margin:0 4px;}
.u-gap10{gap:10px;}.u-gap14{gap:14px;}.u-bgt{background:transparent;}.u-bn{border:none;}.u-fw400{font-weight:400;}
.u-bord{border:1px solid var(--border-default);}.u-rad6{border-radius:6px;}.u-ml4{margin-left:4px;}.u-mt14{margin-top:14px;}.u-w100{width:100%;}.u-bl-acc{border-left:3px solid var(--accent);}.u-relative{position:relative;}.u-h250{height:250px;}.u-p0168{padding:0 16px 8px;}.u-p01612{padding:0 16px 12px;}.u-p8160{padding:8px 16px 0;}.u-gcspan2{grid-column:span 2;}
.u-warn-box{padding:12px;margin-bottom:12px;background:var(--warn-tint-10);border:1px solid var(--warn-tint-35);border-radius:6px;font-size:12px;color:var(--warn);}
.u-mb2{margin-bottom:2px;}.u-h180{height:180px;}.u-h190{height:190px;}.u-p16{padding:16px;}.u-p24{padding:24px;}.u-p2p8{padding:2px 8px;}.u-lh15{line-height:1.5;}.u-m2028{margin:2px 0 8px 2px;}.u-flex-sb-ac{display:flex;justify-content:space-between;align-items:center;}.u-gaf120{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));}.u-scrollbox{max-height:420px;overflow:auto;-webkit-overflow-scrolling:touch;}
.hip4-table th.u-tar,.hip4-table td.u-tar{text-align:right;}.hip4-table th.u-tal,.hip4-table td.u-tal{text-align:left;}
.u-m0{margin:0;}.u-mt1{margin-top:1px;}.u-m2002{margin:2px 0 0 2px;}.u-m6020{margin:6px 0 2px 0;}.u-fs17{font-size:17px;}.u-gap16{gap:16px;}.u-gap812{gap:8px 12px;}.u-w8{width:8px;}.u-mw100{min-width:100px;}.u-mw110{min-width:110px;}.u-mw130{min-width:130px;}.u-mw200{min-width:200px;}.u-flex1{flex:1;}.u-ais{align-items:flex-start;}.u-lh16{line-height:1.6;}.u-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:4px;}.u-bg-acc{background:var(--accent);}.u-bg-ter{background:var(--text-tertiary);}.u-sq140{width:140px;height:140px;flex-shrink:0;}
.u-twarn{color:var(--warn);}.u-mn2028{margin:-2px 0 8px 2px;}.u-m0082{margin:0 0 8px 2px;}.u-gaf130{grid-template-columns:repeat(auto-fit,minmax(130px,1fr));}
.u-mt0{margin-top:0;}.u-minh14{min-height:14px;}.u-mt16{margin-top:16px;}.u-mt18{margin-top:18px;}.u-p101411{padding:10px 14px 11px;}.u-ls07{letter-spacing:0.07em;}.u-lh145{line-height:1.45;}.u-aife{align-items:flex-end;}.u-h160{height:160px;}.u-pb4{padding-bottom:4px;}
.u-h22{height:22px;}.u-rad4{border-radius:4px;}.u-ovh{overflow:hidden;}.u-p18{padding:18px;}.u-p240{padding:24px 0;}.u-gap1016{gap:10px 16px;}.u-mw240{min-width:240px;}.u-mw50{min-width:50px;}.u-mb16{margin-bottom:16px;}.u-h320{height:320px;}.u-fs105{font-size:10.5px;}.u-op8{opacity:.8;}.u-fs16{font-size:16px;}.u-fs22{font-size:22px;}.u-fs30{font-size:30px;}
.u-stat-tile{text-align:center;padding:14px 10px;background:var(--bg-elevated);border-radius:8px;border:1px solid var(--border-default);}
.u-mw540{min-width:540px;}.u-gcfull{grid-column:1/-1;}.u-maxh300{max-height:300px;}.u-g161{grid-template-columns:1.6fr 1fr;}.u-aist{align-items:start;}.u-m2216{margin:2px 2px 16px;}
.u-chart-empty{position:absolute;inset:0;align-items:center;justify-content:center;color:var(--text-disabled);font-size:11px;}
.u-srcm-btn{margin-left:auto;font-size:11px;color:var(--accent);text-decoration:none;border:1px solid var(--border-default);border-radius:5px;padding:4px 10px;}
.u-est-badge{font-size:9px;font-weight:600;letter-spacing:.4px;padding:1px 5px;border-radius:3px;background:var(--warn-tint-10);color:var(--warn);text-transform:uppercase;vertical-align:middle;}
.hm-search-input{flex:1;min-width:160px;background:var(--bg-sunken);border:1px solid var(--border-default);color:var(--text-primary);border-radius:6px;padding:6px 10px;font-size:12px;outline:none;}
.u-eyebrow{font-family:var(--font-plex);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-tertiary);}
.u-metaline{font-family:var(--font-plex);font-size:10px;color:var(--text-disabled);letter-spacing:.04em;}
.u-tile{padding:10px 12px;background:var(--bg-elevated);border-radius:6px;border:1px solid var(--border-default);}
.u-sunken-tile{background:var(--bg-sunken);padding:8px;border-radius:4px;}
.u-empty{text-align:center;padding:20px;color:var(--text-tertiary);}
.u-sticky-head{position:sticky;top:0;background:var(--bg-elevated);}
.tbl-empty{text-align:center;padding:24px;color:var(--text-tertiary);}
.tbl-scroll{max-height:360px;overflow-y:auto;}
/* Bottom fade cue when a capped table has more rows below the fold. Sticky
   pseudo overlays the last row (negative margin = no added height). Driven by a
   scroll timeline so it self-disables: a non-scrollable (short) table leaves an
   inactive timeline, so opacity stays 0 and no false "more content" hint shows;
   it also fades out at the very bottom of the scroll. Chromium-only progressive
   enhancement — browsers without scroll-driven animations simply show no cue.
   #tab-buypress keeps its own explicit "← scroll →" hint, so exclude it. */
.tbl-scroll::after{content:'';position:sticky;bottom:0;left:0;display:block;height:28px;margin-top:-28px;background:linear-gradient(to bottom,transparent,var(--bg-elevated));pointer-events:none;opacity:0;animation:tbl-scroll-fade linear both;animation-timeline:scroll(self block);}
@keyframes tbl-scroll-fade{0%,85%{opacity:1;}100%{opacity:0;}}
#tab-buypress .tbl-scroll::after{display:none;}
.section-eyebrow{margin:28px 0 12px;padding:0 2px;font-size:12px;font-weight:500;letter-spacing:.04em;color:var(--text-secondary);}
.audit-btn{background:var(--bg-sunken);border:1px solid var(--border-default);color:var(--text-tertiary);font-size:10px;padding:4px 10px;border-radius:4px;cursor:pointer;}
.audit-panel{margin-top:8px;border:1px solid var(--border-default);border-radius:6px;background:var(--bg-elevated);padding:12px;font-size:10px;color:var(--text-secondary);}
/* data-table cell utils — scoped (0,2,1) so they beat `.data-table td` (0,1,1) */
.data-table td.u-tar,.data-table th.u-tar{text-align:right;}
.data-table td.u-tac,.data-table th.u-tac{text-align:center;}
.data-table td.u-tal,.data-table th.u-tal{text-align:left;}
.data-table td.u-p68,.data-table th.u-p68{padding:6px 8px;}
.data-table td.u-p78{padding:7px 8px;}
.data-table td.u-p58{padding:5px 8px;}
.data-table td.u-p812{padding:8px 12px;}
.data-table td.u-p612{padding:6px 12px;}
/* ── D3 batch (body clusters: audit/thead/USDC+Coinbase/tables) ── */
.u-p008{padding:0 0 8px;}.u-p0016{padding:0 16px;}.u-pt10{padding-top:10px;}.u-p1012{padding:10px 12px;}.u-p6140{padding:6px 14px 0;}
.u-mn4010{margin:-4px 0 10px;}.u-m01610{margin:0 16px 10px;}.u-m0014{margin:0 0 14px;}.u-mxauto{margin:0 auto;}.u-mt5{margin-top:5px;}
.u-tacc{color:var(--accent);}.u-h12{height:12px;}.u-gap9{gap:9px;}
.u-op65{opacity:.65;}.u-op85{opacity:.85;}
.u-fplex{font-family:var(--font-plex,monospace);}
.u-empty-msg{padding:20px 0;text-align:center;color:var(--text-secondary);font-size:13px;}
.u-linkbtn{background:none;border:1px solid var(--border-default);color:var(--accent);border-radius:5px;padding:5px 14px;font-size:11px;cursor:pointer;font-family:inherit;letter-spacing:0.01em;}
.u-onchain-badge{font-size:9px;font-weight:600;letter-spacing:.4px;padding:1px 5px;border-radius:3px;background:var(--positive-tint-10);color:var(--positive);text-transform:uppercase;vertical-align:middle;}
.u-iflex-ac-g5{display:inline-flex;align-items:center;gap:5px;}
.u-legbar{display:inline-block;width:14px;height:3px;border-radius:1px;}
.u-legln{display:inline-block;width:10px;height:2px;}
.u-legdash-h3{display:inline-block;width:14px;border-bottom:2px dashed var(--role-hip3);}
.u-dot8{width:8px;height:8px;border-radius:50%;flex:none;}
.u-bg-sblue{background:var(--series-blue);}.u-bg-semerald{background:var(--series-emerald);}.u-bg-warn{background:var(--warn);}
/* scoped table-cell utils (beat .data-table td / .hip4-table td (0,1,1)) */
.data-table tr.u-hrow{border-bottom:1px solid var(--border-default);color:var(--text-tertiary);}
.data-table td.u-p20{padding:20px;}.data-table td.u-tter{color:var(--text-tertiary);}
.hip4-table td.u-tac{text-align:center;}.hip4-table td.u-p16{padding:16px;}.hip4-table td.u-tter{color:var(--text-tertiary);}
.data-table td.u-p200{padding:20px 0;}
.u-ml8{margin-left:8px;}.u-mlauto{margin-left:auto;}.u-curhelp{cursor:help;}

/* ════════════════════ MOBILE NAV SHELL (≤768px) — design handoff 2a, 2026-07-06 ════════════════════
   Bottom tab bar (Perps · HYPE · HIP-3 · Spot · More) + "More" bottom sheet replace the
   scroll-overflowing #dash-tabs on phones, and the v2 horizontal sub-nav band (#sidebar)
   is re-enabled as a single scrollable pill row — it was display:none ≤768px, stranding
   sub-views (HYPE has 13). Markup in index.html, wiring in js/nav.js (mobileNavGo /
   mobileMoreToggle / updateMobileNav). Appended last so it beats both the legacy ≤768px
   block and the unscoped v2 sub-nav rules. */
#mobile-tabbar, #mobile-more-sheet, #mobile-more-scrim { display: none; }

@media (max-width: 768px) {
  /* dash tabs replaced by the bottom bar */
  #dash-tabs { display: none; }

  /* ── sub-view pill bar: #sidebar back on, as one scrollable row under the 52px header ── */
  #sidebar {
    display: block !important;   /* beats the legacy `display:none !important` above (later in file) */
    position: sticky; top: 52px; left: auto; bottom: auto;
    width: 100%; height: auto; overflow: visible;
    background: var(--bg-inset); border-right: none; border-bottom: 1px solid var(--border-card);
    padding: 8px 10px; z-index: 250;
  }
  #sidebar.subnav-solo { display: none !important; }
  /* nav groups keep switchDash's inline display:block — scroll comes from nowrap + overflow */
  #sidebar [id^="nav-"] { white-space: nowrap; overflow-x: auto; text-align: left; line-height: 1; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  #sidebar [id^="nav-"]::-webkit-scrollbar { display: none; }
  #sidebar .tree-row .sidebar-item, #sidebar .sidebar-item {
    margin: 0 4px 0 0; padding: 6px 12px; min-height: 28px; font-size: var(--text-sm); border-radius: var(--radius-md);
  }

  /* ── bottom tab bar ── */
  #mobile-tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 300;
    background: var(--bg-inset); border-top: 1px solid var(--border-card);
    padding: 0 4px calc(env(safe-area-inset-bottom, 0px));
  }
  .mtab {
    flex: 1; position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px;
    min-height: 48px; padding: 9px 0 5px; background: transparent; border: none; cursor: pointer;
    font-family: var(--font-plex); font-size: var(--text-xxs); letter-spacing: 0.04em;
    color: var(--text-secondary); font-weight: var(--weight-normal);
  }
  .mtab svg { width: 19px; height: 19px; }
  .mtab::before { content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 18px; height: 2px; border-radius: 0 0 2px 2px; background: transparent; }
  .mtab.active { color: var(--accent); font-weight: var(--weight-medium); }
  .mtab.active::before { background: var(--accent); }

  /* ── "More" bottom sheet + scrim ── */
  #mobile-more-scrim {
    display: block; position: fixed; inset: 0; z-index: 310; background: var(--overlay-scrim);
    opacity: 0; pointer-events: none; transition: opacity var(--duration-med) var(--ease-out);
  }
  #mobile-more-scrim.open { opacity: 1; pointer-events: auto; }
  #mobile-more-sheet {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 320;
    background: var(--bg-elevated); border-top: 1px solid var(--border-kpi); border-radius: 16px 16px 0 0;
    padding-bottom: calc(26px + env(safe-area-inset-bottom, 0px));
    transform: translateY(105%); transition: transform var(--duration-med) var(--ease-out);
  }
  #mobile-more-sheet.open { transform: translateY(0); }
  .mms-handle { display: flex; justify-content: center; padding: 10px 0 2px; }
  .mms-handle span { width: 36px; height: 4px; border-radius: var(--radius-pill); background: var(--border-strong); }
  .mms-label { font-size: var(--text-xxs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-tertiary); padding: 10px 18px 6px; }
  .mms-row {
    display: flex; align-items: center; gap: 11px; width: 100%; min-height: 48px; padding: 0 18px;
    background: transparent; border: none; border-bottom: 1px solid var(--border-row);
    font-family: var(--font-plex); font-size: var(--text-md); color: var(--text-primary); cursor: pointer;
  }
  .mms-row .mms-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--text-disabled); flex: none; }
  .mms-row .mms-name { flex: 1; text-align: left; }
  .mms-row .mms-count { font-size: var(--text-xs); color: var(--text-tertiary); }
  .mms-row svg { width: 12px; height: 12px; color: var(--text-tertiary); flex: none; }
  .mms-row.active { color: var(--accent); }
  .mms-row.active .mms-dot { width: 7px; height: 7px; background: var(--accent); box-shadow: var(--shadow-glow); }

  /* content clears the fixed bottom bar (48px bar + breathing room + safe area) */
  .page-body { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }

  /* ── KPI strips → 2×2 bordered cards (handoff density pattern; beats the legacy 1px-gap grid) ── */
  .metrics-strip { gap: 10px; }
  .ms-item { background: var(--bg-elevated); border: 1px solid var(--border-card); border-radius: var(--radius-lg); padding: 12px; min-height: 0; }
}

/* ════════════════════ MOBILE TABLE CARDS (≤768px) — design handoff 1h, 2026-07-06 ════════════════════
   Wide data-tables scroll sideways on a phone. Here each opted-in table becomes
   cards: cols 1+2 on the top line, cols 3+ revealed on tap (js/mobile-tables.js
   adds the .mtbl-cards marker to the panel + toggles .row-open on the <tr>).
   <thead> is hidden and replaced by a sort-pill row that proxy-clicks the real
   headers. The card layout is GENERIC (.mtbl-cards); only the per-column labels
   are table-specific (each table's small ::before block below). Add a table via
   the TABLES array in mobile-tables.js + one labels block here. */
.mtbl-sort { display: none; }
@media (max-width:768px){
  /* sort pills (shown in place of the hidden <thead>) */
  .mtbl-sort {
    display: flex; align-items: center; gap: 6px; overflow-x: auto;
    padding: 0 0 10px; margin: 0; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .mtbl-sort::-webkit-scrollbar { display: none; }
  .mtbl-sort-lbl { flex: none; font-size: var(--text-xxs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-tertiary); }
  .mtbl-sort-pill {
    flex: none; font-family: var(--font-plex); background: transparent;
    border: 1px solid var(--border-default); border-radius: var(--radius-md);
    color: var(--text-secondary); font-size: var(--text-xs); letter-spacing: .02em;
    padding: 5px 11px; min-height: 28px; white-space: nowrap; cursor: pointer;
  }
  .mtbl-sort-pill:active { border-color: var(--accent-tint-40); color: var(--accent); }

  /* ── generic card transform — any panel the JS marks .mtbl-cards ── */
  .mtbl-cards .tbl-scroll, .mtbl-cards .u-ovx { overflow-x: visible; }
  .mtbl-cards .data-table { min-width: 0; display: block; }
  .mtbl-cards .data-table thead { display: none; }
  .mtbl-cards .data-table tbody { display: block; }
  .mtbl-cards .data-table tr {
    display: grid; grid-template-columns: 1fr auto; column-gap: 10px; row-gap: 6px;
    position: relative; padding: 11px 30px 11px 13px; margin-bottom: 8px; cursor: pointer;
    background: var(--bg-elevated); border: 1px solid var(--border-card) !important; border-radius: var(--radius-lg);
  }
  /* padding:0 !important defeats per-cell inline padding some render fns emit (e.g. HYPE Markets) */
  .mtbl-cards .data-table td { display: block; padding: 0 !important; border: none; white-space: normal; font-family: var(--font-plex); }
  .mtbl-cards .data-table td:nth-child(1) { grid-column: 1; font-size: var(--text-md); font-weight: var(--weight-medium); }
  .mtbl-cards .data-table td:nth-child(2) { grid-column: 2; text-align: right; font-size: var(--text-md); color: var(--text-primary); }
  /* secondary columns — hidden until the row is tapped open */
  .mtbl-cards .data-table td:nth-child(n+3) { display: none; grid-column: 1 / -1; font-size: var(--text-sm); color: var(--text-secondary); }
  .mtbl-cards .data-table tr.row-open td:nth-child(n+3) { display: flex; justify-content: space-between; align-items: baseline; }
  .mtbl-cards .data-table td:nth-child(n+3)::before { color: var(--text-tertiary); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .04em; }
  /* expand chevron */
  .mtbl-cards .data-table tr::after {
    content: '⌄'; position: absolute; right: 11px; top: 9px; color: var(--text-tertiary);
    font-size: 12px; line-height: 1; transition: transform var(--duration-fast) var(--ease-out);
  }
  .mtbl-cards .data-table tr.row-open::after { transform: rotate(180deg); }

  /* ── per-table column labels (col order is table-specific) ── */
  /* Perps · Top Perp Markets by OI */
  #perp-oi-top-panel .data-table td:nth-child(3)::before { content: 'Mark Price'; }
  #perp-oi-top-panel .data-table td:nth-child(4)::before { content: '% of Perp OI'; }
  #perp-oi-top-panel .data-table td:nth-child(5)::before { content: '24H Vol'; }
  #perp-oi-top-panel .data-table td:nth-child(6)::before { content: '7D Volume'; }
  /* Spot · All Spot Markets */
  #tab-spotmarkets .data-table td:nth-child(3)::before { content: 'Chg vs Prev'; }
  #tab-spotmarkets .data-table td:nth-child(4)::before { content: '24H Vol'; }
  #tab-spotmarkets .data-table td:nth-child(5)::before { content: 'Circulating'; }
  #tab-spotmarkets .data-table td:nth-child(6)::before { content: 'Market Cap'; }
  /* HYPE · All Markets (unified explorer) */
  #tab-hypemarkets .data-table td:nth-child(3)::before { content: '24h Change'; }
  #tab-hypemarkets .data-table td:nth-child(4)::before { content: '8h Funding'; }
  #tab-hypemarkets .data-table td:nth-child(5)::before { content: 'Volume'; }
  #tab-hypemarkets .data-table td:nth-child(6)::before { content: 'Open Interest'; }
}

/* ════════════════════ HIP-4 MARKETS CARDS (≤768px) — 2026-07-06 ════════════════════
   HIP-4's "All Markets" table is different from the generic .mtbl-cards ones:
   it's a `.hip4-table` (not .data-table), each <tr> already has an onclick that
   opens the market detail (order book / odds / candles), and sorting/filtering
   is external (OI/Volume ctrl-btns + category chips) — no sortable <th>s. So it
   gets a DISPLAY card (all fields visible, tap opens the detail), NOT the
   tap-to-expand pattern, and needs no js/mobile-tables.js wiring or sort pills.
   Pure CSS, scoped to the one table. */
@media (max-width:768px){
  #hip4-markets-full-table { min-width: 0; display: block; }
  #hip4-markets-full-table thead { display: none; }
  #hip4-markets-full-table tbody { display: block; }
  #hip4-markets-full-table tr {
    display: grid; grid-template-columns: 1fr 1fr; gap: 7px 12px;
    padding: 11px 13px; margin-bottom: 8px; cursor: pointer;
    background: var(--bg-elevated); border: 1px solid var(--border-card); border-radius: var(--radius-lg);
  }
  #hip4-markets-full-table td { display: block; padding: 0; border: none; white-space: normal; font-family: var(--font-plex); }
  /* Question — full-width card title (may wrap) */
  #hip4-markets-full-table td:nth-child(1) { grid-column: 1 / -1; font-size: var(--text-md); font-weight: var(--weight-medium); color: var(--text-primary); line-height: 1.35; }
  /* the 5 stats — label:value pairs in a 2-col grid below the title */
  #hip4-markets-full-table td:nth-child(n+2) { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: var(--text-sm); color: var(--text-secondary); }
  #hip4-markets-full-table td:nth-child(2)::before { content: 'Category'; }
  #hip4-markets-full-table td:nth-child(3)::before { content: '% Chance'; }
  #hip4-markets-full-table td:nth-child(4)::before { content: 'OI'; }
  #hip4-markets-full-table td:nth-child(5)::before { content: '24h Vol'; }
  #hip4-markets-full-table td:nth-child(6)::before { content: 'Expiry'; }
  #hip4-markets-full-table td:nth-child(n+2)::before { flex: none; color: var(--text-tertiary); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .04em; }
  /* loading / empty colspan row spans the whole card */
  #hip4-markets-full-table tr.hip4-row-empty { display: block; padding: 16px; text-align: center; }
  #hip4-markets-full-table tr.hip4-row-empty td { display: block; }
}
