/* Shared theme + common components for every page. Single source of color
   variables (dark default, light override) so the toggle works everywhere.
   Badges/pills/tags are TINTED from one base color via color-mix() so they
   auto-adapt: dark tint + light text in dark mode, light tint + dark text in
   light mode. Nothing hard-codes a dark background. */

/* Inter — the typeface used by the Bitcoin Vector dashboard and the landing
   hub. SELF-HOSTED (was a Google Fonts web import): the Google Fonts CDN is
   blocked in mainland China, so the WOFF2 files are vendored under site/fonts/
   (source: templates/fonts/, copied by build_site) and served same-origin.
   theme.css is linked by every page, so these @font-face rules give the whole
   site Inter with no third-party request. */
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url("fonts/Inter-400.woff2") format("woff2");}
@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url("fonts/Inter-500.woff2") format("woff2");}
@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url("fonts/Inter-600.woff2") format("woff2");}
@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url("fonts/Inter-700.woff2") format("woff2");}
@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url("fonts/Inter-800.woff2") format("woff2");}
@font-face{font-family:Inter;font-style:normal;font-weight:900;font-display:swap;src:url("fonts/Inter-900.woff2") format("woff2");}
:root {
  /* ── font stacks ─────────────────────────────────────────────────────────────
     --font-ui   : primary UI stack. Inter (self-hosted woff2) leads; the chain
                   covers Windows (Segoe UI), Android (Roboto), and native CJK
                   glyph coverage (PingFang SC / Hiragino / Microsoft YaHei) so
                   mixed EN+ZH text renders cleanly without the zh-body override.
     --font-mono : monospace for code, tickers, numeric labels. ui-monospace
                   resolves to SF Mono (macOS/iOS), Consolas (Windows), or the
                   platform mono — no external download needed. */
  --font-ui: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
    "Noto Sans CJK SC", sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Mono",
    Menlo, Consolas, "DejaVu Sans Mono", monospace;
  --bg: #0f1115; --panel: #181b21; --panel2: #1e222a; --text: #d7dce3;
  --muted: #8b93a1; --line: #2a2f3a;
  --q1: #2e9e4f; --q2: #d4a017; --q3: #d04545; --q4: #3f78d8;
  --warn: #e0a030; --act: #e05555; --ok: #3da564;
  --up: #45b873; --down: #e06464; --orange: #e08b45;
  --info: #5b9bf0; --link: #7aa7e0;
  --g-cold: #4d8df0; --g-hot: #e0a23c; --g-mid: #3a4150;
  --chart-bg: transparent;
  --card-shadow: 0 1px 0 rgba(255,255,255,.02);
  --popover-shadow: 0 6px 18px rgba(0,0,0,.5);
  /* ── custom scrollbars ───────────────────────────────────────────────────────
     Thumb tint derived from --muted so it adapts to dark / light / zh with no
     per-theme override (--info gives the drag-state a branded accent). Consumed
     by the global scrollbar rules further down and mirrored (with fallbacks) by
     theme.js for the self-contained pages that don't link this file. */
  --sb-thumb: color-mix(in srgb, var(--muted) 34%, transparent);
  --sb-thumb-hover: color-mix(in srgb, var(--muted) 60%, transparent);
  --sb-thumb-active: color-mix(in srgb, var(--info) 62%, var(--muted));
  /* ── frosted-glass popover system ───────────────────────────────────────────
     ONE token set shared by every floating menu surface — the top-nav dropdowns,
     the Research mega-menu, the global-search suggestions, the gear settings
     popover, the bell alert popover and the fired-alerts popup — so they all read
     as a single design family. backdrop-filter blurs the aurora + page behind the
     panel; the translucent fill lets that colour bleed through. Opacity + shadow
     are re-tuned per theme in the light block below. The self-contained vector
     family (no theme.css) mirrors these values inline in _vector_polish.html.j2
     and theme.js, so keep the three in sync if you retune the glass. */
  --glass-bg: color-mix(in srgb, var(--panel) 75%, transparent);
  --glass-brd: color-mix(in srgb, var(--text) 14%, transparent);
  --glass-blur: saturate(180%) blur(22px);
  --glass-shadow: 0 24px 64px -22px rgba(3,7,18,.74), 0 10px 26px -12px rgba(3,7,18,.55),
    inset 0 1px 0 color-mix(in srgb,#fff 10%,transparent);
}
html[data-theme="light"] {
  /* Light palette tuned to match the Bitcoin Vector dashboard: airy #F7F8FA
     canvas, white cards on a soft #EAECF0 grid, and the same vivid #285FFF
     primary so links / buttons / accents read as one design family. The dark
     theme (the :root block above) is intentionally left untouched. */
  --bg: #f7f8fa; --panel: #ffffff; --panel2: #eef1f6; --text: #1c2430;
  --muted: #5d6b7e; --line: #eaecf0;
  --q1: #1f8b41; --q2: #b07d05; --q3: #c12f2f; --q4: #2f63c4;
  --warn: #b9791a; --act: #c43d3d; --ok: #2f8a52;
  --up: #1f9a55; --down: #cf4040; --orange: #c4781f;
  --info: #285fff; --link: #285fff;
  --g-cold: #285fff; --g-hot: #c2841f; --g-mid: #cdd5e0;
  --chart-bg: #11151c;            /* keep dark-rendered Plotly charts legible */
  --card-shadow: 0 1px 3px rgba(20,30,50,.07);
  /* soft, light popover shadow — the dark theme's heavy 50%-black drop shadow
     reads as a murky grey halo on the white light-mode tooltips */
  --popover-shadow: 0 4px 10px rgba(20,30,50,.06), 0 12px 28px rgba(20,30,50,.14);
  /* light glass: brighter fill (white reads thin when too transparent) + an airy
     soft shadow with a crisp white top-edge sheen instead of the dark theme's
     heavy drop. */
  --glass-bg: color-mix(in srgb, var(--panel) 64%, transparent);
  --glass-brd: color-mix(in srgb, #1c2430 9%, transparent);
  --glass-shadow: 0 20px 54px -24px rgba(20,32,64,.34), 0 10px 24px -14px rgba(20,32,64,.20),
    inset 0 1px 0 rgba(255,255,255,.85);
}
/* ---- Chinese mode: Asia colour convention -----------------------------------
   In Asia red = up/bullish, green = down/bearish — the inverse of the West. So
   in zh mode we SWAP the up/down pair and flip the green/red quadrants
   (Goldilocks -> red, Stagflation -> green); gold (Reflation) and blue
   (Growth-scare) already read right and stay. Status colours (--ok/--warn/--act,
   data-health, alert severity) encode health/danger, NOT price direction, so
   they are deliberately left alone. Because every tinted badge, gauge, quad tile
   and .pos/.neg already resolves these vars at paint time (mtf.js re-reads them
   on `langchange`), the whole UI recolours instantly.
   Specificity note: html[data-theme="light"] and html[data-lang="zh"] tie at
   (0,1,1); the dual-attribute selector (0,2,1) below pins the light+zh combo. */
html[data-lang="zh"] {
  --up: #e06464; --down: #45b873;        /* swapped: red now = up */
  --q1: #d04545;                         /* Goldilocks -> red */
  --q3: #2e9e4f;                         /* Stagflation -> green */
}
html[data-theme="light"][data-lang="zh"] {
  --up: #cf4040; --down: #1f9a55;
  --q1: #c12f2f;
  --q3: #1f8b41;
}
/* ---- Chinese mode: directional GAUGES that paint state from status tokens ----
   The status tokens --ok/--act deliberately DON'T swap (they encode health/danger, see
   above). But a few gauges are genuine market-DIRECTION reads (bullish vs bearish) that
   happen to colour themselves from --ok/--act — the Risk Radar (.rrx: --ok=calm/risk-on,
   --act=risk-off) and the Ignition Radar (.igx/.igs: --ok=ignited/breakout). Under the
   Asia convention these must read red=risk-on/bullish, green=risk-off/bearish — matching
   the price tables and the Market State board (which already swap via --up/--down). We
   remap ONLY the pole tokens, ONLY inside these gauge scopes, so global --ok/--act stay
   Western and every health/severity/staleness/validation signal keeps red=bad. --up/--down
   already carry correct dark+light zh values, so remapping onto them needs no hex here.
   (Mid-tones --warn/--orange/--info/--muted are direction-neutral escalation — left alone.) */
html[data-lang="zh"] .rrx { --ok: var(--up); --act: var(--down); }
html[data-lang="zh"] :is(.igx, .igs) { --ok: var(--up); }
/* ---- language visibility toggle (dual-emit text) ---------------------------- */
html:not([data-lang="zh"]) .l-zh { display: none; }
html[data-lang="zh"] .l-en { display: none; }
/* CJK type: put the native CJK face first so Hanzi always uses a proper glyph
   rather than Inter's Latin fallback, and drop wide tracking on headings (looks
   wrong on Hanzi). Inter stays in the stack so any Latin mixed-in text still
   picks up the branded weight. */
html[data-lang="zh"] body {
  font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
    "Noto Sans CJK SC", "Microsoft JhengHei", "Heiti SC", Inter, sans-serif;
}
html[data-lang="zh"] h2 { letter-spacing: 0; }

a { color: var(--link); }

/* ---- custom scrollbars ------------------------------------------------------
   One themed scrollbar for the whole site — the page scroll and every scroll
   container. The tint derives from --muted (via the --sb-* tokens up top) so it
   tracks dark / light / zh automatically; a transparent track plus a rounded
   pill inset by a padding-box border reads as a floating bar, not a heavy gutter.
   Element-scoped rules (.tbl-scroll, .lst-ovl-body, the mobile chip strips) carry
   a class and out-specificity these, so their bespoke treatment is preserved.
   Firefox uses the two standard properties; WebKit / Blink the pseudo-elements. */
* { scrollbar-width: thin; scrollbar-color: var(--sb-thumb) transparent; }
*::-webkit-scrollbar { width: 11px; height: 11px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--sb-thumb); border-radius: 999px;
  border: 3px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--sb-thumb-hover); }
*::-webkit-scrollbar-thumb:active { background: var(--sb-thumb-active); }
*::-webkit-scrollbar-corner { background: transparent; }

/* Canonical UI font on every page. The `html body` selector has higher
   specificity than each page's own `body { font: 14px/1.5 -apple-system… }`
   shorthand, so it swaps the family while leaving font-size/line-height
   untouched. Uses the --font-ui token so all font-family declarations across
   the site resolve to one consistent stack. */
html body { font-family: var(--font-ui); font-size: 15px;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* ---- ambient aurora backdrop (site-wide) ------------------------------------
   The landing hub's soft accent washes, shared by every page. A fixed, full-
   viewport pseudo-element pinned behind all content (z-index:-1) — it paints
   over the opaque `body { background:var(--bg) }` but under the page's own
   content, so it reads as faint colour in the margins/gaps without touching
   legibility. Dark and light get SEPARATE tunings: richer, jewel-toned washes
   on the dark canvas; airier, lighter tints on the white canvas. Colours are
   fixed accents blended into transparent via color-mix, so only the alpha
   differs between themes. Non-animated, so no reduced-motion concern. */
html body::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(680px 440px at 10% -8%, color-mix(in srgb, #416aec 20%, transparent), transparent 68%),
    radial-gradient(620px 440px at 94% 2%, color-mix(in srgb, #8b5cf6 16%, transparent), transparent 70%),
    radial-gradient(760px 520px at 50% 112%, color-mix(in srgb, #0ea5e9 14%, transparent), transparent 70%);
}
html[data-theme="light"] body::before {
  background:
    radial-gradient(680px 440px at 10% -8%, color-mix(in srgb, #416aec 9%, transparent), transparent 68%),
    radial-gradient(620px 440px at 94% 2%, color-mix(in srgb, #8b5cf6 8%, transparent), transparent 70%),
    radial-gradient(760px 520px at 50% 112%, color-mix(in srgb, #0ea5e9 7%, transparent), transparent 70%);
}

/* ---- Vector polish: airier cards + a little more headline hierarchy ---------
   Bitcoin Vector breathes more than this data-dense dashboard. These nudge (not
   restructure) toward its feel; `html body …` out-specifies each page's own
   element rules so no (i18n-heavy) template edits are needed. Both themes. */
html body .grid { gap: 18px; }
html body .panel { border-radius: 14px; padding: 16px 18px; }
html body .actcol, html body .mtf-card, html body .card { border-radius: 12px; }
html body h1 { font-size: 24px; }
html body .badge { font-size: 14px; padding: 4px 13px; }
html body .prob .pc { font-size: 18px; font-weight: 700; }

/* buttons — shared polish mirroring the landing's interactive feel: smooth
   transitions, a subtle lift + accent glow on hover, a pressed state, and a
   crisp keyboard focus ring. The accent is always --link (per theme); the
   red/green up-down semantics are never touched. */
.navbtn, .theme-btn { transition: transform .16s ease, border-color .16s ease,
  color .16s ease, background .16s ease, box-shadow .18s ease; cursor: pointer; }
.navbtn { background: var(--panel2); border: 1px solid var(--line); color: var(--link);
  padding: 5px 14px; border-radius: 8px; font-size: 13px; }
.navbtn:hover { border-color: var(--link); transform: translateY(-1px);
  box-shadow: 0 5px 15px -5px color-mix(in srgb, var(--link) 50%, transparent); }
.navbtn:active { transform: translateY(0); box-shadow: none; }
.theme-btn { background: var(--panel2); border: 1px solid var(--line);
  color: var(--muted); padding: 5px 11px; border-radius: 8px; font-size: 13px;
  line-height: 1; }
.theme-btn:hover { color: var(--text); border-color: var(--link); transform: translateY(-1px);
  box-shadow: 0 5px 15px -5px color-mix(in srgb, var(--link) 42%, transparent); }
.theme-btn:active { transform: translateY(0); box-shadow: none; }

/* common page-local pill / action buttons — layer the same hover feel site-wide
   (additive: only transition + a hover accent border + soft glow), so each keeps
   its own base colours and its .on/.active fills. html-body specificity wins over
   a bare `.fbtn:hover` but loses to a two-class `.fbtn.on:hover`, so active
   states are left intact. */
html body :is(.tm-btn, .vtm-btn, .lang-btn, .wl-btn, .fbtn, .aff) {
  transition: transform .16s ease, border-color .16s ease, color .16s ease,
              background .16s ease, box-shadow .18s ease; }
html body :is(.tm-btn, .vtm-btn, .lang-btn, .wl-btn, .fbtn, .aff):hover {
  border-color: color-mix(in srgb, var(--link) 58%, var(--line));
  box-shadow: 0 4px 13px -5px color-mix(in srgb, var(--link) 40%, transparent); }
/* tabs / segmented controls — accent glow on hover, no lift (tabs shouldn't move) */
html body :is(.tabbtn, .segbtn, .brief-tab-btn) {
  transition: color .16s ease, border-color .16s ease, background .16s ease, box-shadow .18s ease; }
html body :is(.tabbtn, .segbtn, .brief-tab-btn):hover {
  box-shadow: 0 3px 10px -4px color-mix(in srgb, var(--link) 34%, transparent); }

/* clickable card / tile containers — the landing's hover light-up, shared: a
   gentle lift, an accent border and a soft accent glow. Additive (hover only),
   so each card keeps its own base layout. */
html body :is(a.actitem, a.idx-alloc, .nbcard, a.scard) {
  transition: transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease, box-shadow .2s ease; }
html body :is(a.actitem, a.idx-alloc, .nbcard, a.scard):hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--link) 45%, var(--line));
  box-shadow: 0 14px 30px -16px color-mix(in srgb, var(--link) 40%, transparent); }

/* keyboard focus ring on interactive surfaces — accessible, and low-specificity
   (:where) so it never fights component styles; only shows for keyboard nav. */
:where(.navbtn, .theme-btn, .tm-btn, .vtm-btn, .lang-btn, .wl-btn, .fbtn, .tabbtn,
  .segbtn, .brief-tab-btn, .aff, .af-toggle, .sm-btn, .theme-switch, .lang-toggle,
  .ai-brief-link, .nav-link, .nav-dd-menu a, a.actitem, a.idx-alloc, .nbcard,
  a.scard):focus-visible {
  outline: 2px solid color-mix(in srgb, var(--link) 70%, transparent); outline-offset: 2px; }

/* ---- tinted semantic badges -------------------------------------------------
   Any element with one of these classes is tinted from its --c base color. */
.st-FRESH_BUY, .st-TURN_SIGNALED, .st-RALLY_ON, .st-BOTTOM_WATCH, .st-TOP_WATCH,
.st-ROLLING_OVER, .st-DECLINE, .st-COUNTERTREND_BOUNCE,
.state-STABLE, .state-WEAKENING, .state-TRANSITIONING, .state-NEW_REGIME,
.pill-ok, .pill-stale, .pill-failed, .pill-dead, .pill-blocked,
.tag-lead, .tag-avoid, .tag-watch, .chip-pos, .chip-neg,
.sig-p, .sig-m, .sig-i, .urgpill, .lad-tint {
  background: color-mix(in srgb, var(--c, var(--muted)) 12%, var(--panel));
  color: color-mix(in srgb, var(--c, var(--muted)) 86%, var(--text));
  border-color: color-mix(in srgb, var(--c, var(--muted)) 34%, transparent);
  font-variant-numeric: tabular-nums; letter-spacing: .01em;
}
/* base-color assignments */
.st-FRESH_BUY, .st-RALLY_ON, .pill-ok, .tag-lead, .chip-pos, .sig-p,
.urgpill.urg-now { --c: var(--up); }
.st-TURN_SIGNALED, .st-BOTTOM_WATCH, .tag-watch, .sig-i,
.urgpill.urg-imminent, .urgpill.urg-soon, .state-NEW_REGIME { --c: var(--info); }
.st-TOP_WATCH, .pill-stale, .urgpill.urg-caution, .state-WEAKENING { --c: var(--warn); }
.st-ROLLING_OVER, .st-COUNTERTREND_BOUNCE, .state-TRANSITIONING { --c: var(--orange); }
.st-DECLINE, .pill-failed, .pill-dead, .tag-avoid, .chip-neg, .sig-m,
.urgpill.urg-exit, .urgpill.urg-avoid { --c: var(--down); }
.pill-blocked, .state-STABLE, .urgpill.urg-hold, .urgpill.urg-later { --c: var(--muted); }

.pos { color: var(--up); } .neg { color: var(--down); }

/* advancing/declining mini-bar (market-breadth scorecard) */
.bbar { display:inline-flex; width:90px; height:7px; margin-left:8px; vertical-align:middle;
  border:1px solid var(--line); border-radius:4px; overflow:hidden; background:var(--panel2); }
.bbar i { display:block; height:100%; }

/* market snapshot tiles + VIX monitor (macro at-a-glance surfacing) */
.mtiles { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
@media (max-width:760px){ .mtiles { grid-template-columns:repeat(2,1fr); } }
.mtile { background:var(--panel2); border:1px solid var(--line); border-radius:9px; padding:10px 12px; }
.mtile-top { display:flex; justify-content:space-between; align-items:baseline; gap:6px; }
.mtile-lbl { font-size:12px; color:var(--muted); }
.mtile-tag { font-size:9px; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); opacity:.65; white-space:nowrap; }
.mtile-val { font-size:20px; font-weight:700; margin:3px 0 1px; }
.mtile-chg { font-size:12px; }
.vixhead { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
.vixnum { font-size:30px; font-weight:700; line-height:1; }
.vixstats { display:flex; gap:16px; flex-wrap:wrap; margin-top:8px; }
.badge.vix-muted { --c: var(--muted); } .badge.vix-warn { --c: var(--warn); } .badge.vix-neg { --c: var(--down); }

/* rotation-stage pills (heat board) — tinted like the badges */
.stg-improving, .stg-leading, .stg-weakening, .stg-lagging {
  background: color-mix(in srgb, var(--c) 15%, var(--panel));
  color: color-mix(in srgb, var(--c) 80%, var(--text));
}
.stg-improving { --c: var(--info); } .stg-leading { --c: var(--up); }
.stg-weakening { --c: var(--warn); } .stg-lagging { --c: var(--down); }

/* charts render on their own dark slate (set in build_site PLOT_LAYOUT); the
   wrapper just rounds the corners so they sit cleanly in either theme */
.chart, .tv { border-radius: 8px; overflow: hidden; }

/* multi-timeframe visual cards */
.mtf-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin-top: 8px; }
@media (max-width: 620px) { .mtf-grid { grid-template-columns: 1fr; } }
.mtf-card { background: var(--panel2); border: 1px solid var(--line);
  border-radius: 10px; padding: 9px 12px; }
.mtf-h { font-size: 11px; font-weight: 700; letter-spacing: .08em;
  color: var(--muted); margin-bottom: 5px; }
.mtf-row { display: grid; grid-template-columns: 38px 1fr auto; align-items: center;
  gap: 7px; margin: 3px 0; }
.mtf-k { font-size: 11px; color: var(--muted); font-weight: 600; }
.mtf-v { font-size: 13px; font-weight: 700; text-align: right; display: flex;
  flex-direction: column; align-items: flex-end; line-height: 1.1; }
.mtf-v small { font-size: 9.5px; font-weight: 400; color: var(--muted); }

/* ---- site footer (shared signature, themed via vars) ---- */
.site-footer {
  max-width: 1500px;
  margin: 44px auto 16px;
  padding: 22px 16px 4px;
  border-top: 1px solid var(--line);
  text-align: center;
  line-height: 1.6;
  font-family: var(--font-ui);
}
.site-footer .made {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: .2px;
}
.site-footer .dev {
  display: block;
  margin-top: 1px;
  font-size: 12px;
  color: var(--muted);
}

/* ===================== unified macro nav =====================
   One bar across the macro dashboard family: section links · global stock
   search · animated theme + language toggles. The toggles are driven PURELY
   by the html[data-theme] / html[data-lang] attributes (theme.js just flips
   those), so no JS rewrites their markup. The legacy .theme-btn / .lang-btn
   remain for pages we are NOT restyling (Bitcoin Vector, hub, China). */
/* 2-column grid so the controls (theme + language toggles) sit in a fixed
   right-hand column that NEVER moves — the links wrap inside the left column and
   the search drops to a full-width row below, so switching language (which
   changes link-text widths) can't shift the toggles around. */
/* max-width + auto margins pin the bar to ONE consistent width on every page
   (matching .site-footer and the vector family's 1500px nav) — full-width macro
   dashboards and 1180px reading pages no longer make the menu jump width as you
   navigate between them. Below 1500px the cap is inert, so laptops see no change. */
.site-nav { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; column-gap: 12px; row-gap: 9px; margin: 0 auto 16px;
  max-width: 1500px; }
/* the menu owns the full first row on its own (one clean line); the search +
   the Mastermind/Terminal/⚙ cluster share the second row. Keeping the links off
   the controls' column is what holds the bar to TWO rows — 7 dropdowns + brand
   no longer get squeezed into wrapping a third row beside the pills. */
.site-nav .nav-links { grid-column: 1 / -1; grid-row: 1; display: flex; flex-wrap: wrap;
  align-items: center; gap: 3px; min-width: 0; }
/* ── Brand lockup — the crafted Mastermind “M” logomark + MASTERMIND wordmark, the
   first item in the shared _navlinks list, pinned at the head of the menu bar and
   linking Home. The wordmark collapses on phones (≤560px); the full “Market
   Intelligence” lockup also lives on the landing hero. */
.site-nav .nav-brand { display: inline-flex; align-items: center; gap: 8px; flex: none;
  padding: 3px 10px 3px 4px; margin: 0 6px 0 0; border-radius: 11px; text-decoration: none;
  transition: background .18s, transform .16s ease; }
.site-nav .nav-brand:hover { background: color-mix(in srgb, var(--link) 11%, transparent);
  transform: translateY(-1px); }
.site-nav .nav-brand .brand-glyph { width: 29px; height: 29px; display: block; flex: none;
  filter: drop-shadow(0 2px 6px rgba(40,56,128,.34)); }
/* weight 900 (Inter Black — loaded via the @font-face rules at the top) + tight tracking so the
   wordmark reads as heavy as the logo glyph; line-height:1 so the all-caps ink centres
   on the glyph (the inherited 1.5 line-height left the caps sitting visibly high). */
.site-nav .nav-brand .brand-word { font-family: var(--font-ui);
  font-size: 13.5px; font-weight: 900; letter-spacing: .07em; line-height: 1;
  color: var(--text); white-space: nowrap; }
.site-nav a.nav-link { padding: 7px 11px; border-radius: 9px; font-size: 13.5px;
  font-weight: 500; color: var(--muted); text-decoration: none; white-space: nowrap;
  transition: color .18s, background .18s; }
.site-nav a.nav-link:hover, .site-nav a.nav-link.active { color: var(--text);
  background: color-mix(in srgb, var(--link) 12%, var(--panel2)); }
/* nav dropdown (e.g. US Macro ▾ → dashboard + S&P / Macro Vector); mirrors the
   inline Bitcoin-Vector dropdown some pages already ship, themed via theme vars */
.site-nav .nav-dd { position: relative; display: inline-flex; }
.site-nav .nav-dd > a.nav-link .caret { display: inline-block; margin-left: 3px;
  font-size: 9px; opacity: .6; transition: transform .2s; }
.site-nav .nav-dd:hover > a.nav-link .caret { transform: rotate(180deg); }
.site-nav .nav-dd::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 9px; }
.site-nav .nav-dd-menu { position: absolute; top: calc(100% + 7px); left: 0; z-index: 90;
  min-width: 218px; background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-brd); border-radius: 14px;
  box-shadow: var(--glass-shadow); padding: 6px; opacity: 0; visibility: hidden;
  transform: translateY(-6px); transition: opacity .18s, transform .18s, visibility .18s; }
.site-nav .nav-dd:hover > .nav-dd-menu, .site-nav .nav-dd:focus-within > .nav-dd-menu {
  opacity: 1; visibility: visible; transform: translateY(0); }
.site-nav .nav-dd-menu a { display: block; padding: 9px 12px; border-radius: 9px; font-size: 13.5px;
  font-weight: 600; color: var(--muted); text-decoration: none; white-space: nowrap;
  transition: color .18s, background .18s; }
.site-nav .nav-dd-menu a:hover { color: var(--text);
  background: color-mix(in srgb, var(--link) 12%, var(--panel2)); }

/* US Macro submenu — CSS-only dropdown (hover + focus-within for keyboard), shared
   across every .site-nav page. Houses the factor/index lab (factors, baskets,
   seasonality) under the US Macro entry without crowding the flat bar. */
.nav-dd { position: relative; display: inline-flex; }
.nav-dd > a.nav-link .caret { display: inline-block; margin-left: 3px; font-size: 9px; opacity: .6;
  transition: transform .2s; }
.nav-dd:hover > a.nav-link .caret, .nav-dd:focus-within > a.nav-link .caret { transform: rotate(180deg); }
.nav-dd::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 9px; } /* hover gap bridge */
.nav-dd-menu { position: absolute; top: calc(100% + 7px); left: 0; min-width: 232px; background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-brd); border-radius: 14px; box-shadow: var(--glass-shadow); padding: 6px;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s; z-index: 70; }
.nav-dd:hover > .nav-dd-menu, .nav-dd:focus-within > .nav-dd-menu { opacity: 1; visibility: visible;
  transform: translateY(0); }
.nav-dd-menu a { display: block; padding: 8px 11px; border-radius: 9px; font-size: 13px; font-weight: 500;
  color: var(--text); text-decoration: none; white-space: nowrap; transition: background .15s, color .15s; }
.nav-dd-menu a .d { display: block; font-size: 11px; font-weight: 400; color: var(--muted); margin-top: 1px; }
.nav-dd-menu a:hover, .nav-dd-menu a.active { background: color-mix(in srgb, var(--link) 12%, var(--panel2)); }
/* 3rd tier: a .nav-dd nested inside a .nav-dd-menu (Other Assets ▸ Bitcoin
   Vector / Commodities). On desktop the child menu flies out to the right of
   its row; ::after bridges the gap so the cursor can cross into it. */
.nav-dd-menu .nav-sub { display: block; position: relative; }
/* flex-start (not center): the trigger is a two-line row (title + .d description),
   so the leading emoji must sit on the first line exactly like the leaf links;
   only the ▸ caret stays vertically centered via align-self. */
.nav-dd-menu .nav-sub > a.nav-sub-trig { display: flex; align-items: flex-start; gap: .3em; }
.nav-dd-menu .nav-sub > a.nav-sub-trig .caret-r { margin-left: auto; padding-left: 12px; font-size: 10px;
  opacity: .55; flex: none; align-self: center; transition: transform .2s; }
.nav-dd-menu .nav-sub:hover > a.nav-sub-trig .caret-r { opacity: .9; transform: translateX(2px); }
/* nav-sub-text: title+description column inside the flex .nav-sub-trig row —
   makes fly-out triggers visually identical to leaf links while the flex
   layout keeps the ▸ caret right-aligned. */
.nav-dd-menu .nav-sub > a.nav-sub-trig .nav-sub-text { display: block; flex: 1; min-width: 0; white-space: normal; }
.nav-dd-menu .nav-sub > .nav-dd-menu { top: -7px; left: 100%; z-index: 95;
  /* The 2nd-tier .nav-dd-menu already has backdrop-filter, making it a backdrop
     root — so this nested fly-out's own backdrop-filter can't reach & blur the
     page behind it, and the translucent --glass-bg alone reads as see-through.
     Give it a denser near-opaque fill so it matches the 2nd tier's frosted density. */
  background: color-mix(in srgb, var(--panel) 96%, transparent); }
.nav-dd-menu .nav-sub::after { content: ""; position: absolute; top: 0; left: 100%; width: 12px; height: 100%; }
@media (max-width: 560px) {   /* no hover on touch — render the submenu inline-expanded */
  .nav-dd { display: block; }
  .nav-dd > a.nav-link .caret { display: none; }
  .nav-dd-menu { position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; padding: 1px 0 4px 16px; min-width: 0; }
  .nav-dd-menu a { padding: 5px 8px; font-size: 12.5px; }
  .nav-dd-menu a .d { display: none; }
}
/* Pre-JS / no-JS overflow guard for the .site-nav family. theme.js loads at the
   END of <body> and only then adds .has-nav-toggle, whose 0,3,0-specificity rules
   collapse the dropdowns into the hamburger. Until it runs, the FIRST paint shows
   the un-collapsed bar — and the closed .nav-dd-menu panels are still
   position:absolute; min-width:218px, so on a phone they stick out past the
   viewport and force documentElement.scrollWidth wider than the screen, clipping
   page content (a horizontal-overflow flash on every load; also the permanent
   state if JS fails). The generic ≤560 collapse above can't neutralise this
   because `.site-nav .nav-dd-menu{position:absolute}` (0,2,0) out-specificities its
   bare `.nav-dd-menu` (0,1,0). Mirror the hamburger's closed state at the same
   ≤1259px range: fold the dropdowns in-flow (stacked, zero-height) so nothing
   overflows. Once theme.js runs its has-nav-toggle rules (0,3,0) win and this goes
   inert; desktop (>1259px) is untouched, so hover fly-outs are unaffected. */
@media (max-width: 1259px) {
  .site-nav .nav-dd { display: block; }
  .site-nav .nav-dd-menu { position: static; min-width: 0; max-height: 0;
    overflow: hidden; transform: none; box-shadow: none; border: 0; background: transparent; }
}

/* global stock search */
.nav-search { grid-column: 1; grid-row: 2; position: relative; min-width: 0; max-width: 480px; }
.nav-search .mag { position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  font-size: 12px; opacity: .65; pointer-events: none; }
.nav-search input { width: 100%; box-sizing: border-box; padding: 8px 12px 8px 32px;
  border-radius: 10px; border: 1px solid var(--line); background: var(--panel2);
  color: var(--text); font: inherit; font-size: 13px; outline: none;
  transition: border-color .18s, box-shadow .25s ease;
  /* idle: a calm #416aec glow that breathes in and out, drawing the eye to the
     search. Stops dead on focus (see :focus) so typing feels solid and steady. */
  animation: searchBreathe 3.8s ease-in-out infinite; }
@keyframes searchBreathe {
  0%, 100% { border-color: color-mix(in srgb, #416aec 30%, var(--line));
    box-shadow: 0 0 0 0 rgba(65,106,236,0), 0 0 5px 0 rgba(65,106,236,.10); }
  50% { border-color: #416aec;
    box-shadow: 0 0 0 3px rgba(65,106,236,.22), 0 0 16px 2px rgba(65,106,236,.38); } }
.nav-search input::placeholder { color: var(--muted); }
.nav-search input:focus { border-color: var(--link); animation: none; box-shadow: none; }
.nav-sugg { position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 80;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-brd); border-radius: 13px; overflow: hidden;
  overflow-y: auto; max-height: 60vh; box-shadow: var(--glass-shadow); display: none; }
.nav-sugg.show { display: block; }
.nav-sugg .row { display: flex; align-items: center; gap: 9px; padding: 8px 12px; cursor: pointer; }
.nav-sugg .row:hover, .nav-sugg .row.sel { background: color-mix(in srgb, var(--link) 12%, var(--panel2)); }
/* leading market flag (US / China / HK / Canada / Intl) on the unified universe search */
.nav-sugg .row .mkt { flex: none; width: 20px; text-align: center; font-size: 13px; line-height: 1; }
.nav-sugg .row b { min-width: 58px; font-size: 13px; color: var(--text); font-weight: 600; }
.nav-sugg .row small { flex: 1; color: var(--muted); font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.nav-sugg .row .stt { font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 6px;
  white-space: nowrap; }
.nav-sugg .empty { padding: 11px 13px; color: var(--muted); font-size: 12.5px; }

/* ---- responsive data tables ------------------------------------------------
   Wide data tables (screeners, scoreboards, flow tables) are wrapped by theme.js
   in this container so they scroll horizontally WITHIN their card on narrow screens
   instead of bleeding past the viewport. width:100% tables keep filling the card on
   desktop (content fits, no scroll); only genuine overflow scrolls. The thin styled
   scrollbar hints the table is scrollable. */
.tbl-scroll { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain; }
.tbl-scroll::-webkit-scrollbar { height: 6px; }
.tbl-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; }

/* ---- live table filter (injected by tablesort.js into long data tables) -----
   The little searchbar that auto-appears above any scorecard / data table with
   ≥12 rows (Data health, screeners, …). Built as <div.tbl-filter><input
   type=search><span.cnt>. Mirrors .nav-search so it feels native to the page
   rather than a naked browser input. */
.tbl-filter { display: flex; align-items: center; gap: 10px; margin: 2px 0 12px;
  flex-wrap: wrap; }
.tbl-filter input[type="search"] {
  appearance: none; -webkit-appearance: none; /* search fields ignore border/radius otherwise */
  flex: 0 1 280px; min-width: 0; box-sizing: border-box;
  padding: 7px 12px 7px 32px; border-radius: 10px;
  border: 1px solid var(--line); color: var(--text); font: inherit; font-size: 13px;
  outline: none; transition: border-color .18s, box-shadow .25s ease;
  background: var(--panel2)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238b94a8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E")
    no-repeat 10px 50%;
  background-size: 14px; }
.tbl-filter input[type="search"]::placeholder { color: var(--muted); }
.tbl-filter input[type="search"]:hover { border-color: color-mix(in srgb, var(--link) 45%, var(--line)); }
.tbl-filter input[type="search"]:focus { border-color: var(--link);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--link) 20%, transparent); }
.tbl-filter .cnt { font-size: 12px; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }

.site-nav .nav-ctrls { grid-column: 2; grid-row: 2; justify-self: end; align-self: center;
  display: flex; align-items: center; gap: 10px; }

/* static AI Daily Brief entry — pinned in the nav-ctrls cluster beside the theme +
   language toggles, so it never scrolls with the main menu. Styled as a refined
   pill: a soft top-lit gradient, a hairline border and a faint resting shadow give
   it depth so it reads as a real button rather than a flat chip. */
.nav-ctrls .ai-brief-link { display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap; flex: none; padding: 6px 13px; border-radius: 999px;
  background: linear-gradient(180deg, var(--panel), var(--panel2));
  border: 1px solid var(--line); color: var(--text);
  font-size: 12.5px; font-weight: 600; letter-spacing: .1px; line-height: 1; cursor: pointer;
  box-shadow: 0 1px 2px rgba(16,24,40,.05), inset 0 1px 0 rgba(255,255,255,.05);
  transition: background .2s, border-color .2s, color .2s, transform .16s ease, box-shadow .18s ease; }
/* Shared hover for BOTH pills (Mastermind + Terminal): fill with the link accent +
   white text, lift and glow. Mastermind used to only outline its border on hover;
   it now uses the Terminal pill's nicer fill animation so the two feel identical. */
.nav-ctrls .ai-brief-link:hover { background: var(--link); border-color: var(--link); color: #fff;
  transform: translateY(-1px); box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--link) 50%, transparent); }
.nav-ctrls .ai-brief-link:active { transform: translateY(0); box-shadow: none; }
.nav-ctrls .ai-brief-link.active { background: var(--link); border-color: var(--link); color: #fff; }
/* Terminal entry — the live Mastermind Terminal (app.mastermind-x.com), pinned
   beside the Mastermind button. Link-accented border/text + a faint link-tinted
   fill AT REST mark it as the one outbound door to the live app; the brighter
   fill-on-hover is the shared rule above. */
.nav-ctrls .ai-brief-link.terminal-link {
  border-color: color-mix(in srgb, var(--link) 55%, var(--line)); color: var(--link);
  background: linear-gradient(180deg, color-mix(in srgb, var(--link) 12%, var(--panel)), color-mix(in srgb, var(--link) 7%, var(--panel2))); }
/* Terminal's at-rest border/background tie the shared :hover rule on specificity, so
   spell its hover out in full (higher specificity) to guarantee the solid link fill +
   white text win over the resting tint. */
.nav-ctrls .ai-brief-link.terminal-link:hover { background: var(--link); border-color: var(--link); color: #fff; }

/* AI Daily Brief entry card — the single in-page doorway to the cross-asset LLM
   synthesis page (aibrief.html). Replaces the old inline AI Master Brief panel on the
   macro / China / Hong Kong / Bitcoin dashboards. Rendered as a clickable .panel/.card. */
.aibrief-card { display: flex; align-items: center; gap: 14px; text-decoration: none;
  color: inherit; border-left: 3px solid var(--link); cursor: pointer;
  transition: border-color .15s, transform .16s ease, box-shadow .18s ease; }
.aibrief-card:hover { transform: translateY(-1px);
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--link) 42%, transparent); }
.aibrief-card .abc-ic { font-size: 30px; line-height: 1; flex: none; }
.aibrief-card .abc-mid { flex: 1; min-width: 0; }
.aibrief-card .abc-tit { display: block; font-size: 16px; font-weight: 700; }
.aibrief-card .abc-sub { display: block; margin-top: 2px; }
.aibrief-card .abc-go { font-size: 22px; font-weight: 700; color: var(--link); flex: none; }

/* animated dark / light switch — slides on html[data-theme] */
.theme-switch { width: 56px; height: 27px; border-radius: 999px; background: var(--panel2);
  border: 1px solid var(--line); position: relative; cursor: pointer; padding: 0; flex: none;
  transition: border-color .18s ease, box-shadow .18s ease; }
.theme-switch:hover, .lang-toggle:hover { border-color: color-mix(in srgb, var(--link) 55%, var(--line));
  box-shadow: 0 3px 11px -5px color-mix(in srgb, var(--link) 40%, transparent); }
.theme-switch .ic { position: absolute; top: 50%; transform: translateY(-50%); font-size: 10.5px;
  opacity: .5; line-height: 1; }
/* Place each static icon UNDER where the knob rests for its mode: the knob sits
   left in dark (shows 🌙) and slides right in light (shows ☀️). So the moon goes
   left and the sun goes right — the knob then covers the icon it duplicates,
   leaving the OTHER icon visible. (Previously both were on the wrong side, so the
   knob's ☀️ + the static ☀️ showed two suns in light mode.) */
.theme-switch .ic.sun { right: 8px; } .theme-switch .ic.moon { left: 8px; }
.theme-switch .knob { position: absolute; top: 2px; left: 2px; width: 22px; height: 22px;
  border-radius: 50%; background: #e8c15a; display: flex; align-items: center; justify-content: center;
  font-size: 11px; box-shadow: 0 2px 5px rgba(0,0,0,.3);
  transition: transform .34s cubic-bezier(.34, 1.45, .5, 1), background .3s; }
.theme-switch .knob::before { content: "🌙"; }
html[data-theme="light"] .theme-switch .knob { transform: translateX(29px); background: #285fff; }
html[data-theme="light"] .theme-switch .knob::before { content: "☀️"; }

/* animated EN / 中文 segmented toggle — slides on html[data-lang] */
.lang-toggle { display: inline-flex; position: relative; background: var(--panel2);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px; flex: none; cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease; }
.lang-toggle .pill { position: absolute; top: 3px; left: 3px; width: calc(50% - 3px);
  height: calc(100% - 6px); border-radius: 999px; background: var(--link);
  transition: transform .34s cubic-bezier(.34, 1.4, .5, 1); }
html[data-lang="zh"] .lang-toggle .pill { transform: translateX(100%); }
.lang-toggle .opt { position: relative; z-index: 1; min-width: 28px; text-align: center;
  padding: 3px 9px; font-size: 11.5px; font-weight: 600; color: var(--muted); transition: color .25s;
  user-select: none; }
html:not([data-lang="zh"]) .lang-toggle .en-opt { color: #fff; }
html[data-lang="zh"] .lang-toggle .zh-opt { color: #fff; }

/* ===================== readability restructure components =====================
   Shared by the stock analyzer and the sector-ETF pages: a bold VERDICT hero and
   an at-a-glance SIGNAL-CHIP strip so the call + the technical picture read in a
   few seconds. Colours resolve from the theme vars at paint time, so light/dark
   and the zh red/green swap both apply automatically. */
.verdict { display: flex; align-items: center; gap: 14px 16px; flex-wrap: wrap;
  padding: 14px 18px; border-radius: 14px; background: var(--panel2);
  border: 1px solid var(--line); border-left: 6px solid var(--c, var(--muted));
  margin: 12px 0 14px; }
.verdict .v-act { font-size: 23px; font-weight: 800; line-height: 1.05;
  letter-spacing: .005em; color: var(--c, var(--text)); white-space: nowrap; }
.verdict .v-tag { font-size: 12px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; padding: 4px 11px; border-radius: 8px; white-space: nowrap;
  background: color-mix(in srgb, var(--c, var(--muted)) 18%, var(--panel));
  color: color-mix(in srgb, var(--c, var(--muted)) 85%, var(--text));
  border: 1px solid color-mix(in srgb, var(--c, var(--muted)) 35%, transparent); }
.verdict .v-text { flex: 1; min-width: 220px; font-size: 14.5px; line-height: 1.45;
  color: var(--text); }
.verdict .v-text b { color: var(--c, var(--text)); }
/* urgency → accent colour (mirrors the entrybar mapping, one source here) */
.verdict.urg-now    { --c: var(--up); }
.verdict.urg-imminent, .verdict.urg-soon { --c: var(--g-cold); }
.verdict.urg-caution { --c: var(--warn); }
.verdict.urg-exit, .verdict.urg-avoid { --c: var(--down); }
.verdict.urg-hold, .verdict.urg-later { --c: var(--muted); }

.sigstrip { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 6px; }
.sigchip { display: flex; flex-direction: column; gap: 1px; padding: 8px 13px;
  border-radius: 11px; background: var(--panel2); border: 1px solid var(--line);
  min-width: 104px; }
.sigchip .sc-k { font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); font-weight: 700; }
.sigchip .sc-v { font-size: 15px; font-weight: 800; line-height: 1.15; color: var(--text); }
.sigchip .sc-s { font-size: 10.5px; font-weight: 500; color: var(--muted); }
.sigchip.up   { border-color: color-mix(in srgb, var(--up) 42%, transparent);
  background: color-mix(in srgb, var(--up) 9%, var(--panel)); }
.sigchip.up   .sc-v { color: var(--up); }
.sigchip.down { border-color: color-mix(in srgb, var(--down) 42%, transparent);
  background: color-mix(in srgb, var(--down) 9%, var(--panel)); }
.sigchip.down .sc-v { color: var(--down); }
.sigchip.warn { border-color: color-mix(in srgb, var(--warn) 42%, transparent);
  background: color-mix(in srgb, var(--warn) 10%, var(--panel)); }
.sigchip.warn .sc-v { color: var(--warn); }

/* ===================== alert feed (.af-*) =====================
   Cloned from the Bitcoin Vector alert timeline (.tl-*), re-themed to the shared
   vars and shared by the stock + sector pages. The node colour encodes DIRECTION
   (var(--up)/--down, so it swaps in zh mode); severity only drives sort order. */
.af-toggle { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  background: var(--panel2); border: 1px solid var(--line); color: var(--text);
  padding: 6px 13px; border-radius: 10px; font-size: 13px; font-weight: 700; line-height: 1;
  transition: transform .16s ease, border-color .16s ease, color .16s ease,
              background .16s ease, box-shadow .18s ease; }
.af-toggle:hover { border-color: var(--link); transform: translateY(-1px);
  box-shadow: 0 5px 14px -5px color-mix(in srgb, var(--link) 42%, transparent); }
.af-toggle:active { transform: translateY(0); box-shadow: none; }
.af-toggle[aria-expanded="true"] { border-color: var(--link); color: var(--link);
  background: color-mix(in srgb, var(--link) 10%, var(--panel2)); }
.af-toggle .af-badge { background: var(--act); color: #fff; font-size: 11px; font-weight: 800;
  min-width: 18px; text-align: center; padding: 1px 6px; border-radius: 9px; }
.af-toggle .af-caret { font-size: 10px; opacity: .6; transition: transform .2s; }
.af-toggle[aria-expanded="true"] .af-caret { transform: rotate(180deg); }

/* --- floating alert popover -------------------------------------------------
   The feed no longer expands in place (which shoved the page down and read as
   "the content vanished"). It now floats out of the 🔔 toggle as an anchored
   popover that OVERLAYS the page — the underlying content never moves, so the
   user keeps their place. A soft scrim dims (not hides) the page behind it and
   gives a click-away target. Shared by the stock + sector pages. */
.af-wrap { position: relative; display: inline-flex; }
.af-scrim { position: fixed; inset: 0; z-index: 90; background: transparent;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .22s ease, visibility 0s linear .22s; }
.af-scrim.af-open { opacity: 1; visibility: visible; pointer-events: auto;
  background: color-mix(in srgb, var(--bg) 30%, transparent);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  transition: opacity .22s ease; }

/* JS pins top/left/transform-origin on open so the panel grows straight out of
   the bell and is always clamped on-screen (the toggle can wrap anywhere in the
   header); top/right here are just the no-JS fallback. */
.af { position: fixed; top: 64px; right: 14px; z-index: 100;
  width: min(470px, calc(100vw - 24px));
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-brd); border-radius: 16px;
  box-shadow: var(--glass-shadow);
  transform-origin: top right; transform: translateY(-7px) scale(.95); opacity: 0;
  visibility: hidden; pointer-events: none;
  transition: opacity .19s ease, transform .24s cubic-bezier(.18,.9,.32,1.12),
              visibility 0s linear .24s; }
.af.af-open { opacity: 1; transform: translateY(0) scale(1);
  visibility: visible; pointer-events: auto;
  transition: opacity .19s ease, transform .24s cubic-bezier(.18,.9,.32,1.12); }
.af-bar { display: flex; align-items: center; gap: 9px; padding: 12px 15px 11px;
  border-bottom: 1px solid var(--line); }
.af-bar-t { font-size: 13.5px; font-weight: 800; color: var(--text);
  flex: 1; min-width: 0; }
.af-x { display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--panel2); color: var(--muted); font-size: 13px; cursor: pointer;
  line-height: 1; transition: color .15s, border-color .15s, background .15s; }
.af-x:hover { color: var(--text); border-color: var(--link); }
.af-body { padding: 13px 15px 15px; max-height: min(62vh, 540px); overflow-y: auto;
  overscroll-behavior: contain; border-radius: 0 0 14px 14px; }
.af-body > :last-child { margin-bottom: 0; }

@media (max-width: 560px) {
  /* phone: rise from the bottom as a sheet instead of a corner dropdown */
  .af { position: fixed; left: 50%; right: auto; top: auto; bottom: env(safe-area-inset-bottom, 0);
    width: 100%; max-width: 540px; border-radius: 16px 16px 0 0;
    transform-origin: bottom center; transform: translate(-50%, 16px) scale(1); }
  .af.af-open { transform: translate(-50%, 0) scale(1); }
  .af-body { max-height: 68vh; border-radius: 0; }
  .af-scrim.af-open { background: color-mix(in srgb, var(--bg) 52%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .af { transition: opacity .15s ease, visibility 0s linear .15s; transform: none; }
  .af.af-open { transform: none; transition: opacity .15s ease; }
  .nav-search input { animation: none; }
  /* hover lifts collapse to a static accent (keep colour/shadow, drop the move) */
  .navbtn:hover, .theme-btn:hover, .af-toggle:hover, .nav-ctrls .ai-brief-link:hover,
  html body :is(a.actitem, a.idx-alloc, .nbcard, a.scard):hover { transform: none; }
}

/* pinned standing read — the ladder's current call, top of the feed */
.af-pin { border: 1px solid color-mix(in srgb, var(--c, var(--info)) 32%, var(--line));
  background: color-mix(in srgb, var(--c, var(--info)) 8%, var(--panel));
  border-left: 4px solid var(--c, var(--info)); border-radius: 12px;
  padding: 11px 14px; margin-bottom: 14px; }
.af-pin.dir-up { --c: var(--up); } .af-pin.dir-down { --c: var(--down); }
.af-pin.dir-neutral { --c: var(--muted); }
.af-pin .af-pin-h { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.af-pin .af-pin-tag { font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--c, var(--info)); }
.af-pin .af-pin-title { font-size: 15.5px; font-weight: 800; color: var(--text); }
.af-pin .af-pin-d { margin: 5px 0 0; font-size: 13px; color: var(--muted); line-height: 1.55; }

.af-filters { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 14px; }
.aff { padding: 5px 13px; border-radius: 9px; background: var(--panel2); color: var(--muted);
  font-weight: 700; font-size: 12.5px; cursor: pointer; border: 1px solid var(--line); }
.aff:hover { color: var(--text); }
.aff.active { background: var(--link); color: #fff; border-color: var(--link); }

.af-day { margin-bottom: 16px; }
.af-date { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; margin: 0 0 8px; }
.af-item { border-left: 2px solid var(--line); padding: 0 0 0 18px; margin-left: 6px;
  position: relative; }
.af-item > summary { display: flex; align-items: center; gap: 10px; padding: 8px 0;
  cursor: pointer; list-style: none; flex-wrap: wrap; }
.af-item > summary::-webkit-details-marker { display: none; }
.af-item[hidden] { display: none; }
.af-node { position: absolute; left: -7px; top: 14px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--muted); border: 2px solid var(--panel); }
.af-node.dir-up { background: var(--up); } .af-node.dir-down { background: var(--down); }
.af-node.dir-neutral { background: var(--muted); }
.af-item.pinned > summary .af-node { box-shadow: 0 0 0 3px color-mix(in srgb, var(--info) 30%, transparent); }
.af-chip { font-size: 10.5px; font-weight: 700; padding: 2px 9px; border-radius: 7px;
  background: color-mix(in srgb, var(--c, var(--muted)) 16%, var(--panel));
  color: color-mix(in srgb, var(--c, var(--muted)) 82%, var(--text));
  border: 1px solid color-mix(in srgb, var(--c, var(--muted)) 28%, transparent); white-space: nowrap; }
.af-chip.f-signal   { --c: var(--info); } .af-chip.f-trend  { --c: var(--link); }
.af-chip.f-momentum { --c: var(--g-cold); } .af-chip.f-strength { --c: var(--warn); }
.af-chip.f-cycle    { --c: var(--orange); }
.af-head { font-weight: 600; color: var(--text); font-size: 13.5px; flex: 1; min-width: 180px; }
.af-time { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.af-detail { padding: 2px 0 12px; font-size: 12.5px; color: var(--muted); line-height: 1.6; }
.af-edge { margin-top: 6px; font-size: 12px; color: var(--text); }
.af-fwd { margin-top: 3px; font-size: 12px; color: var(--muted); }
.af-empty { padding: 10px 2px; color: var(--muted); font-size: 13px; }

/* mobile: full-width search, and tighter links so the wrapped menu stays compact
   (controls stay pinned in their own grid column regardless) */
@media (max-width: 760px) { .nav-search { max-width: none; } }
@media (max-width: 560px) {
  /* one column: toggles get their own top-right row, the menu links wrap across
     the FULL width below (instead of being squeezed beside the toggles), then
     the search — so links stay readable and the toggles never float mid-list. */
  .site-nav { grid-template-columns: 1fr; column-gap: 8px; row-gap: 8px; }
  /* stretch the cluster to the full column and let it WRAP — keeping the default
     justify-self:end sized it to its content (max-content), so the AI-brief pills +
     theme + EN/中文 toggles overflowed the viewport ~21px at 375px. flex-wrap lets
     the toggles drop to a second row instead of spilling; justify-content keeps
     them flush right as the comment below intends. */
  .site-nav .nav-ctrls { grid-column: 1; grid-row: 1; margin-top: 0;
    justify-self: stretch; flex-wrap: wrap; justify-content: flex-end; min-width: 0; }
  .site-nav .nav-links { grid-column: 1; grid-row: 2; }
  .nav-search { grid-column: 1; grid-row: 3; }
  .site-nav a.nav-link { padding: 6px 8px; font-size: 12.5px; }
  .site-nav .nav-ctrls { gap: 7px; }
  .site-nav .nav-brand .brand-word { display: none; }  /* phones: keep the menu compact, glyph only */
}

/* ---- Time-machine warning chips: hover definition popover ------------------ */
.tm-flag { position: relative; cursor: help; }
.tm-flag .tm-tip { display: none; position: absolute; bottom: 145%; left: 0;
  width: 230px; max-width: 230px; background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 10px; z-index: 70; font-size: 11.5px; font-weight: 400;
  line-height: 1.45; color: var(--text); text-align: left; box-shadow: var(--popover-shadow);
  pointer-events: none; white-space: normal; letter-spacing: normal; }
.tm-flag:hover .tm-tip, .tm-flag:focus .tm-tip { display: block; }
/* chips near the right edge of the row open leftward so the tip stays on-screen */
.tm-flags .tm-flag:nth-child(n+4) .tm-tip { left: auto; right: 0; }

/* ---- Signal stack: consolidated cross-subsystem read (display-only) -------- */
#signal-stack .sstack-grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 760px) { #signal-stack .sstack-grid { grid-template-columns: 1fr; } }
.sstack-legs { display: flex; flex-direction: column; }
.sstack-leg { display: grid; grid-template-columns: 12px 1fr auto; align-items: center; gap: 11px;
  padding: 7px 2px; border-bottom: 1px solid var(--line); }
.sstack-leg:last-child { border-bottom: none; }
.sstack-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
.sstack-name { font-size: 13.5px; color: var(--text); }
.sstack-tier { font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
  border: 1px solid var(--line); border-radius: 4px; padding: 1px 4px; margin-left: 7px; vertical-align: middle; }
.sstack-state { font-size: 12.5px; font-weight: 600; text-align: right; }
.sstack-dot.tone-up { background: var(--up); } .sstack-dot.tone-down { background: var(--down); }
.sstack-dot.tone-flat { background: var(--muted); }
.sstack-state.tone-up, b.tone-up { color: var(--up); } .sstack-state.tone-down, b.tone-down { color: var(--down); }
.sstack-state.tone-flat { color: var(--muted); }
.sstack-verdict { background: var(--panel2); border: 1px solid var(--line); border-radius: 11px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 9px; }
.sstack-final { font-size: 16.5px; color: var(--text); }
.sstack-final.tone-up { color: var(--up); } .sstack-final.tone-down { color: var(--down); }
.sstack-agree { font-size: 13px; color: var(--muted); } .sstack-agree b { color: var(--text); }
.sstack-tally { font-size: 12px; color: var(--muted); } .sstack-tally b { color: var(--text); }
.sstack-contra { font-size: 13px; color: var(--warn); line-height: 1.45; margin-top: 2px; }
.sstack-contra.ok { color: var(--ok); }

/* ---- progressive "show more" for standout-stock card grids (shared; wired by
   theme.js initShowMore on any [data-showmore] grid). Cards beyond the initial
   count are display:none until revealed, then fade-slide in (staggered). ------- */
.sm-hidden { display: none !important; }
@keyframes smReveal { from { opacity: 0; transform: translateY(10px) scale(.985); }
                      to   { opacity: 1; transform: none; } }
.sm-reveal { animation: smReveal .36s cubic-bezier(.2,.7,.3,1) both; }
@media (prefers-reduced-motion: reduce) { .sm-reveal { animation: none; } }
.sm-bar { display: flex; align-items: center; justify-content: center; gap: 10px 14px;
  flex-wrap: wrap; margin: 15px 0 2px; }
.sm-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.sm-count b { color: var(--text); font-weight: 700; }
.sm-btns { display: inline-flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.sm-btn { display: inline-flex; align-items: center; gap: 7px; padding: 8px 18px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel2); color: var(--text); font: inherit;
  font-size: 13px; font-weight: 600; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease; }
.sm-btn:hover { border-color: var(--link); color: var(--link); transform: translateY(-1px);
  box-shadow: 0 5px 16px rgba(0,0,0,.16); }
.sm-btn:active { transform: translateY(0); box-shadow: none; }
.sm-btn .sm-ic { font-size: 11px; line-height: 1; transition: transform .25s ease; }
.sm-btn.sm-ghost { background: transparent; border-color: transparent; color: var(--muted); font-weight: 500; padding: 8px 12px; }
.sm-btn.sm-ghost:hover { color: var(--link); background: var(--panel2); box-shadow: none; transform: none; }
.sm-btn.sm-collapse .sm-ic { transform: rotate(180deg); }

/* ---- sitewide theme-toggle flourish (theme.js skyToggleFx) ------------------
   A compact, modern icon blooms in the centre of the screen on every page EXCEPT
   the landing hub (which runs its own richer sun/moon choreography + sets
   window.__skyDeck): a luminous sun (→ light) or a crescent moon (→ dark). It
   pops in with a soft expanding ring, holds, and fades. Pure CSS, self-removing.
   The crescent is mask-carved on .disc; the glow lives on .orb (unmasked). */
.sky-fx { position: fixed; inset: 0; z-index: 2147483600; pointer-events: none;
  display: grid; place-items: center; }
.sky-fx .orb { position: relative; width: clamp(74px, 11vw, 104px); height: clamp(74px, 11vw, 104px);
  border-radius: 50%; animation: skyfx-pop 1.05s cubic-bezier(.18,.9,.3,1) forwards; }
.sky-fx .disc { position: absolute; inset: 0; border-radius: 50%; }
.sky-fx .ring { position: absolute; inset: -7px; border-radius: 50%; border: 2px solid currentColor;
  opacity: 0; animation: skyfx-ring 1.05s ease-out forwards; }
.sky-fx.sun .orb { box-shadow: 0 0 40px 8px rgba(255,210,120,.55), 0 0 104px 34px rgba(255,180,80,.28); }
.sky-fx.sun .disc { background: radial-gradient(circle at 50% 46%, #fffdf7 0%, #ffeeb8 26%, #ffc35a 58%, rgba(255,150,40,.3) 74%, transparent 82%); }
.sky-fx.sun .ring { color: rgba(255,200,110,.6); }
.sky-fx.moon .orb { box-shadow: 0 0 40px 8px rgba(160,190,245,.5), 0 0 104px 34px rgba(130,165,235,.26); }
.sky-fx.moon .disc { background: radial-gradient(circle at 42% 38%, #f4f7ff 0%, #cbd6ee 64%, #9fb0d2 100%);
  -webkit-mask: radial-gradient(circle at 70% 36%, transparent 0 41%, #000 42%);
  mask: radial-gradient(circle at 70% 36%, transparent 0 41%, #000 42%); }
.sky-fx.moon .ring { color: rgba(160,190,245,.55); }
@keyframes skyfx-pop { 0% { transform: scale(.5); opacity: 0; } 26% { transform: scale(1.05); opacity: 1; }
  40% { transform: scale(1); } 72% { opacity: 1; } 100% { transform: scale(1.02); opacity: 0; } }
@keyframes skyfx-ring { 0% { transform: scale(.55); opacity: .55; } 70% { opacity: .12; } 100% { transform: scale(2.1); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .sky-fx { display: none !important; } }

/* Forward-cone "anticipation" conviction note — hidden site-wide (low signal value).
   Single shared-CSS gate so it stays suppressed on every dashboard (US / China / HK /
   Canada / Intl) regardless of which generator emitted it (engine.stock_score or
   scripts.build_intl_library._cone_note). The sibling 'rank' note is unaffected. */
.nb-note-anticipation { display: none !important; }

/* ---- confluence buy-gate tier badge (owner's T1->T4 cascade, _sig_badge.html.j2) ---- */
.sig-gate { display:inline-flex; align-items:center; gap:3px; font-size:11px; font-weight:600;
  line-height:1; padding:2px 7px; border-radius:999px; white-space:nowrap;
  background: color-mix(in srgb, var(--c, var(--muted)) 16%, var(--panel));
  color: color-mix(in srgb, var(--c, var(--muted)) 82%, var(--text));
  border: 1px solid color-mix(in srgb, var(--c, var(--muted)) 34%, transparent); }
.sig-gate.sig-take { --c: var(--ok); }
.sig-gate.sig-pending { --c: var(--warn); }
.sig-gate.sig-t2 { --c: var(--ok); opacity:.82; }
.sig-gate.sig-early { --c: var(--muted); }
/* S1 HTF-sponsorship badge (display-only, rank-neutral, 2026-07-06) */
.sig-gate.sig-htf-s1 { --c: #7c6ece; font-size:10px; font-weight:800; letter-spacing:.3px; }
.sig-gate .sig-w { font-size:9.5px; font-weight:700; letter-spacing:.2px; opacity:.7;
  padding-left:3px; border-left:1px solid color-mix(in srgb, var(--c, var(--muted)) 30%, transparent); }
/* provisional-basis marker (W6 #22): a T3 fresh fire is graded on an incomplete resample
   bucket and repaints at a measured 9.4% US / 0% CN (post-N=2 persistence hardening) — flagged wherever the tier renders
   (_sig_badge, Top-setups strip, discovery chip). Dashed border = tentative by design. */
.prov-flag { display:inline-block; font-size:9px; font-weight:800; letter-spacing:.4px;
  text-transform:uppercase; line-height:1; padding:2px 5px; border-radius:4px; margin-left:4px;
  vertical-align:1px; white-space:nowrap; cursor:help;
  background: color-mix(in srgb, var(--warn) 22%, var(--panel));
  color: color-mix(in srgb, var(--warn) 92%, var(--text));
  border: 1.5px solid color-mix(in srgb, var(--warn) 60%, transparent); }

/* ---- Collapsible "Show more" lists (buy/add & reduce/avoid columns) -------------------
   Keeps long action lists short: 7 rows on a wide screen, 5 on a narrow one, the rest behind
   a Show more / Show less toggle. Markup: a column with class .lst-wrap containing a
   .lst-collapse.is-collapsed wrapper around the rows and a sibling .lst-more <button>.
   theme.js flips .is-collapsed + aria-expanded on click. Row hiding is plain :nth-child;
   only the button's visibility uses :has() (so it surfaces just when rows are actually
   hidden) — degrades to an always-shown button if :has() is unsupported, which is harmless. */
.lst-collapse.is-collapsed > :nth-child(n+8) { display:none; }
@media (max-width:680px) { .lst-collapse.is-collapsed > :nth-child(n+6) { display:none; } }
.lst-more { display:block; width:100%; margin-top:8px; padding:6px 10px;
  font: inherit; font-size:12px; font-weight:600; color:var(--muted); text-align:center;
  background:var(--panel2); border:1px solid var(--line); border-radius:8px; cursor:pointer; }
.lst-more:hover { color:var(--text); border-color:var(--muted); }
.lst-more .lm-hide { display:none; }
.lst-more[aria-expanded="true"] .lm-show { display:none; }
.lst-more[aria-expanded="true"] .lm-hide { display:inline; }
/* on wide screens, hide the button unless an 8th row exists (nothing hidden at ≤7 rows) */
@media (min-width:681px) {
  .lst-wrap:has(.lst-collapse) > .lst-more { display:none; }
  .lst-wrap:has(.lst-collapse > :nth-child(8)) > .lst-more { display:block; }
}

/* Tighter 6-row variant (.lst-cap6) — same plumbing, but caps at 6 on EVERY width.
   Used by the HOLD / avoid action column, which stacks the most sectors + baskets. The
   6th-child override beats the shared 5-on-mobile rule above; the :has() gate re-enables
   the button at a 7th row (the shared rule above would otherwise wait for an 8th). */
.lst-collapse.lst-cap6.is-collapsed > :nth-child(n+7) { display:none; }
@media (max-width:680px) { .lst-collapse.lst-cap6.is-collapsed > :nth-child(6) { display:flex; } }
@media (min-width:681px) {
  .lst-wrap:has(.lst-collapse.lst-cap6 > :nth-child(7)) > .lst-more { display:block; }
}

/* Tightest 4-row variant (.lst-cap4) — the China stocks page's "What to act on now"
   sector columns cap at 4 on EVERY width; button gates on a 5th child. */
.lst-collapse.lst-cap4.is-collapsed > :nth-child(n+5) { display:none; }
@media (min-width:681px) {
  .lst-wrap:has(.lst-collapse.lst-cap4 > :nth-child(5)) > .lst-more { display:block; }
}

/* ---- List overlay (theme.js initListOverlay) -------------------------------------
   Replaces the in-flow "Show more" expansion on every .lst-wrap list: theme.js restyles
   the .lst-more button into a quiet "View all N" pill (.lst-viewall) and a click MOVES
   the live .lst-collapse node into a centered modal instead of unfolding it in place
   (a 40-row lane expanded in-flow made the column ~4 pages tall). The list node itself
   is relocated — bilingual l-en/l-zh spans, delegated handlers and row popovers keep
   working inside the modal — and is returned to its placeholder on close. The native
   scrollbar is hidden and replaced by a JS-driven thumb (.lst-ovl-sb) because macOS
   overlay scrollbars auto-hide and ignore ::-webkit-scrollbar styling entirely. */
.lst-more.lst-viewall { width:fit-content; padding:4px 12px; margin:8px auto 2px;
  font-size:11px; border-radius:999px; background:transparent; }
.lst-more.lst-viewall .lst-va-arr { opacity:.6; margin-left:2px; }
.lst-more.lst-viewall:hover .lst-va-arr { opacity:1; }
.lst-ovl { position:fixed; inset:0; z-index:10500; display:flex; align-items:center;
  justify-content:center; padding:20px;
  background:color-mix(in srgb, var(--bg) 60%, transparent);
  backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px);
  opacity:0; pointer-events:none; transition:opacity .16s ease; }
.lst-ovl.is-open { opacity:1; pointer-events:auto; }
.lst-ovl-modal { width:min(660px, 94vw); max-height:78vh; display:flex; flex-direction:column;
  background:var(--panel); border:1px solid var(--line); border-radius:14px;
  box-shadow:0 28px 90px rgba(0,0,0,.45), 0 2px 8px rgba(0,0,0,.3);
  transform:translateY(10px) scale(.985); transition:transform .18s cubic-bezier(.2,.7,.3,1);
  overflow:hidden; outline:none; }
.lst-ovl.is-open .lst-ovl-modal { transform:none; }
@media (prefers-reduced-motion:reduce) { .lst-ovl, .lst-ovl-modal { transition:none; } }
.lst-ovl-hd { --lane:var(--muted); position:relative; display:flex; align-items:flex-start;
  gap:10px; padding:14px 16px 11px; border-bottom:1px solid var(--line); }
.lst-ovl-hd::before { content:""; position:absolute; top:0; left:0; right:0; height:3px;
  background:linear-gradient(90deg, var(--lane), transparent 70%); }
.lst-ovl-title { font-size:13px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--lane); line-height:1.3; }
.lst-ovl-count { margin-left:6px; font-size:11px; font-weight:600; color:var(--muted);
  background:var(--panel2); border:1px solid var(--line); border-radius:999px;
  padding:1px 8px; vertical-align:1px; }
.lst-ovl-sub { display:block; margin-top:2px; font-size:11px; font-weight:400; letter-spacing:0;
  text-transform:none; color:var(--muted); }
.lst-ovl-x { margin-left:auto; flex:none; width:28px; height:28px; border-radius:8px;
  border:1px solid transparent; background:transparent; color:var(--muted);
  font:inherit; font-size:15px; line-height:1; cursor:pointer; }
.lst-ovl-x:hover { background:var(--panel2); color:var(--text); border-color:var(--line); }
.lst-ovl-bodywrap { position:relative; flex:1; min-height:0; display:flex; }
.lst-ovl-body { flex:1; overflow-y:auto; overscroll-behavior:contain;
  padding:6px 18px 12px 16px; scrollbar-width:none; -ms-overflow-style:none; }
.lst-ovl-body::-webkit-scrollbar { display:none; }
.lst-ovl-sb { position:absolute; top:8px; right:5px; bottom:8px; width:5px; border-radius:3px;
  background:color-mix(in srgb, var(--muted) 12%, transparent); }
.lst-ovl-sb-thumb { position:absolute; left:0; width:100%; border-radius:3px;
  background:color-mix(in srgb, var(--muted) 55%, transparent); cursor:grab; }
.lst-ovl-sb-thumb:hover, .lst-ovl-sb-thumb.is-drag {
  background:color-mix(in srgb, var(--muted) 80%, transparent); }
.lst-ovl-ft { padding:9px 16px; font-size:10.5px; color:var(--muted);
  border-top:1px solid var(--line); display:flex; gap:12px; justify-content:space-between; }
body.lst-ovl-lock { overflow:hidden; }
/* transitional: the US action board's page-local .act-pop (z 9999) must clear the
   overlay until the follow-up PR replaces it with the shared .row-pop engine */
body.lst-ovl-lock .act-pop { z-index:12000; }
/* rows breathe a little more inside the modal than in a packed column */
.lst-ovl-body > .lst-collapse > * { border-bottom:1px solid
  color-mix(in srgb, var(--line) 60%, transparent); padding-top:8px; padding-bottom:9px; }
.lst-ovl-body > .lst-collapse > :last-child { border-bottom:0; }

/* ---- Row conditions popover (theme.js initRowPop) --------------------------------
   Shared hover/focus card for board rows: any element with [data-rpop] and a hidden
   .rp-src child gets a body-appended fixed popover built from a CLONE of that child
   (dual-span l-en/l-zh content — the [data-lang] CSS picks the language, so it
   live-updates on toggle). Unlike the retired page-local .act-pop engine, the card
   itself is hoverable (grace timers bridge the gap), scrolling REPOSITIONS instead of
   dismissing, and keyboard focus opens it. z-index sits above the list overlay so
   cards work on rows inside the modal. */
.row-pop { position:fixed; z-index:12000; width:360px; max-width:min(92vw, 400px);
  background:var(--panel); border:1px solid var(--line); border-radius:12px;
  box-shadow:0 18px 60px rgba(0,0,0,.4), 0 2px 8px rgba(0,0,0,.25);
  font-size:12px; color:var(--text); }
.row-pop-hd { display:flex; align-items:center; gap:8px; padding:11px 13px 9px; flex-wrap:wrap; }
.row-pop-name { font-weight:700; font-size:13px; color:var(--text); }
.row-pop-kind { font-size:9.5px; font-weight:600; letter-spacing:.08em; padding:2px 7px;
  border-radius:999px; color:var(--muted); background:var(--panel2); border:1px solid var(--line); }
.row-pop-tag { margin-left:auto; font-size:10px; font-weight:700; letter-spacing:.05em;
  padding:2px 8px; border-radius:6px; color:var(--muted); background:var(--panel2);
  border:1px solid var(--line); }
.row-pop-tag.up   { color:var(--up);   background:color-mix(in srgb, var(--up) 12%, transparent);
  border-color:color-mix(in srgb, var(--up) 35%, transparent); }
.row-pop-tag.dn   { color:var(--down); background:color-mix(in srgb, var(--down) 10%, transparent);
  border-color:color-mix(in srgb, var(--down) 32%, transparent); }
.row-pop-tag.warn { color:var(--warn); background:color-mix(in srgb, var(--warn) 10%, transparent);
  border-color:color-mix(in srgb, var(--warn) 32%, transparent); }
.row-pop-div { height:1px; background:var(--line); margin:0 13px; }
.row-pop-grid { display:grid; grid-template-columns:1fr 1fr; gap:7px 14px; padding:10px 13px; }
.row-pop-cell { display:flex; flex-direction:column; gap:2px; min-width:0; }
.row-pop-cell.wide { grid-column:1 / -1; }
.row-pop-lbl { font-size:9.5px; letter-spacing:.07em; text-transform:uppercase; color:var(--muted); }
.row-pop-val { font-size:12px; font-weight:600; color:var(--text); font-variant-numeric:tabular-nums; }
.row-pop-val .up  { color:var(--up); }
.row-pop-val .dn  { color:var(--down); }
.row-pop-val .mut { color:var(--muted); font-weight:400; }
.row-pop-bar { height:3px; border-radius:2px; background:var(--panel2); margin-top:3px;
  position:relative; overflow:hidden; }
.row-pop-bar i { position:absolute; top:0; bottom:0; left:0; border-radius:2px; background:currentColor; }
.row-pop-why { margin:0; padding:2px 13px 10px; }
.row-pop-why li { list-style:none; position:relative; padding-left:12px; margin:3px 0;
  font-size:11px; color:var(--muted); line-height:1.45; }
.row-pop-why li::before { content:"·"; position:absolute; left:2px; }
.row-pop-ft { padding:7px 13px 9px; border-top:1px solid var(--line); font-size:9.5px;
  color:var(--muted); display:flex; justify-content:space-between; gap:10px; }
.rp-src { display:none !important; }

/* ==== Act-Now v2 four-lane board (W8-R3, china_stocks.html) ================
   anv2-board: stocks-mode only; macro-panel keeps legacy actcol.
   Lane accent: buy=green, pull=blue, bot=amber, red=red.
   Mobile: single-column ≤560px; board label 12px nowrap at 390px.
   =========================================================================== */
.anv2-board { }
.anv2-hd { display:flex; align-items:flex-start; justify-content:space-between; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
.anv2-hd h2 { font-size:15px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; margin:0; display:flex; align-items:center; gap:8px; flex-wrap:nowrap; white-space:nowrap; }
@media (max-width:390px) { .anv2-hd h2 { font-size:12px; } }
.anv2-v2pill { font-size:10px; font-weight:700; background:color-mix(in srgb,var(--info) 14%,var(--panel)); color:color-mix(in srgb,var(--info) 80%,var(--text)); border:1px solid color-mix(in srgb,var(--info) 28%,transparent); padding:1px 7px; border-radius:5px; }
.anv2-meta { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.anv2-xlink { font-size:12px; color:var(--link); font-weight:600; text-decoration:none; white-space:nowrap; }
.anv2-xlink:hover { text-decoration:underline; }
.anv2-notes { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:8px; }
/* four-column grid at ≥960px, two-column 560–959, single-column ≤560 */
.anv2-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; align-items:start; }
@media (max-width:960px) { .anv2-grid { grid-template-columns:repeat(2,1fr); } }
@media (max-width:560px)  { .anv2-grid { grid-template-columns:1fr; } }
/* individual lane card */
.anv2-lane { background:var(--panel); border:1px solid var(--line); border-radius:14px; overflow:hidden; display:flex; flex-direction:column; }
/* accent top bar */
.anv2-lane-hd { padding:10px 13px 8px; border-bottom:1px solid var(--line); position:relative; }
.anv2-lane-hd::before { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:14px 14px 0 0; background:var(--anv2-accent,var(--muted)); }
.anv2-lane--buy   { --anv2-accent: var(--up); }
.anv2-lane--pull  { --anv2-accent: var(--info); }
.anv2-lane--bot   { --anv2-accent: var(--warn); }
.anv2-lane--red   { --anv2-accent: var(--down); }
.anv2-lane-title { font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; display:flex; align-items:center; gap:5px; white-space:nowrap; }
.anv2-lane--buy   .anv2-lane-title { color:var(--up); }
.anv2-lane--pull  .anv2-lane-title { color:var(--info); }
.anv2-lane--bot   .anv2-lane-title { color:var(--warn); }
.anv2-lane--red   .anv2-lane-title { color:var(--down); }
.anv2-lane-count { font-size:11px; color:var(--muted); font-weight:400; text-transform:none; letter-spacing:0; }
.anv2-lane-sub { font-size:10.5px; color:var(--muted); margin-top:3px; line-height:1.4; }
.anv2-lane--bot .anv2-lane-sub { color:color-mix(in srgb,var(--warn) 75%,var(--muted)); }
/* lane body */
.anv2-lane-body { padding:6px 0; flex:1; }
/* bottoming disclaimer box */
.anv2-bot-disc { margin:6px 12px 4px; background:color-mix(in srgb,var(--warn) 8%,var(--panel2)); border:1px solid color-mix(in srgb,var(--warn) 20%,transparent); border-radius:7px; padding:6px 9px; font-size:10.5px; line-height:1.45; }
.anv2-bot-disc strong { display:block; font-size:10px; letter-spacing:.04em; text-transform:uppercase; color:color-mix(in srgb,var(--warn) 90%,var(--text)); margin-bottom:2px; }
/* row items */
.anv2-lst .anv2-row { padding:7px 13px; border-bottom:1px solid color-mix(in srgb,var(--line) 55%,transparent); min-width:0; overflow:hidden; }
.anv2-lst .anv2-row:last-child { border-bottom:none; }
.anv2-lst .anv2-row:hover { background:color-mix(in srgb,var(--panel2) 55%,transparent); }
.anv2-row-top { display:flex; align-items:center; justify-content:space-between; gap:6px; margin-bottom:4px; }
.anv2-name { font-size:12.5px; font-weight:600; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.anv2-score { font-size:15px; font-weight:800; font-variant-numeric:tabular-nums; white-space:nowrap; }
.anv2-score-hi  { color:var(--up); }
.anv2-score-mid { color:var(--warn); }
.anv2-score-lo  { color:var(--down); }
.anv2-chips { display:flex; flex-wrap:wrap; gap:3px; align-items:center; margin-bottom:3px; }
/* chip base */
.anv2-chip { display:inline-flex; align-items:center; font-size:10px; font-weight:700; letter-spacing:.03em; padding:2px 6px; border-radius:4px; border:1px solid; white-space:nowrap; text-transform:uppercase; }
.anv2-chip-theme  { background:color-mix(in srgb,var(--info) 12%,var(--panel)); color:color-mix(in srgb,var(--info) 80%,var(--text)); border-color:color-mix(in srgb,var(--info) 26%,transparent); }
.anv2-chip-basket { background:color-mix(in srgb,#8b5cf6 10%,var(--panel)); color:color-mix(in srgb,#8b5cf6 80%,var(--text)); border-color:color-mix(in srgb,#8b5cf6 24%,transparent); }
.anv2-chip-sector { background:color-mix(in srgb,var(--warn) 10%,var(--panel)); color:color-mix(in srgb,var(--warn) 75%,var(--text)); border-color:color-mix(in srgb,var(--warn) 24%,transparent); }
/* reco chips */
.anv2-chip-reco-accumulate,.anv2-chip-reco-enter { background:color-mix(in srgb,var(--up) 14%,var(--panel)); color:color-mix(in srgb,var(--up) 85%,var(--text)); border-color:color-mix(in srgb,var(--up) 32%,transparent); }
.anv2-chip-reco-hold { background:color-mix(in srgb,var(--muted) 12%,var(--panel)); color:color-mix(in srgb,var(--muted) 75%,var(--text)); border-color:color-mix(in srgb,var(--muted) 24%,transparent); }
.anv2-chip-reco-trim,.anv2-chip-reco-avoid { background:color-mix(in srgb,var(--down) 12%,var(--panel)); color:color-mix(in srgb,var(--down) 80%,var(--text)); border-color:color-mix(in srgb,var(--down) 28%,transparent); }
/* bottoming + dual-read chips */
.anv2-chip-trough  { background:color-mix(in srgb,var(--warn) 12%,var(--panel)); color:color-mix(in srgb,var(--warn) 85%,var(--text)); border-color:color-mix(in srgb,var(--warn) 28%,transparent); }
.anv2-chip-turn    { background:color-mix(in srgb,#3dd6c8 10%,var(--panel)); color:color-mix(in srgb,#3dd6c8 80%,var(--text)); border-color:color-mix(in srgb,#3dd6c8 24%,transparent); }
.anv2-chip-washout { background:color-mix(in srgb,var(--warn) 11%,var(--panel)); color:color-mix(in srgb,var(--warn) 80%,var(--text)); border-color:color-mix(in srgb,var(--warn) 26%,transparent); cursor:help; }
.anv2-chip-tag     { background:var(--panel2); color:var(--muted); border-color:var(--line); }
/* stat line */
.anv2-stat { font-size:11px; color:var(--muted); }
.anv2-pos { color:var(--up); font-weight:600; }
.anv2-neg { color:var(--down); font-weight:600; }

/* ==== regime panels (base-effect strip + HMM regime-probability) — shared by dashboard.html.j2 (US) + china.html.j2. Status colours --ok/--warn/--muted do NOT flip in zh; quad colours --q1..--q4 do (intentional). ==== */
/* MEASURED / MODELED / NO-EDGE honesty badges (status colours --ok/--warn/--muted do NOT
   flip in zh mode, unlike --up/--down) + the base-effect forward strip (v0). */
.mbadge { display:inline-flex; align-items:center; gap:4px; font-size:9px; font-weight:800;
          letter-spacing:.07em; padding:2px 7px; border-radius:5px; text-transform:uppercase; border:1px solid; }
.mbadge.measured { color:var(--ok);    border-color:color-mix(in srgb,var(--ok) 55%,transparent);   background:color-mix(in srgb,var(--ok) 12%,transparent); }
.mbadge.modeled  { color:var(--warn);  border-color:color-mix(in srgb,var(--warn) 55%,transparent); background:color-mix(in srgb,var(--warn) 12%,transparent); }
.mbadge.noedge   { color:var(--muted); border-color:var(--line); background:var(--panel2); }
.bfwd .bfwd-head { display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin:0 0 4px; }
.bfwd .bfwd-head h3 { font-size:12px; margin:0; color:var(--text); text-transform:uppercase; letter-spacing:.05em; }
.bfwd-sub { color:var(--muted); font-size:12px; margin:0 0 12px; max-width:78ch; }
.bfwd-main { display:flex; gap:18px; flex-wrap:wrap; align-items:stretch; }
.bfwd-now { flex:0 0 auto; min-width:158px; display:flex; flex-direction:column; gap:3px; justify-content:center;
            padding:10px 15px; border-radius:11px; color:#fff; }
.bfwd-now.q-Q2 { color:#1a1a1a; }
.bfwd-now .k { font-size:9px; letter-spacing:.09em; text-transform:uppercase; opacity:.9; }
.bfwd-now .v { font-size:17px; font-weight:800; line-height:1.12; }
.bfwd-now .s { font-size:10px; opacity:.88; }
.bfwd-axes { flex:1 1 300px; display:grid; grid-template-columns:auto auto 1fr; gap:7px 14px; align-content:center; }
.bfwd-ax-l { font-size:11px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; align-self:center; }
.bfwd-ax-v { font-variant-numeric:tabular-nums; font-weight:700; font-size:13px; align-self:center; white-space:nowrap; }
.bfwd-ax-v .bfa { font-weight:700; margin-left:3px; }
.bfwd-ax-n { font-size:11px; color:var(--muted); align-self:center; }
.bfwd-path { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:14px; }
.bfwd-path .pl { font-size:10px; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; margin-right:2px; }
.bfwd-path .arw { color:var(--muted); }
.bfq { border-radius:6px; padding:4px 9px; color:#fff; font-weight:700; font-size:10.5px; white-space:nowrap; }
.bfq.q-Q2 { color:#1a1a1a; } .bfq small { font-weight:500; opacity:.85; }
.bfwd-note { font-size:11px; color:var(--muted); margin-top:12px; line-height:1.5;
             border-top:1px solid var(--line); padding-top:8px; }
@media (max-width:640px){ .bfwd-main{ gap:12px; } .bfwd-now{ width:100%; }
  .bfwd-axes{ grid-template-columns:auto 1fr; column-gap:12px; row-gap:2px; }
  .bfwd-ax-n{ grid-column:1/-1; margin:0 0 8px; } }
/* HMM regime-probability panel (v1) — soft P(Quad) + transition odds + hazard */
.rhmm-main { display:flex; gap:24px; flex-wrap:wrap; align-items:flex-start; }
.rhmm-bars { display:grid; grid-template-columns:auto 1fr auto; gap:5px 9px; align-items:center;
             flex:1 1 340px; max-width:480px; }
.rhmm-q { font-size:11px; font-weight:600; white-space:nowrap; }
.rhmm-track { height:12px; border-radius:6px; background:var(--panel2); overflow:hidden; min-width:70px; }
.rhmm-fill { height:100%; border-radius:6px; }
.rhmm-pct { font-size:11px; font-variant-numeric:tabular-nums; color:var(--muted); text-align:right; min-width:34px; }
.rhmm-side { flex:1 1 300px; font-size:12px; line-height:1.65; }
.rhmm-side .k { color:var(--muted); text-transform:uppercase; font-size:10px; letter-spacing:.05em; }
.rhmm-chip { display:inline-block; padding:1px 7px; border-radius:5px; color:#fff; font-size:10.5px;
             font-weight:700; margin:0 3px 3px 0; }
.rhmm-chip.q-Q2 { color:#1a1a1a; }
@media (max-width:640px){ .rhmm-bars{ min-width:0; } }

/* ---- i18n tooltip popover ([data-tip-en]/[data-tip-zh], wired in theme.js) --------
   The replacement for bilingual title= attributes: ONE body-appended fixed-position
   popover whose dual-span body follows the [data-lang] rules above — so only the
   active language ever shows. Body-level + fixed → no card overflow clipping. */
[data-tip-en] { cursor: help; }
.i18n-tip-pop {
  /* above .row-pop (12000): a chip tip opened from inside a row must not vanish
     behind that row's own conditions card */
  display: none; position: fixed; z-index: 12500;
  max-width: min(320px, calc(100vw - 24px));
  padding: 7px 10px; border-radius: 8px;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0,0,0,.18);
  font-size: 11px; font-weight: 500; line-height: 1.5; color: var(--text);
  text-align: left; text-transform: none; letter-spacing: normal; white-space: normal;
}

/* ── W8-R1: Ripening three-zone shelf (READY / BASING / FALLING sink) ─────── */
/* Zone accent tokens — inherit from --up/--down/--warn; re-stated for legibility. */
.rip-shelf { border:1px solid var(--line); border-radius:12px; overflow:hidden; margin-top:16px; }
.rip-shelf-hdr { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
                 padding:13px 16px 11px; border-bottom:1px solid var(--line);
                 background:color-mix(in srgb,var(--warn) 4%,var(--panel)); }
.rip-shelf-title { font-size:12px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
                   color:var(--muted); }
.rip-shelf-sub { font-size:11px; color:var(--muted); }
.rip-shelf-asof { margin-left:auto; font-size:10.5px; color:var(--muted); opacity:.7; }

/* Zone band */
.rip-zone { padding:14px 16px; border-bottom:1px solid var(--line); }
.rip-zone:last-child { border-bottom:none; }
.rip-zone.rz-ready  { background:color-mix(in srgb,var(--up) 5%,var(--panel)); border-left:3px solid var(--up); }
.rip-zone.rz-basing { background:var(--panel); border-left:3px solid color-mix(in srgb,var(--muted) 40%,var(--line)); }
.rip-zone.rz-fall   { background:color-mix(in srgb,var(--down) 5%,var(--panel)); border-left:3px solid var(--down); }

/* Zone header row — uses .nb-shelf-hdr accent-left-border idiom */
.rip-zone-hdr { display:flex; align-items:center; gap:9px; margin-bottom:12px; flex-wrap:wrap; }
.rip-zone-label { font-size:11px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; }
.rz-ready  .rip-zone-label { color:var(--up); }
.rz-basing .rip-zone-label { color:var(--muted); }
.rz-fall   .rip-zone-label { color:var(--down); }
.rip-zone-count { font-size:9.5px; font-weight:700; padding:1px 6px; border-radius:14px; }
.rz-ready  .rip-zone-count { background:color-mix(in srgb,var(--up) 14%,var(--panel)); color:var(--up); border:1px solid color-mix(in srgb,var(--up) 28%,transparent); }
.rz-basing .rip-zone-count { background:color-mix(in srgb,var(--muted) 12%,var(--panel)); color:var(--muted); border:1px solid color-mix(in srgb,var(--muted) 20%,transparent); }
.rz-fall   .rip-zone-count { background:color-mix(in srgb,var(--down) 14%,var(--panel)); color:var(--down); border:1px solid color-mix(in srgb,var(--down) 28%,transparent); }
.rip-zone-defn { font-size:10.5px; color:var(--muted); margin-left:auto; font-style:italic; }
.rip-toggle-btn { margin-left:auto; font-size:10.5px; color:var(--link); cursor:pointer;
                  background:none; border:none; font-family:inherit; padding:2px 7px; border-radius:6px; }
.rip-toggle-btn:hover { background:color-mix(in srgb,var(--link) 10%,transparent); }

/* Scorecard grid for READY + BASING */
.rip-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(240px,1fr)); gap:12px; }
@media (max-width:480px) { .rip-grid, .nbgrid { grid-template-columns:1fr; } }

/* Full scorecard for ripening (similar to .nbcard chassis) */
.rip-card { background:var(--panel2,var(--panel)); border:1px solid var(--line); border-radius:11px;
            overflow:hidden; display:flex; flex-direction:column; transition:border-color .18s; }
.rip-card:hover { border-color:color-mix(in srgb,var(--link) 40%,var(--line)); }
.rip-card-stripe { height:3px; }
.rz-ready  .rip-card-stripe { background:linear-gradient(90deg,var(--up),color-mix(in srgb,var(--up) 30%,transparent)); }
.rz-basing .rip-card-stripe { background:linear-gradient(90deg,var(--muted),transparent); opacity:.6; }
.rz-fall   .rip-card-stripe { background:linear-gradient(90deg,var(--down),color-mix(in srgb,var(--down) 30%,transparent)); }
.rip-card-body { padding:11px 13px; display:flex; flex-direction:column; gap:8px; }
.rip-card-id { display:flex; justify-content:space-between; align-items:flex-start; gap:6px; }
.rip-card-tk { font-size:13px; font-weight:800; letter-spacing:.02em; color:var(--text); }
.rip-card-px { font-size:13px; font-weight:700; color:var(--text); white-space:nowrap; text-align:right; }
.rip-card-nm { font-size:11px; color:var(--muted); line-height:1.3; margin-top:1px; }
.rip-card-sec { font-size:9.5px; color:var(--muted); opacity:.8; margin-top:1px; }
/* Sparkline row */
.rip-card-spark { height:34px; width:100%; }
.rip-card-spark svg { width:100%; height:100%; }
/* 2-col metrics grid */
.rip-metrics { display:grid; grid-template-columns:1fr 1fr; gap:5px 10px; }
.rip-metric { display:flex; flex-direction:column; gap:1px; }
.rip-metric-lbl { font-size:9px; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; font-weight:600; }
.rip-metric-val { font-size:12px; font-weight:700; color:var(--text); display:flex; align-items:center; gap:3px; }
.rip-metric-val.pos { color:var(--up); } .rip-metric-val.neg { color:var(--down); } .rip-metric-val.mut { color:var(--muted); }
/* MACD glyph strip (D/2D/3D) */
.rip-macd-strip { display:flex; gap:3px; align-items:center; }
.rip-macd-g { font-size:12px; line-height:1; }
.rip-macd-g.pg { color:var(--up); } .rip-macd-g.ng { color:var(--down); } .rip-macd-g.mg { color:var(--muted); }
.rip-macd-lbl { font-size:8.5px; color:var(--muted); letter-spacing:.03em; }
/* Evidence + chip row */
.rip-chips { display:flex; flex-wrap:wrap; gap:4px; margin-top:2px; }
.rip-chip { font-size:9px; font-weight:600; padding:2px 7px; border-radius:14px; border:1px solid transparent; white-space:nowrap; }
.rip-chip.cp-cross { background:color-mix(in srgb,var(--info) 10%,var(--panel)); color:var(--info); border-color:color-mix(in srgb,var(--info) 25%,transparent); }
.rip-chip.cp-ready { background:color-mix(in srgb,var(--up) 10%,var(--panel)); color:var(--up); border-color:color-mix(in srgb,var(--up) 25%,transparent); }
.rip-chip.cp-warn  { background:color-mix(in srgb,var(--warn) 10%,var(--panel)); color:var(--warn); border-color:color-mix(in srgb,var(--warn) 25%,transparent); }
.rip-chip.cp-neutral { background:color-mix(in srgb,var(--muted) 8%,var(--panel)); color:var(--muted); border-color:color-mix(in srgb,var(--muted) 18%,transparent); }
/* Stoch arrow */
.rip-arrow { font-size:10px; }
.rip-arrow.up { color:var(--up); } .rip-arrow.dn { color:var(--down); } .rip-arrow.fl { color:var(--muted); }

/* FALLING sink — compact rows, muted+red */
.rip-fall-rows { display:flex; flex-direction:column; gap:5px; }
.rip-fall-row { display:grid; grid-template-columns:120px 1fr auto auto; align-items:center; gap:10px;
                background:color-mix(in srgb,var(--down) 4%,var(--panel)); border:1px solid color-mix(in srgb,var(--down) 15%,var(--line));
                border-radius:7px; padding:7px 11px; opacity:.72; font-size:11px; }
.rip-fall-tk { font-weight:800; color:var(--text); }
.rip-fall-nm { font-size:10px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rip-fall-ret { font-weight:700; color:var(--down); white-space:nowrap; }
.rip-fall-lbl { font-size:9.5px; color:var(--down); opacity:.7; }
@media (max-width:480px) {
  .rip-fall-row { grid-template-columns:1fr auto; grid-template-rows:auto auto; }
  .rip-fall-nm { grid-column:1/-1; grid-row:2; }
}
/* Collapse state */
.rip-fall-body { display:block; }
.rip-fall-body.rip-collapsed { display:none; }

/* ---- help "?" icon glyph metrics (site-wide correction) --------------------
   The circular help/hint icon is defined inline per page as
   `.help { width:15px; height:15px; border-radius:50%; font-size:10px; … }`.
   At 10px the "?" glyph is too tall for the 13px inner circle and its top curve
   + bottom dot visibly touch the border. This one shared rule shrinks the glyph
   so it sits centred with even breathing room on every page at once — the
   `span.help` selector (0,0,1,1) outranks the inline `.help` rules (0,0,1,0)
   regardless of source order, and every help icon is a <span class="help">.
   Only the glyph metrics are overridden; the circle box stays as each page
   defines it (so the icon footprint / alignment is unchanged). */
span.help { font-size: 9px; line-height: 1; }

/* 2026-07-16: unify the look with the "new" Mag7 / Leadership icons — a filled pill
   (panel2 fill + subtle line border + bolder glyph) instead of the thin outline — and
   route the tooltip through theme.js's viewport-clamped tap-to-toggle popover.
   BOTH the restyle and the popover apply ONLY to icons theme.js has confirmed are
   canonical help() "?" glyphs (upgradeHelpIcons → .help-upgraded). This scoping is
   deliberate and load-bearing: the bare `.help` class is reused on NON-icon content
   (market-state factor labels `f-name help`, the seasonality cell, the anticipation
   `idxbadge … help`) whose rich tooltips + styling must be left untouched — those are
   never upgraded, so they never match .help-upgraded. */
span.help.help-upgraded { font-size: 9.5px; font-weight: 700;
  background: var(--panel2); border-color: var(--line); color: var(--muted); }
/* once upgraded, suppress the old nested :hover tooltip so it doesn't double up with
   the popover (progressive enhancement — .tip stays live until JS marks the icon). */
.help.help-upgraded .tip { display: none !important; }

/* The upgraded "?" icons (and the sibling Mag7 / Leadership / table-header icons) must
   not select-on-hold or pop the iOS callout menu on touch — a long press should do
   nothing (the popover opens on tap), not start a text selection. Scoped so content
   rows keep normal selection; the popover body (.i18n-tip-pop) also stays selectable. */
.help.help-upgraded, .m7p-help, .ldb-help, .st-th-tip {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
