:root {
  --bg: #0a0a0f;
  --bg1: #111118;
  --bg2: #1a1a24;
  --bg3: #22222f;
  --border: rgba(255,255,255,0.08);
  --border2: rgba(255,255,255,0.14);
  --text: #f0f0f5;
  --muted: #7a7a94;
  /* Was #545470 — 2.58:1 against --bg1, well under the 4.5:1 WCAG AA text
     floor (verified with the dataviz skill's validator). #7f7fa8 clears
     4.93:1 in the same hue family, so labels stay legible without a visual
     shift. */
  --muted2: #7f7fa8;
  --accent: #6c63ff;
  --accent2: #8b85ff;
  --green: #22d3a0;
  --red: #ff5c7a;
  --amber: #f59e0b;
  --blue: #38bdf8;
  --purple: #a78bfa;
  --font: 'Inter', system-ui, sans-serif;
  --radius: 12px;
  --radius-sm: 8px;

  /* Data-viz categorical palette — the dataviz skill's validated 8-hue order,
     dark-mode steps, checked against THIS app's card surface (--bg1 #111118)
     via scripts/validate_palette.js: all 8 pass lightness band / chroma floor
     / CVD-adjacent ΔE >=8.4 / normal-vision ΔE >=19.3 / contrast >=3:1. The old
     ad-hoc set (#6c63ff/#38bdf8/#22d3a0/#f59e0b/#ff5c7a/#a78bfa/#34d399/#fb923c)
     FAILED the lightness-band check — several hues were too washed-out against
     this surface. Fixed order: assign by position, never re-sort when a filter
     changes which series are on screen. Distinct from --green/--red above
     (those are pos/neg status ink, not series identity). */
  --series-1: #3987e5; /* blue */
  --series-2: #d95926; /* orange */
  --series-3: #199e70; /* aqua */
  --series-4: #c98500; /* yellow */
  --series-5: #d55181; /* magenta */
  --series-6: #008300; /* green */
  --series-7: #9085e9; /* violet */
  --series-8: #e66767; /* red */
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 14px; }
body { background: var(--bg); color: var(--text); font-family: var(--font); min-height: 100vh; }

/* Nav */
.nav { position: sticky; top: 0; z-index: 100; background: rgba(10,10,15,0.92); backdrop-filter: blur(16px); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 0; padding: 0 16px; height: 52px; }
.nav-logo { font-size: 15px; font-weight: 600; letter-spacing: -0.3px; color: var(--text); margin-right: 18px; display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.nav-tabs { display: flex; gap: 2px; flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.nav-tabs::-webkit-scrollbar { display: none; }
.nav-tab { padding: 6px 9px; border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--muted); transition: all 0.15s; border: none; background: transparent; white-space: nowrap; }
.nav-tab:hover { color: var(--text); background: var(--bg2); }
.nav-tab.active { color: var(--text); background: var(--bg2); font-weight: 500; }
/* Divider + muted styling that set the reference/help pages apart from the
   functional analytics tabs. */
.nav-divider { align-self: center; flex: 0 0 auto; width: 1px; height: 18px; background: var(--border2); margin: 0 7px; }
.nav-tab-ref { font-size: 12px; padding: 6px 8px; color: var(--muted); opacity: 0.8; }
.nav-tab-ref:hover { opacity: 1; }
.nav-tab-ref.active { opacity: 1; color: var(--text); background: var(--bg2); font-weight: 500; }
.nav-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
/* The nav now carries 10 tabs (6 functional + 4 reference) plus the right-hand
   controls. On anything short of a wide desktop that doesn't all fit, so the
   lowest-value chrome — the "Last updated" status text — drops out first, which
   frees enough room to keep every tab fully visible. It returns on wide screens. */
@media (max-width: 1600px) { #last-updated { display: none; } }

/* Control strip — second ticket tape, directly under the nav. Everything that
   isn't primary page navigation or the sign-in/out identity action lives here:
   view mode, total value, portfolio switcher, currency, risk-free rate, and
   account/plan controls — each labeled so its purpose is never a guess. Same
   horizontal-scroll behavior as .nav-tabs (drag / shift+wheel / trackpad), but
   WITH a visible (thin) scrollbar rather than a hidden one, so it's obvious at
   a glance that there's more to scroll to once this row gets crowded. */
.control-strip {
  display: flex; align-items: center; gap: 14px; flex-wrap: nowrap;
  padding: 7px 16px; border-bottom: 1px solid var(--border);
  background: var(--bg1); overflow-x: auto; scrollbar-width: thin;
}
.control-strip::-webkit-scrollbar { height: 6px; }
.control-strip::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }
.cs-group { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; white-space: nowrap; }
.cs-label {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--muted2); font-weight: 600; cursor: default;
}
label.cs-label { cursor: pointer; }
.cs-sep { flex: 0 0 auto; width: 1px; height: 18px; background: var(--border2); }
.cs-spacer { flex: 1 1 auto; min-width: 12px; }
.cs-select {
  padding: 2px 4px; border-radius: 4px; border: 1px solid var(--border2);
  background: transparent; color: var(--muted); font-size: 11px; cursor: pointer;
}
.cs-input {
  width: 48px; padding: 2px 4px; border-radius: 4px; border: 1px solid var(--border2);
  background: transparent; color: var(--muted); font-size: 11px;
}
.cs-unit { font-size: 11px; color: var(--muted); }
.cs-btn {
  padding: 3px 10px; border-radius: 5px; border: 1px solid var(--border2);
  background: transparent; color: var(--muted); font-size: 11px; cursor: pointer;
}
.cs-btn:hover { color: var(--text); border-color: var(--muted); }
.cs-btn-danger { border-color: rgba(248,113,113,0.4); color: var(--red,#f87171); }
.cs-btn-danger:hover { border-color: var(--red,#f87171); background: rgba(248,113,113,0.08); }

/* Command palette trigger (command_palette.js) — a full-width bar beneath the
   Focus/Topics strip, not a button crammed into the busy top nav. Still a
   button under the hood (click opens the palette overlay), but shaped, sized
   and labeled like a real search field so it reads as one at a glance. */
.search-strip {
  padding: 10px 20px 14px; border-bottom: 1px solid var(--border); background: var(--bg1);
}
.search-strip-title {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.7px;
  color: var(--muted); font-weight: 600; margin-bottom: 6px;
}
.search-strip-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; max-width: 620px;
  padding: 10px 14px; border-radius: 9px; border: 1px solid var(--border2);
  background: var(--bg2); color: var(--muted); font-size: 13px; cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.search-strip-btn:hover {
  border-color: var(--accent2); color: var(--text); background: var(--bg3);
  box-shadow: 0 2px 10px rgba(108,99,255,0.15);
}
.search-strip-icon { font-size: 15px; color: var(--muted); }
.search-strip-btn:hover .search-strip-icon { color: var(--accent2); }
.search-strip-placeholder { flex: 1; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.search-strip-kbd {
  padding: 2px 7px; border-radius: 5px; border: 1px solid var(--border2);
  font-size: 10.5px; color: var(--muted2); font-family: monospace; flex: none;
  background: var(--bg1);
}

/* Panel-jump highlight (command_palette.js _cpJumpToPanel) — a brief pulse so
   the panel a search result lands on is unmistakable, not just "somewhere on
   this now-scrolled page". Pure CSS transition, no animation library. */
.cp-jump-highlight { outline: 2px solid var(--accent); outline-offset: 2px; transition: outline-color 1.1s ease-out; }
.cp-jump-highlight.cp-jump-fade { outline-color: transparent; }

/* Simple ↔ Pro view toggle (segmented control) */
.view-mode-toggle { display: inline-flex; border: 1px solid var(--border2); border-radius: 7px; overflow: hidden; background: var(--bg2); }
.view-mode-toggle .vm-btn { padding: 3px 11px; font-size: 11px; font-weight: 600; letter-spacing: 0.2px; color: var(--muted); background: transparent; border: none; cursor: pointer; transition: all 0.15s; line-height: 1.6; }
.view-mode-toggle .vm-btn:hover { color: var(--text); }
.view-mode-toggle .vm-btn.active { background: var(--accent); color: #fff; }

/* Simple mode hides advanced panels. Additive: default (Pro) shows everything;
   only .mode-simple suppresses .adv-only. The mode class rides on <html> (set
   by an inline head script) so the FIRST paint already respects it — no flash
   of the full pro layout for Simple users. !important beats inline display
   styles on panels that also toggle display (e.g. lazily-shown cards). */
:root.mode-simple .adv-only { display: none !important; }
/* Table columns that are prosumer-only (e.g. the watchlist's extra return
   horizons, Sharpe, MDD). Marked on both the <th> and matching <td> so a whole
   column collapses in Simple mode, leaving a lean, readable set. */
:root.mode-simple .wl-adv-col { display: none; }
/* A gentle hint shown at the foot of a slimmed page, prompting the upgrade to
   Pro. Present in the DOM always; only visible in Simple mode. */
.pro-hint { display: none; }
:root.mode-simple .pro-hint { display: block; }

/* Plain ↔ technical labels. A `.term` wraps a plain-language `.term-plain`
   (shown in Simple, with the jargon kept as a small secondary `.term-sub`) and
   the `.term-pro` technical form (shown in Pro). Lets newcomers read "Reward for
   risk" while power users still see "Sharpe / Sortino" — same element, no JS. */
.term-plain { display: none; }
.term-pro   { display: inline; }
:root.mode-simple .term-plain { display: inline; }
:root.mode-simple .term-pro   { display: none; }
.term-sub { font-size: 0.82em; color: var(--muted2); font-weight: 400; letter-spacing: 0; }

/* ── Personalization: "Focus" (topic) + panel layout axes ──────────────────────
   Orthogonal to the Simple/Advanced depth toggle above. See js/interests.js and
   js/layout_customize.js.

   Topic gating: every gated panel carries data-facet="<facet>". A class
   focus-off-<facet> on <html> (added by interests.js / the pre-paint snippet for
   any facet the user has NOT chosen) hides that facet's panels. !important beats
   the inline display styles some panels toggle (e.g. market-context-card), the
   same reason .adv-only uses it. Each gated panel currently has exactly one
   facet, so a single-facet hide rule is sufficient. (There used to also be a
   whole-tab "Section" toggle for Signals — removed; that tab is always shown.) */
:root.focus-off-risk        [data-facet~="risk"]        { display: none !important; }
:root.focus-off-exposures   [data-facet~="exposures"]   { display: none !important; }
:root.focus-off-income_tax  [data-facet~="income_tax"]  { display: none !important; }

/* Per-panel show/hide (layout axis). User-explicit, so it wins over everything. */
[data-hidden] { display: none !important; }

/* Empty-state shown when a whole tab's topic is switched off. Only the Scenarios
   tab needs it (all data-facet="risk", a cross-cutting topic that can blank the
   tab). Hidden normally; revealed only when that topic is off. */
.focus-empty-state { display: none; }
:root.focus-off-risk #scenarios-off-notice { display: block; }

/* Focus bar — the control strip under the nav. Two scopes, visually grouped:
   left = app-wide TOPICS (chip toggles), right = THIS TAB (panel customizer).
   A control strip, not content — but the on/off states must be unmistakable. */
.focus-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px;
  padding: 8px 20px; border-bottom: 1px solid var(--border);
  background: var(--bg1); font-size: 11px;
}
.focus-topics { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.focus-tabtools { display: flex; align-items: center; margin-left: auto; }
.focus-lead {
  display: inline-flex; align-items: baseline; gap: 6px; margin-right: 4px;
  text-transform: uppercase; letter-spacing: 0.7px; color: var(--muted);
  font-weight: 600;
}
.focus-lead-note {
  text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--muted2);
  font-size: 10px;
}
/* Off state: a clearly-present, shaded pill (never near-invisible). On state:
   accent-filled with a ✓ so identity isn't colour-alone. */
.focus-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 11px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--border2); background: var(--bg2);
  color: var(--muted); font-size: 11px; line-height: 1.4; transition: all 0.12s;
}
.focus-chip .fc-tick { font-size: 9px; width: 8px; text-align: center; }
.focus-chip:hover { color: var(--text); border-color: var(--muted); }
.focus-chip.active {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
.focus-reset, .focus-customize {
  padding: 3px 10px; border-radius: 5px; cursor: pointer;
  border: 1px solid var(--border2); background: transparent;
  color: var(--muted); font-size: 11px;
}
.focus-reset { border-style: dashed; margin-left: 2px; }
.focus-reset:hover, .focus-customize:hover { color: var(--text); border-color: var(--muted); }
.focus-customize { font-weight: 600; }
/* First-run hint — full-width row under the controls; dismissible, one-time. */
.focus-hint {
  flex-basis: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 2px; padding: 6px 10px; border-radius: 6px;
  background: var(--bg2); border: 1px solid var(--border2);
  color: var(--muted); font-size: 10.5px; line-height: 1.45;
}
.focus-hint strong { color: var(--text); font-weight: 600; }
.focus-hint-x {
  flex: none; padding: 2px 10px; border-radius: 5px; cursor: pointer;
  border: 1px solid var(--border2); background: transparent; color: var(--muted); font-size: 10.5px;
}
.focus-hint-x:hover { color: var(--text); border-color: var(--muted); }

/* Panel customizer popover (layout_customize.js) */
.pc-overlay {
  position: fixed; inset: 0; z-index: 10000; display: flex;
  align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.62); padding: 20px;
}
.pc-dialog {
  width: 100%; max-width: 460px; max-height: 82vh; display: flex; flex-direction: column;
  background: var(--bg1); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.pc-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px 8px; }
.pc-title { font-size: 15px; font-weight: 700; color: var(--text); letter-spacing: -0.2px; }
.pc-close { background: none; border: none; color: var(--muted); font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
.pc-close:hover { color: var(--text); }
.pc-sub { font-size: 11.5px; color: var(--muted); line-height: 1.5; padding: 0 18px 10px; }
.pc-focus-note {
  margin: 0 18px 10px; padding: 6px 10px; border-radius: 6px;
  background: var(--bg2); border: 1px solid var(--border2);
  font-size: 10.5px; color: var(--muted); line-height: 1.45;
}
.pc-list { overflow-y: auto; padding: 4px 10px; }
.pc-group {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--muted2); font-weight: 600;
  padding: 12px 8px 4px; margin-top: 2px;
}
.pc-group:first-child { padding-top: 4px; }
.pc-row {
  display: flex; align-items: center; gap: 10px; padding: 7px 8px;
  border-radius: 6px; cursor: pointer; color: var(--text);
}
.pc-row:hover { background: var(--bg2); }
.pc-row input { cursor: pointer; width: 15px; height: 15px; accent-color: var(--accent); flex: none; }
.pc-row.pc-pinned { cursor: default; }
.pc-row.pc-pinned input { cursor: not-allowed; }
.pc-text { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pc-name { font-size: 13px; line-height: 1.3; }
.pc-blurb { font-size: 10.5px; color: var(--muted); line-height: 1.3; }
.pc-lock { flex: none; font-size: 11px; opacity: 0.6; }
.pc-empty { padding: 18px; text-align: center; color: var(--muted); font-size: 12px; }
.pc-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 18px; border-top: 1px solid var(--border); margin-top: 4px;
}
.pc-reset { background: none; border: none; color: var(--muted); font-size: 11.5px; cursor: pointer; text-decoration: underline; }
.pc-reset:hover { color: var(--text); }
.pc-done {
  padding: 6px 18px; border-radius: 6px; border: 1px solid var(--accent);
  background: var(--accent); color: #fff; font-size: 12px; font-weight: 600; cursor: pointer;
}

/* Ticker drawer (ticker_drawer.js) — a right-side slide-over, opened from any
   [data-open-ticker] element anywhere in the app (holdings table, watchlist,
   contributors bar, command palette results). Consolidates one ticker's info
   into one place instead of it being scattered across tabs. */
.td-overlay {
  position: fixed; inset: 0; z-index: 10001;
  background: rgba(0, 0, 0, 0.5); opacity: 0; transition: opacity 0.15s;
  display: flex; justify-content: flex-end;
}
.td-overlay.open { opacity: 1; }
.td-panel {
  width: 100%; max-width: 420px; height: 100%; background: var(--bg1);
  border-left: 1px solid var(--border); box-shadow: -12px 0 40px rgba(0,0,0,0.4);
  transform: translateX(100%); transition: transform 0.18s ease-out;
  display: flex; flex-direction: column; overflow: hidden;
}
.td-overlay.open .td-panel { transform: translateX(0); }
.td-body { overflow-y: auto; flex: 1; }
.td-head { padding: 20px 20px 16px; border-bottom: 1px solid var(--border); position: relative; }
.td-close {
  position: absolute; top: 14px; right: 14px; background: none; border: none;
  color: var(--muted); font-size: 22px; line-height: 1; cursor: pointer; padding: 2px 6px;
}
.td-close:hover { color: var(--text); }
.td-title-row { display: flex; align-items: center; gap: 8px; padding-right: 30px; }
.td-ticker { font-size: 19px; font-weight: 700; color: var(--text); letter-spacing: -0.3px; }
.td-name { font-size: 12px; color: var(--muted); margin-top: 2px; }
.td-price-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; margin-top: 10px; }
.td-price { font-size: 15px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.td-status {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.4px; font-weight: 600;
  padding: 2px 8px; border-radius: 8px;
}
.td-status-held { color: var(--green); background: rgba(34,211,160,0.12); }
.td-status-watched { color: var(--accent2); background: rgba(139,133,255,0.12); }
.td-status-elsewhere { color: var(--amber); background: rgba(245,158,11,0.12); cursor: help; }
.td-range { margin-top: 12px; }
.td-simple { padding: 18px 20px; }
.td-simple-text { font-size: 13px; color: var(--text); line-height: 1.6; }
.td-switch-btn {
  margin-top: 14px; padding: 7px 14px; border-radius: 6px; border: 1px solid var(--border2);
  background: transparent; color: var(--muted); font-size: 11.5px; cursor: pointer;
}
.td-switch-btn:hover { color: var(--text); border-color: var(--muted); }
.td-advanced { padding: 16px 20px 20px; }
.td-advanced .detail-grid { grid-template-columns: 1fr 1fr; }
.td-signals { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.td-sig-row {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12px; padding: 5px 0; color: var(--text);
}
.td-sig-label { color: var(--muted); }
.td-untracked { padding: 18px 20px; }

/* Command palette (command_palette.js) — reuses .pc-overlay/.pc-dialog/.pc-list/
   .pc-row/.pc-text/.pc-name/.pc-blurb/.pc-empty from the panel customizer so the
   two modal patterns in the app stay visually consistent; .cp-* only adds what's
   actually different (top-anchored instead of centered, the search input, the
   keyboard-nav highlight, and the kind icon/sub-label per row). */
.cp-overlay { align-items: flex-start; padding-top: 12vh; }
.cp-dialog { max-width: 560px; }
.cp-input-row { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.cp-input-icon { color: var(--muted); font-size: 15px; }
.cp-input { flex: 1; background: none; border: none; outline: none; color: var(--text); font-size: 14px; }
.cp-input::placeholder { color: var(--muted); }
.cp-list { max-height: 50vh; }
.cp-row { justify-content: space-between; }
.cp-row.cp-active { background: var(--bg2); }
.cp-icon { flex: none; color: var(--muted); font-size: 13px; width: 16px; text-align: center; }
.cp-sub { flex: none; font-size: 10px; color: var(--muted2); text-transform: uppercase; letter-spacing: 0.4px; }
.cp-foot {
  padding: 8px 18px; border-top: 1px solid var(--border);
  font-size: 10px; color: var(--muted2); letter-spacing: 0.2px;
}

/* Narrative "Translation:" strip — one plain-English sentence that turns a dense
   pro panel (correlations, beta, concentration) into a teaching moment. Filled
   by buildNarratives(); hidden when empty. */
.narrative { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 12px; padding: 9px 12px;
  background: var(--bg2); border-radius: 7px; border-left: 2px solid var(--accent); }
.narrative:empty { display: none; }
.narrative .narrative-tag { font-size: 10px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--accent2); font-weight: 700; flex-shrink: 0; padding-top: 1px; }
.narrative .narrative-text { font-size: 12px; color: var(--text); line-height: 1.5; }

/* First-run guided reveal (onboarding_tour.js). Non-blocking: the dim is a
   spotlight cutout via the ring's huge box-shadow, so the highlighted element
   stays bright and clicks pass through to the app. */
#tour-overlay { position: fixed; inset: 0; z-index: 9998; pointer-events: none; }
.tour-ring {
  position: fixed; border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(0,0,0,0.55), 0 0 0 2px var(--accent), 0 0 22px 2px rgba(108,99,255,0.55);
  transition: top .25s ease, left .25s ease, width .25s ease, height .25s ease;
  pointer-events: none;
}
.tour-tip {
  position: fixed; max-width: 330px; background: var(--bg1);
  border: 1px solid var(--border2); border-radius: 10px; padding: 14px 16px;
  z-index: 9999; pointer-events: auto; box-shadow: 0 12px 44px rgba(0,0,0,0.55);
}
.tour-tip .tour-count { font-size: 10px; text-transform: uppercase; letter-spacing: 0.7px; color: var(--muted2); margin-bottom: 6px; }
.tour-tip .tour-title { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 6px; letter-spacing: -0.2px; }
.tour-tip .tour-body { font-size: 12.5px; color: var(--muted); line-height: 1.55; margin-bottom: 14px; }
.tour-tip .tour-actions { display: flex; align-items: center; justify-content: space-between; }
.tour-tip .tour-skip { background: transparent; border: none; color: var(--muted2); font-size: 11px; cursor: pointer; padding: 4px 2px; }
.tour-tip .tour-skip:hover { color: var(--muted); }
.tour-tip .tour-next { background: var(--accent); border: none; color: #fff; font-size: 12px; font-weight: 600; padding: 6px 16px; border-radius: 6px; cursor: pointer; }
.tour-tip .tour-next:hover { background: var(--accent2); }
.pill { padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 500; }
.pill-green { background: rgba(34,211,160,0.12); color: var(--green); }
.pill-red { background: rgba(255,92,122,0.12); color: var(--red); }
.pill-amber { background: rgba(245,158,11,0.12); color: var(--amber); }

/* Layout */
.page { display: none; padding: 28px 24px 60px; max-width: 1400px; margin: 0 auto; }
.page.active { display: block; }

/* Reference pages (FAQ / Learn / Methodology / Feedback): a bordered, narrower
   reading column with a left accent, so informational content is visually
   distinct from the functional analytics dashboards. */
.resource-panel { max-width: 800px; margin: 4px auto 0; border: 1px solid var(--border2); border-left: 3px solid var(--accent, #6c63ff); border-radius: 10px; background: var(--bg2); padding: 24px 30px; }
.resource-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: 0.9px; text-transform: uppercase; color: var(--accent, #6c63ff); margin-bottom: 8px; }
.resource-title { font-size: 20px; font-weight: 700; letter-spacing: -0.2px; color: var(--text); margin-bottom: 6px; }

/* Cards */
.card { background: var(--bg1); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; }
.card-sm { padding: 16px; }
.card-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.8px; color: var(--muted); margin-bottom: 6px; font-weight: 500; }
.card-value { font-size: 28px; font-weight: 600; letter-spacing: -0.5px; }
.card-sub { font-size: 12px; color: var(--muted); margin-top: 4px; }

/* Grids */
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-2-1 { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; }
.grid-1-2 { display: grid; grid-template-columns: 1fr 2fr; gap: 16px; }
.gap-16 { gap: 16px; }
.mb-12 { margin-bottom: 12px; }
.mb-16 { margin-bottom: 16px; }
.mb-20 { margin-bottom: 20px; }
.mb-24 { margin-bottom: 24px; }

/* Typography */
.section-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
.section-title .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
/* Page-level group header — separates the sub-sections of a dense page
   (Risk / Signals / Lab). Deliberately quieter than a card's .section-title. */
.group-header { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.9px; color: var(--muted); margin: 26px 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.group-header:first-child { margin-top: 4px; }

/* Chart containers */
.chart-wrap { position: relative; width: 100%; }

/* Table */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th { padding: 10px 12px; text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--muted2); font-weight: 500; border-bottom: 1px solid var(--border); white-space: nowrap; }
td { padding: 11px 12px; border-bottom: 1px solid var(--border); color: var(--text); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--bg2); }
.td-muted { color: var(--muted); }
.td-mono { font-family: 'SF Mono', monospace; font-size: 12px; }

/* Tags */
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10.5px; font-weight: 500; }
.tag-stock { background: rgba(57,135,229,0.14); color: var(--series-1); }
.tag-etf { background: rgba(217,89,38,0.14); color: var(--series-2); }
.tag-crypto { background: rgba(25,158,112,0.14); color: var(--series-3); }

/* P&L colours */
.pos { color: var(--green); }
.neg { color: var(--red); }
.neu { color: var(--muted); }

/* Expandable rows */
.expanded-row td { background: var(--bg2); }
.detail-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; padding: 6px 0; }
.detail-label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
.detail-val { font-size: 13px; font-weight: 500; }

/* Bar */
.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.bar-label { font-size: 12px; color: var(--text); width: 150px; flex-shrink: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-track { flex: 1; background: var(--bg3); border-radius: 3px; height: 6px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 3px; transition: width 0.4s; }
.bar-pct { font-size: 12px; color: var(--muted); width: 45px; text-align: right; flex-shrink: 0; }
/* Exposure bar lists (sector/geo/thematic/currency) can run long — cap the
   height and scroll the overflow so a card never stretches arbitrarily. Short
   lists size to content; the cap only engages past ~10 rows. The 4px scrollbar
   is styled globally. scrollbar-gutter keeps the % column from shifting when a
   scrollbar appears; the small right padding keeps it off the numbers. */
.exp-scroll { max-height: 260px; overflow-y: auto; padding-right: 6px; scrollbar-gutter: stable; }
/* The trailing row's margin is redundant inside a scroll box. */
.exp-scroll .bar-row:last-child { margin-bottom: 0; }

/* Score ring */
.score-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.score-num { font-size: 32px; font-weight: 600; letter-spacing: -1px; }
.score-label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; }

/* Heatmap cell */
.hm-cell { display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 500; border-radius: 3px; }

/* Macro bar */
.macro-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.macro-row:last-child { border-bottom: none; }
.macro-factor { font-size: 12px; color: var(--text); width: 120px; }
.macro-bar-wrap { flex: 1; position: relative; height: 4px; background: var(--bg3); border-radius: 2px; }
.macro-bar { position: absolute; top: 0; height: 100%; border-radius: 2px; }
.macro-val { font-size: 12px; font-family: monospace; width: 55px; text-align: right; }
.macro-interp { font-size: 11px; color: var(--muted); }

/* Market context strip — stat tiles with a sparkline.
   Six tiles at desktop, folding to 3 / 2 rather than shrinking below a legible
   number width. The sparkline is deliberately recessive (muted, 1.5px): it is
   context for the headline value, not the subject of the tile. */
.mkt-intro { font-size: 11.5px; color: var(--muted); line-height: 1.65; margin-bottom: 14px; max-width: 90ch; }
.mkt-intro b { color: var(--text); font-weight: 600; }
.mkt-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; }
.mkt-tile { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 11px 12px 9px; min-width: 0; }
.mkt-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Inline per-indicator description (was hover-only). Clamped to 2 lines with a
   reserved min-height so the value / sparkline / exposure rows stay aligned
   across tiles whose descriptions differ in length. */
.mkt-hint { font-size: 9.5px; color: var(--muted2); line-height: 1.35; margin-top: 3px; min-height: 26px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mkt-value { font-size: 17px; font-weight: 600; letter-spacing: -0.3px; font-variant-numeric: tabular-nums; margin-top: 3px; }
/* Direction is carried by the GLYPH, not by colour alone — and deliberately not
   by the green/red P&L palette: "10Y up" or "dollar up" has no inherent good or
   bad, and painting it as gain/loss would assert a judgment this app cannot
   justify. Portfolio-relative interpretation lives in .mkt-exposure below. */
.mkt-delta { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; margin-top: 1px; }
.mkt-spark { display: block; width: 100%; height: 22px; margin-top: 7px; overflow: visible; }
.mkt-spark polyline { fill: none; stroke: var(--muted); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.mkt-exposure { font-size: 10px; color: var(--muted2); margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mkt-exposure b { color: var(--muted); font-weight: 600; font-variant-numeric: tabular-nums; }
@media (max-width: 1100px) { .mkt-strip { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px)  { .mkt-strip { grid-template-columns: repeat(2, 1fr); } }

/* Factor lens — factor return (diverging bar) vs this portfolio's exposure.
   Returns get the gain/loss palette here, unlike the market-context strip's
   level deltas: a factor RETURN has an unambiguous direction, whereas "VIX up"
   does not. */
.lens-head, .lens-row { display: grid; grid-template-columns: 150px 1fr 62px 92px; align-items: center; gap: 10px; }
.lens-head { font-size: 9px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--muted2); padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.lens-row { padding: 9px 0; border-bottom: 1px solid var(--border); }
.lens-row:last-child { border-bottom: none; }
.lens-name { font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lens-bar-wrap { position: relative; height: 5px; background: var(--bg3); border-radius: 3px; }
.lens-bar-wrap::before { content: ''; position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--border2); }
.lens-bar { position: absolute; top: 0; height: 100%; border-radius: 3px; }
.lens-ret { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; margin-top: 3px; }
.lens-beta { font-size: 11px; font-family: monospace; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.lens-effect { font-size: 11px; text-align: right; font-variant-numeric: tabular-nums; }
.lens-effect small { display: block; font-size: 9px; color: var(--muted2); font-variant-numeric: normal; }
.lens-note { font-size: 10px; color: var(--muted2); margin-top: 10px; line-height: 1.5; }
@media (max-width: 700px) {
  .lens-head { display: none; }
  .lens-row { grid-template-columns: 1fr 78px; grid-template-areas: 'name effect' 'bar bar'; row-gap: 5px; }
  .lens-name { grid-area: name; }
  .lens-effect { grid-area: effect; }
  .lens-bar-col { grid-area: bar; }
  .lens-beta { display: none; }   /* the effect column already carries the signal */
}

/* Factor attribution card — ex-post decomposition of realized return */
.attr-summary { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.attr-actual-val { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.attr-actual-val.pos { color: var(--green); } .attr-actual-val.neg { color: var(--red); }
.attr-actual-lbl { font-size: 10px; color: var(--muted2); text-transform: uppercase; letter-spacing: 0.6px; margin-left: 8px; }
.attr-split { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.attr-plus { margin: 0 6px; color: var(--muted2); }
.attr-head, .attr-row { display: grid; grid-template-columns: 150px 1fr 70px; align-items: center; gap: 10px; }
.attr-head { font-size: 9px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--muted2); padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.attr-row { padding: 9px 0; border-bottom: 1px solid var(--border); }
.attr-row:last-child { border-bottom: none; }
.attr-row-resid { background: var(--bg3); border-radius: 6px; padding: 9px 8px; margin-top: 6px; border-bottom: none; }
.attr-name { font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.attr-bar-wrap { position: relative; height: 5px; background: var(--bg3); border-radius: 3px; }
.attr-bar-wrap::before { content: ''; position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--border2); }
.attr-bar { position: absolute; top: 0; height: 100%; border-radius: 3px; }
.attr-sub { font-size: 9px; color: var(--muted2); margin-top: 3px; font-variant-numeric: tabular-nums; }
.attr-contrib { font-size: 11px; text-align: right; font-variant-numeric: tabular-nums; }
.attr-contrib.pos { color: var(--green); } .attr-contrib.neg { color: var(--red); }
.attr-note { font-size: 10px; color: var(--muted2); margin-top: 10px; line-height: 1.5; }
.attr-note.attr-ok { color: var(--green); } .attr-note.attr-warn { color: var(--red); }
@media (max-width: 700px) {
  .attr-head { display: none; }
  .attr-row { grid-template-columns: 1fr 70px; grid-template-areas: 'name contrib' 'bar bar'; row-gap: 5px; }
  .attr-name { grid-area: name; }
  .attr-contrib { grid-area: contrib; }
  .attr-bar-col { grid-area: bar; }
}

/* Currencies card */
.fx-summary { font-size: 12px; color: var(--text); margin-bottom: 12px; line-height: 1.5; }
.fx-summary b { font-variant-numeric: tabular-nums; }
.fx-head, .fx-row { display: grid; grid-template-columns: 88px 84px 62px 62px 1fr 74px; align-items: center; gap: 10px; }
.fx-head { font-size: 9px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--muted2); padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.fx-row { padding: 8px 0; border-bottom: 1px solid var(--border); }
.fx-row:last-child { border-bottom: none; }
.fx-row.held { background: linear-gradient(90deg, rgba(108,99,255,0.06), transparent 60%); }
.fx-pair { font-size: 12px; color: var(--text); }
.fx-rate { font-size: 12px; font-family: monospace; font-variant-numeric: tabular-nums; }
/* Muted, not gain/loss coloured — see _fxCls() for why green here would
   actively mislead the holder the row is highlighted for. */
.fx-chg { font-size: 11px; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); }
.fx-spark { display: block; width: 100%; height: 18px; overflow: visible; }
.fx-spark polyline { fill: none; stroke: var(--muted); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.fx-exp { font-size: 10px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 760px) {
  .fx-head { display: none; }
  .fx-row { grid-template-columns: 1fr auto auto; gap: 8px; }
  .fx-spark { display: none; }        /* the numbers survive; the trend is the luxury */
  .fx-row > .fx-chg.ytd { display: none; }
}

/* Scenario card */
.scenario-card { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px; }
.scenario-name { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
.scenario-return { font-size: 22px; font-weight: 600; }
.scenario-dates { font-size: 10px; color: var(--muted); margin-top: 4px; }

/* Cluster */
.cluster-row { padding: 10px 14px; background: var(--bg2); border-radius: var(--radius-sm); margin-bottom: 6px; display: flex; align-items: center; gap: 12px; }
.cluster-assets { font-size: 12px; color: var(--text); flex: 1; }
.cluster-pct { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* Personality badge */
.personality { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 20px; font-size: 12px; font-weight: 600; background: rgba(108,99,255,0.15); color: var(--accent2); border: 1px solid rgba(108,99,255,0.25); }

/* Exposure dot */
.exp-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* Divider */
.divider { border: none; border-top: 1px solid var(--border); margin: 20px 0; }

/* Scrollbar */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bg3); border-radius: 2px; }

@media (max-width: 900px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-2-1, .grid-1-2, .grid-2 { grid-template-columns: 1fr; }
}

/* ── New features ────────────────────────────────────────────────────────── */

/* Date range & filter strip buttons */
.range-btn {
  padding: 3px 10px; border-radius: 5px;
  border: 1px solid var(--border2); font-size: 11px; cursor: pointer;
  color: var(--muted); background: transparent; transition: all 0.15s;
  font-family: var(--font);
}
.range-btn.active, .range-btn:hover { background: var(--bg2); color: var(--text); }

/* Utility spacing */
.mt-16 { margin-top: 16px; }

/* Simulator / scenario form elements */
.sim-form { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
.sim-field { display: flex; flex-direction: column; gap: 4px; }
.sim-label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.sim-input {
  background: var(--bg2); border: 1px solid var(--border2); border-radius: 5px;
  padding: 6px 8px; color: var(--text); font-size: 12px; font-family: var(--font);
  width: 100%; box-sizing: border-box; transition: border-color 0.15s;
}
.sim-input:focus { outline: none; border-color: var(--accent); }
.sim-btn {
  padding: 7px 16px; background: var(--accent); color: #fff;
  border: none; border-radius: 6px; font-size: 12px; font-family: var(--font);
  cursor: pointer; transition: opacity 0.15s;
}
.sim-btn:hover { opacity: 0.85; }

/* Delta indicators */
.delta-pos { color: var(--green); }
.delta-neg { color: var(--red); }
.delta-neu { color: var(--muted); }

/* Opportunity gap */
.gap-pos { color: var(--green); }
.gap-neg { color: var(--red); }

/* Rebalancing rows */
.rebal-row {
  display: grid; grid-template-columns: 70px 1fr 80px 60px 1fr;
  gap: 6px; align-items: center; padding: 5px 0;
  border-bottom: 1px solid var(--border); font-size: 12px;
}
.rebal-hdr { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.rebal-input {
  background: var(--bg2); border: 1px solid var(--border2); border-radius: 4px;
  padding: 3px 6px; color: var(--text); font-size: 11px; font-family: var(--font);
  width: 60px; text-align: right;
}
.rebal-input:focus { outline: none; border-color: var(--accent); }

/* Tax status tags */
.tag-lt      { background: rgba(34,211,160,0.15); color: #22d3a0; }
.tag-st      { background: rgba(245,158,11,0.15);  color: #f59e0b; }
.tag-harvest { background: rgba(255,92,122,0.15);  color: #ff5c7a; }

/* ── Token Generator ─────────────────────────────────────────────────────── */

/* Stepper */
.tk-stepper { display: flex; align-items: center; }
.tk-step { display: flex; align-items: center; gap: 8px; }
.tk-step-dot {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--bg3); border: 1px solid var(--border2);
  color: var(--muted); font-size: 11px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.tk-step.active .tk-step-dot { background: var(--accent); border-color: var(--accent); color: #fff; }
.tk-step.done   .tk-step-dot { background: rgba(34,211,160,0.12); border-color: var(--green); color: var(--green); }
.tk-step-label { font-size: 12px; color: var(--muted); white-space: nowrap; }
.tk-step.active .tk-step-label { color: var(--text); font-weight: 500; }
.tk-step.done   .tk-step-label { color: var(--green); }
.tk-step-line { flex: 1; height: 1px; background: var(--border); margin: 0 10px; min-width: 20px; transition: background 0.2s; }
.tk-step-line.done { background: var(--green); }

/* Network selector */
.tk-network-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 4px; }
.tk-network-btn {
  padding: 10px 8px; background: var(--bg2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); cursor: pointer; text-align: center;
  transition: border-color 0.15s, background 0.15s; font-family: var(--font);
}
.tk-network-btn:hover  { border-color: var(--border2); background: var(--bg3); }
.tk-network-btn.active { border-color: var(--accent); background: rgba(108,99,255,0.1); }
.tk-network-label { font-size: 12px; font-weight: 500; color: var(--text); }
.tk-network-sub   { font-size: 10px; color: var(--muted); margin-top: 3px; }

/* Feature toggle row */
.tk-feature-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0; border-bottom: 1px solid var(--border); gap: 12px;
}
.tk-feature-row:last-child { border-bottom: none; }
.tk-toggle {
  width: 38px; height: 22px; border-radius: 11px; background: var(--bg3);
  border: 1px solid var(--border2); cursor: pointer; position: relative;
  transition: background 0.2s, border-color 0.2s; flex-shrink: 0;
}
.tk-toggle.on { background: var(--accent); border-color: var(--accent); }
.tk-toggle-knob {
  width: 16px; height: 16px; border-radius: 50%; background: var(--muted2);
  position: absolute; top: 2px; left: 2px; transition: left 0.2s, background 0.2s;
}
.tk-toggle.on .tk-toggle-knob { left: 18px; background: #fff; }

/* Tokenomics allocation row */
.tk-alloc-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border); }
.tk-alloc-row:last-child { border-bottom: none; }
.tk-alloc-swatch { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.tk-alloc-label  { font-size: 12px; color: var(--text); width: 76px; flex-shrink: 0; }
.tk-slider {
  -webkit-appearance: none; appearance: none;
  flex: 1; height: 4px; border-radius: 2px; background: var(--bg3); outline: none; cursor: pointer;
}
.tk-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 50%; background: var(--accent); cursor: pointer;
}
.tk-alloc-total { font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 5px; }
.tk-alloc-total.ok  { background: rgba(34,211,160,0.1);  color: var(--green); }
.tk-alloc-total.err { background: rgba(245,158,11,0.1);  color: var(--amber); }
.tk-alloc-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; gap: 1px; }

/* Deploy stages */
.tk-stage { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 12px; color: var(--muted); }
.tk-stage:last-child { border-bottom: none; }
.tk-stage.active { color: var(--text); }
.tk-stage.done   { color: var(--green); }
.tk-stage-spinner {
  width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid var(--bg3); border-top-color: var(--accent);
  animation: tk-spin 0.7s linear infinite;
}
.tk-stage-check {
  width: 14px; height: 14px; flex-shrink: 0; font-size: 12px;
  display: flex; align-items: center; justify-content: center; color: var(--green);
}
.tk-stage-check::before { content: '✓'; }
@keyframes tk-spin { to { transform: rotate(360deg); } }

/* Token logo */
.tk-token-logo {
  width: 64px; height: 64px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent) 0%, var(--purple) 100%);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; color: #fff; margin: 0 auto;
  letter-spacing: 0.5px;
}

/* Preview card */
.tk-preview-card {
  background: var(--bg1); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 20px;
  position: sticky; top: 70px;
}

/* ── Print / PDF export (PDF V1: window.print() "Download report") ──────────── */
/* Remaps the dark theme to an ink-friendly light palette, hides all interactive
   chrome, and prints only the active page. Anything tagged .no-print is dropped. */
@media print {
  :root {
    --bg: #ffffff; --bg1: #ffffff; --bg2: #f4f4f7; --bg3: #ececf2;
    --border: rgba(0,0,0,0.12); --border2: rgba(0,0,0,0.20);
    --text: #101018; --muted: #4a4a5a; --muted2: #6a6a7a;
  }
  body { background: #fff; }
  /* Chrome + interactive controls that don't belong in a report. */
  .nav, .control-strip, .no-print, #nav-currency,
  .range-btn, .sim-btn, button, select, input,
  .ad-slot, [id^="ad-"], #onboarding, .modal, .modal-backdrop { display: none !important; }
  /* Print every page's content, not just the on-screen active one is overkill —
     print only the active page so the report matches what the user sees. */
  .page { display: none !important; }
  .page.active { display: block !important; }
  .card { background: #fff; border: 1px solid var(--border); break-inside: avoid; page-break-inside: avoid; }
  .card, .grid-2, .grid-3, .grid-4, .grid-2-1 { box-shadow: none !important; }
  canvas { max-width: 100% !important; }
  a { color: inherit; text-decoration: none; }
}
