
  * { box-sizing: border-box; }
  body { background: var(--bg); color: var(--text);
         font-family: var(--font-ui); font-size: 14px; line-height: 1.5;
         margin: 0; padding: 18px; }
  /* breathing room on wide desktops — content centered, never edge-to-edge */
  @media (min-width: 1100px) { body { padding: 26px max(40px, calc((100vw - 1500px) / 2)); } }
  body.page-macro { padding-top: 26px; }
  a { text-decoration: none; }
  h1 { font-size: 20px; margin: 0 0 2px; }
  h2 { font-size: 15px; margin: 0 0 10px; color: var(--muted);
       text-transform: uppercase; letter-spacing: .06em; }
  h3 { font-size: 13px; margin: 14px 0 6px; color: var(--text); }
  .grid { display: grid; gap: 14px; grid-template-columns: repeat(12, 1fr); }
  .panel { background: var(--panel); border: 1px solid var(--line);
           border-radius: 10px; padding: 14px 16px; }
  .sb-section-lbl{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin:16px 0 6px;border-top:1px solid var(--line);padding-top:10px}
  .sb-section-lbl:first-child{border-top:none;margin-top:0;padding-top:0}
  .span12 { grid-column: span 12; } .span8 { grid-column: span 8; }
  .span6 { grid-column: span 6; } .span4 { grid-column: span 4; }
  @media (max-width: 900px) { .span8, .span6, .span4 { grid-column: span 12; } }

  .badge { display: inline-block; padding: 3px 12px; border-radius: 14px;
           font-weight: 600; font-size: 13px; }
  /* quad badge keeps its solid vivid colour; ink + fill tuned per quad so this
     13px size clears 4.5:1 in BOTH themes (hero badges pass at the 3:1 large-text
     bar elsewhere). Mid-luminance hues carry near-black ink (gold, green) or a
     slightly deepened fill (blue, light green); zh swaps q1/q3 hues at the token
     level, so the ink/fill choices swap with them in the zh rules below (kept
     after the light rules — the tie resolves in source order). */
  .quad-Q3, .quad-Q4 { color: #fff; }
  .quad-Q1, .quad-Q2 { color: #1a1a1a; }
  .quad-Q1 { background: var(--q1); } .quad-Q2 { background: var(--q2); }
  .quad-Q3 { background: var(--q3); } .quad-Q4 { background: var(--q4); }
  html:not([data-theme="light"]) .quad-Q4 { background: color-mix(in srgb, var(--q4) 88%, var(--bg)); }
  html[data-theme="light"] .quad-Q1 { background: color-mix(in srgb, var(--q1) 90%, var(--text)); color: #fff; }
  html[data-lang="zh"] .quad-Q1 { background: var(--q1); color: #fff; }
  html[data-lang="zh"] .quad-Q3 { color: #1a1a1a; }
  html[data-theme="light"][data-lang="zh"] .quad-Q3 { background: color-mix(in srgb, var(--q3) 90%, var(--text)); color: #fff; }

  .kv { color: var(--muted); } .kv b { color: var(--text); font-weight: 600; }

  table { border-collapse: collapse; width: 100%; font-size: 13px; }
  th, td { text-align: right; padding: 4px 8px; border-bottom: 1px solid var(--line); }
  th { color: var(--muted); font-weight: 500; }
  th:first-child, td:first-child { text-align: left; }
  td.l, th.l { text-align: left; }

  .pill { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 12px; }

  .alert { display: block; padding: 10px 13px; border-radius: 8px; margin: 8px 0;
           background: var(--panel2); border-left: 3px solid var(--muted);
           color: var(--text); transition: transform .12s, box-shadow .12s; }
  a.alert:hover { transform: translateX(2px); box-shadow: 0 3px 14px rgba(0,0,0,.22); }
  .alert-act { border-left-color: var(--act); }
  .alert-warn { border-left-color: var(--warn); }
  .alert-info { border-left-color: var(--info); }
  .alert-head { display: flex; align-items: baseline; gap: 8px; }
  .alert-ico { font-size: 15px; flex: none; line-height: 1; }
  .alert-head b { font-size: 13.5px; color: var(--text); }
  .alert-jump { margin-left: auto; font-size: 11px; font-weight: 700;
                color: var(--ink-link, var(--link)); flex: none; white-space: nowrap; }
  .alert-detail { margin: 6px 0 0; font-size: 12.5px; color: var(--text);
                  font-variant-numeric: tabular-nums; }
  .alert-what { margin: 6px 0 0; padding-top: 6px; border-top: 1px solid var(--line);
                font-size: 12px; color: var(--muted); line-height: 1.5; }
  .alert-edge { margin: 5px 0 0; font-size: 12px; color: var(--text); line-height: 1.45; }
  .alert-edge b { color: var(--muted); font-weight: 600; }
  /* deep-linked panel flash: when an alert jumps here, pulse a glow once */
  .panel { scroll-margin-top: 16px; }
  @keyframes panelflash {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--link) 0%, transparent); }
    12%  { box-shadow: 0 0 0 4px color-mix(in srgb, var(--link) 60%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--link) 0%, transparent); }
  }
  .panel.flash { animation: panelflash 2.4s ease-out 1; border-color: var(--link); }
  /* Dislocation stress-filter CSS removed 2026-07-30 with the panel it styled —
     the readout now lives on macro_signals.html (its own scoped `.dislo-panel`
     block). Nothing on this page carries `dislo-strip` / `dlx-*` any more. */
  .muted { color: var(--muted); }
  .chart { width: 100%; }
  .topline { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }

  /* ============================================================================
     RISK RADAR CARD (.rrx) — the one shared, redesigned alert used on the US Macro
     + US-Stocks pages AND the China / HK / Canada Market-State boards (the macros
     live in _risk_radar_card.html.j2). GLOBAL theme vars only + an inline --rc state
     accent, so it renders the same in the page-macro, page-stocks and china/hk/canada
     scopes. The escalating odds ramp replaces the old cramped "5d.. 10d.. 21d.." run.
     Included by dashboard.html.j2 (both modes) + _market_state.css.j2 (CN/HK/CA). ==== */
  .rrx { --rc: var(--warn);
         display: grid; gap: 12px; margin: 12px 0 2px; padding: 15px 18px; border-radius: 12px;
         background: var(--panel);
         border: 1px solid var(--line);
         border-left: 4px solid var(--rc); font-size: 12.5px; line-height: 1.4;
         box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 16px 32px -24px rgba(0,0,0,.4); }
  body.page-macro .ms-front > .rrx { margin: 0 0 14px; }
  /* grouping wrappers: inert everywhere by default (the card keeps its single-column
     stack on the China/HK/Canada/stocks placements); the macro front-page overrides
     these to display:flex to build the 2-column banner. */
  .rrx > .rrx-main, .rrx > .rrx-side { display: contents; min-width: 0; }
  /* Perf: loud pulse = pseudo animating ONLY opacity (compositor-run); animating
     box-shadow on the card repainted it every frame (2026-07-21 mobile audit).
     mmGlowBreathe keyframes ship in theme.css (loaded on every placement). */
  .rrx.rrx-loud { background: color-mix(in srgb, var(--rc) 5%, var(--panel));
         position: relative;
         box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rc) 20%, transparent), 0 14px 34px -18px color-mix(in srgb, var(--rc) 70%, transparent); }
  .rrx.rrx-loud::before { content: ""; position: absolute; inset: 0; border-radius: inherit;
         pointer-events: none;
         box-shadow: 0 0 0 5px color-mix(in srgb, var(--rc) 6%, transparent);
         opacity: 0; animation: mmGlowBreathe 2.4s ease-in-out infinite; }
  @media (prefers-reduced-motion: reduce) { .rrx.rrx-loud::before { animation: none; opacity: 0; }
         .rrx.rrx-loud { box-shadow: 0 0 0 1px color-mix(in srgb, var(--rc) 30%, transparent); } }
  /* header */
  .rrx .rrx-hd { display: flex; align-items: flex-start; gap: 10px; }
  .rrx .rrx-ic { font-size: 18px; line-height: 1.1; flex: none; }
  .rrx .rrx-id { min-width: 0; flex: 1; }
  .rrx .rrx-ttl { display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
         font-weight: 700; font-size: 13px; color: var(--text); }
  .rrx .rrx-badge { font-weight: 800; letter-spacing: .03em; color: var(--rc); font-size: 11.5px;
         font-variant-numeric: tabular-nums; padding: 1px 7px; border-radius: 5px;
         background: color-mix(in srgb, var(--rc) 16%, transparent);
         border: 1px solid color-mix(in srgb, var(--rc) 38%, transparent); }
  .rrx .rrx-dom { color: var(--muted); font-size: 11.5px; margin-top: 2px; }
  .rrx .rrx-authority { font-size: 10.5px; line-height: 1.35; margin-top: 3px; font-weight: 600; }
  .rrx .rrx-authority.is-advisory { color: var(--muted); }
  .rrx .rrx-authority.is-binding { color: var(--rc); }
  .rrx .rrx-amp { color: var(--rc); font-weight: 600; font-size: 11px; margin-top: 3px; }
  .rrx .rrx-gross { flex: none; text-align: center; padding: 3px 11px; border-radius: 9px;
         background: color-mix(in srgb, var(--rc) 12%, transparent);
         border: 1px solid color-mix(in srgb, var(--rc) 32%, transparent); }
  .rrx .rrx-gross .gv { display: block; font-weight: 800; font-size: 15px; color: var(--rc);
         font-variant-numeric: tabular-nums; line-height: 1.1; }
  .rrx .rrx-gross .gn { display: block; font-size: 9px; text-transform: uppercase; letter-spacing: .07em;
         color: var(--muted); }
  /* odds hero — flat on the card (the amber wash now lives on .rrx itself, not a nested box) */
  .rrx .rrx-odds { display: flex; gap: 16px; align-items: stretch; flex-wrap: wrap; }
  .rrx .rrx-odds-l { flex: 1 1 150px; display: flex; flex-direction: column; justify-content: center; }
  .rrx .rrx-cap { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
         color: var(--muted); }
  .rrx .rrx-cap-sub { font-weight: 600; letter-spacing: .02em; opacity: .8; }
  .rrx .rrx-big { font-weight: 800; font-size: 40px; line-height: .95; color: var(--rc); margin: 4px 0 2px;
         font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
  .rrx .rrx-big .pct { font-size: 22px; margin-left: 1px; }
  .rrx .rrx-big .rrx-hz { font-size: 11px; font-weight: 600; color: var(--muted); margin-left: 7px;
         letter-spacing: 0; }
  .rrx .rrx-vsn { font-size: 11.5px; color: var(--muted); }
  .rrx .rrx-vsn b { color: var(--text); font-variant-numeric: tabular-nums; }
  /* escalating ramp */
  .rrx .rrx-ramp { flex: 1 1 240px; min-width: 0; max-width: 430px; display: flex; align-items: flex-end;
         justify-content: space-between; gap: 12px; position: relative; padding-top: 18px; }
  .rrx .rrx-col { flex: 1 1 0; min-width: 0; max-width: 76px; display: flex; flex-direction: column;
         align-items: center; gap: 5px; }
  .rrx .rrx-v { font-size: 12.5px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
  .rrx .rrx-col.is-hd .rrx-v { color: var(--rc); }
  .rrx .rrx-tk { width: 100%; max-width: 54px; height: 64px; position: relative;
         display: flex; align-items: flex-end; justify-content: center; border-bottom: 1px solid var(--line); }
  .rrx .rrx-norm { position: absolute; left: 0; right: 0; bottom: 0; border-radius: 2px 2px 0 0;
         background: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--muted) 32%, transparent) 0 4px, transparent 4px 8px);
         border-top: 1px dashed color-mix(in srgb, var(--muted) 60%, transparent); }
  .rrx .rrx-fill { width: 100%; border-radius: 3px 3px 0 0; position: relative; z-index: 1; min-height: 6px;
         background: linear-gradient(180deg, var(--rc), color-mix(in srgb, var(--rc) 50%, transparent)); }
  .rrx .rrx-hl { font-size: 10.5px; font-weight: 600; color: var(--muted); }
  .rrx .rrx-col.is-hd .rrx-hl { color: var(--text); }
  .rrx .rrx-leg { position: absolute; top: 0; right: 2px; display: flex; align-items: center; gap: 4px;
         font-size: 9.5px; color: var(--muted); }
  .rrx .rrx-leg-n { width: 13px; border-top: 1px dashed color-mix(in srgb, var(--muted) 60%, transparent); }
  /* threat meters */
  .rrx .rrx-threats { display: flex; flex-wrap: wrap; gap: 6px; }
  .rrx .rrx-th { --sb: var(--muted); display: inline-flex; align-items: center; gap: 6px;
         padding: 3px 9px; border-radius: 7px; font-size: 11px;
         background: var(--panel); border: 1px solid var(--line); }
  .rrx .rrx-th.dom { background: color-mix(in srgb, var(--sb) 10%, var(--panel));
         border-color: color-mix(in srgb, var(--sb) 50%, var(--line)); }
  .rrx .rrx-th.dim { opacity: .58; }
  .rrx .rrx-th-n { color: var(--text); font-weight: 600; }
  .rrx .rrx-th.dom .rrx-th-n { color: var(--sb); }
  .rrx .rrx-meter { display: inline-flex; gap: 1.5px; }
  .rrx .rrx-meter i { width: 3px; height: 11px; border-radius: 1px;
         background: color-mix(in srgb, var(--muted) 28%, transparent); }
  .rrx .rrx-meter i.on { background: var(--sb); }
  .rrx .rrx-th-s { color: var(--text); font-weight: 800; font-size: 11.5px; font-variant-numeric: tabular-nums; }
  .rrx .rrx-tag { font-size: 8.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
         border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
  .rrx .rrx-ev { font-size: 11px; color: var(--muted); }
  .rrx .rrx-ev-k { font-weight: 700; color: var(--text); margin-right: 6px; }
  .rrx .rrx-ev-p { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
  /* action */
  .rrx .rrx-do { font-size: 12px; color: var(--text); padding-top: 9px;
         border-top: 1px solid color-mix(in srgb, var(--rc) 20%, var(--line)); }
  .rrx .rrx-do-k { font-weight: 800; color: var(--rc); text-transform: uppercase; letter-spacing: .06em;
         font-size: 10.5px; margin-right: 8px; }
  /* election-cycle context chip (US radar only; engine/election_cycle.py) */
  /* compressed to <=2 dense lines so the cycle context never balloons the card */
  .rrx .rrx-cyc { font-size: 10.5px; color: var(--muted); padding-top: 7px; margin-top: 2px; line-height: 1.4;
         border-top: 1px solid color-mix(in srgb, var(--rc) 16%, var(--line));
         display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; row-gap: 1px; }
  .rrx .rrx-cyc-k { font-weight: 700; color: var(--text); }
  .rrx .rrx-cyc-tag { color: var(--rc); font-weight: 700; font-size: 9.5px; }
  /* RC-R11 washout counter-read chip — a cyan-tinted variant of the modulator row. */
  .rrx .rrx-cyc.rrx-washout { border-top-color: color-mix(in srgb, var(--cyan, #38bdf8) 22%, var(--line)); }
  .rrx .rrx-cyc.rrx-washout .rrx-cyc-k { color: var(--cyan, #38bdf8); }
  .rrx .rrx-cyc-sub { color: var(--muted); font-size: 10px; margin: 0; }
  .rrx .rrx-cyc-sec { color: var(--text); font-size: 10px; margin: 0; flex-basis: 100%;
         font-variant-numeric: tabular-nums; }
  /* self-audit line (international radars only) */
  .rrx .rrx-audit { font-size: 10.5px; color: var(--muted); }
  .rrx .rrx-audit-k { font-weight: 700; color: var(--text); margin-right: 6px; }
  .rrx .rrx-audit b { color: var(--text); font-variant-numeric: tabular-nums; }
  /* track-record line — one muted glance-tier line surfacing the forward-ledger scorecard */
  .rrx .rrx-trk { font-size: 10.5px; color: var(--muted); display: flex;
         align-items: center; gap: 5px; flex-wrap: wrap; line-height: 1.4; }
  /* de-escalation panel (engine/risk_radar_recovery.py) — "risk peaking / risk-off may be ending".
     Display-only; --rvc = green when receding, blue when merely peaking. Cool palette so it never
     reads like a green "all-clear" buy signal. */
  .rrx .rrx-rec { --rvc: var(--info); display: flex; flex-direction: column; gap: 7px;
         padding: 9px 11px; border-radius: 9px;
         background: color-mix(in srgb, var(--rvc) 7%, var(--panel));
         border: 1px solid color-mix(in srgb, var(--rvc) 30%, var(--line));
         border-left: 3px solid var(--rvc); }
  .rrx .rrx-rec.is-turn { background: color-mix(in srgb, var(--rvc) 13%, var(--panel));
         box-shadow: 0 0 0 1px color-mix(in srgb, var(--rvc) 26%, transparent); }
  .rrx .rrx-rec-hd { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
  .rrx .rrx-rec-ar { color: var(--rvc); font-weight: 800; font-size: 14px; line-height: 1; }
  .rrx .rrx-rec-ttl { font-weight: 700; font-size: 12px; color: var(--text); }
  .rrx .rrx-rec-tag { font-size: 8.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
         color: var(--rvc); background: color-mix(in srgb, var(--rvc) 16%, transparent);
         border: 1px solid color-mix(in srgb, var(--rvc) 42%, transparent); border-radius: 4px; padding: 0 5px; }
  .rrx .rrx-rec-mid { display: flex; align-items: center; gap: 9px; }
  .rrx .rrx-rec-spark { width: 84px; height: 24px; flex: none;
         background: color-mix(in srgb, var(--rvc) 5%, transparent); border-radius: 4px; }
  .rrx .rrx-rec-spark .pk { fill: var(--muted); }
  .rrx .rrx-rec-spark .lx { fill: var(--rvc); }
  .rrx .rrx-rec-sub { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 0; }
  .rrx .rrx-rec-cats { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
  .rrx .rrx-rec-k { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
         color: var(--muted); }
  .rrx .rrx-rec-chip { display: inline-flex; align-items: center; gap: 3px; font-size: 10.5px;
         color: var(--text); padding: 2px 7px; border-radius: 6px;
         background: var(--panel); border: 1px solid var(--line); }
  .rrx .rrx-rec-chip.fresh { color: var(--fresh-ok); font-weight: 600;
         border-color: color-mix(in srgb, var(--fresh-ok) 45%, var(--line));
         background: color-mix(in srgb, var(--fresh-ok) 10%, var(--panel)); }
  .rrx .rrx-rec-cats.none { font-size: 10.5px; color: var(--muted); font-style: italic; }
  /* RRX2 WA: drivers line ("what faded / still warm") + muted "no signal" chip */
  .rrx .rrx-rec-drv { font-size: 10px; color: var(--muted); line-height: 1.4; margin-top: -2px; }
  /* RLT-R5: measured-edge salience line — receipt/muted styling, demoted below catalyst chips */
  .rrx .rrx-rec-sal { font-size: 10px; color: var(--muted); font-style: italic; line-height: 1.4;
         padding: 2px 0 0; border-top: 1px solid color-mix(in srgb, var(--muted) 20%, transparent); margin-top: 1px; }
  .rrx .rrx-rec-chip.muted { color: var(--muted); font-style: italic; border-style: dashed; }
  .rrx .rrx-rec-do { font-size: 11px; color: var(--text); line-height: 1.4; }
  .rrx .rrx-rec-do-k { font-weight: 800; color: var(--rvc); text-transform: uppercase; letter-spacing: .06em;
         font-size: 9.5px; margin-right: 6px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx { gap: 10px; padding: 13px 16px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-odds { gap: 14px; align-items: center; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-big { font-size: 34px; margin: 2px 0 1px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-big .pct { font-size: 19px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-vsn { font-size: 11px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-ramp { gap: 10px; padding-top: 12px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-col { gap: 3px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-v { font-size: 11.5px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-tk { height: 44px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-hl { font-size: 10px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-audit,
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-th.dim,
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-rec-mid,
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-rec-do,
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-cyc-sub,
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-cyc-sec { display: none; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-rec { gap: 5px; padding: 7px 10px; }
  body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx .rrx-cyc { padding-top: 5px; line-height: 1.25; }
  body:is(.page-macro, .page-china, .page-canada) { padding-top: 26px; }
  @media (max-width: 760px) {
    .rrx .rrx-odds { flex-direction: column; gap: 14px; }
    .rrx .rrx-odds-l { flex: 0 0 auto; }
    .rrx .rrx-ramp { flex: 0 0 auto; width: 100%; max-width: none; justify-content: space-around; }
  }
  /* phone: collapse to a SIMPLE, STRONG alert — headline + the one number that
     matters + the action. The ramp, the verbose amplification line and the
     non-dominant threat meters are desktop-only detail, not a mobile wall. */
  @media (max-width: 560px) {
    .rrx { padding: 14px 15px; gap: 10px; }
    .rrx .rrx-amp, .rrx .rrx-ramp, .rrx .rrx-ev, .rrx .rrx-cyc, .rrx .rrx-audit { display: none; }
    .rrx .rrx-cgl { display: flex; }
    .rrx .rrx-big { font-size: 34px; }
    .rrx .rrx-threats { gap: 5px; }
    .rrx .rrx-th:not(.dom) { display: none; }
  }
  /* desktop: the consolidated 2-column board (header/odds/ramp | threats/evidence/
     action/cycle) on EVERY market's .ms-front board, not just the US macro one —
     roughly halves the card height vs the single-column stack. The US dashboard
     keeps its own (higher-specificity, identical) copy; this is what reaches the
     China / HK / Canada boards that only load this shared partial.
     `.imd-radar` is the international dashboards' section wrapper (JP/KR/EZ/GB/IN,
     templates/international_macro.html.j2) — a full-page-width placement, so it takes
     the same wide board instead of stranding the ramp beside an empty middle. Inert
     on every page that has no such wrapper. */
  @media (min-width: 1100px) {
    :is(.ms-front, .imd-radar) > .rrx { grid-template-columns: minmax(0,1fr) minmax(0,1fr);
      column-gap: 22px; row-gap: 0; align-items: stretch; }
    :is(.ms-front, .imd-radar) > .rrx > .rrx-main { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
    :is(.ms-front, .imd-radar) > .rrx > .rrx-main .rrx-odds { flex: 1 1 auto; }
    :is(.ms-front, .imd-radar) > .rrx > .rrx-main .rrx-ramp { align-items: stretch; }
    :is(.ms-front, .imd-radar) > .rrx > .rrx-main .rrx-tk { height: auto; flex: 1 1 auto; min-height: 64px; }
    :is(.ms-front, .imd-radar) > .rrx > .rrx-side { display: flex; flex-direction: column; justify-content: center;
      gap: 9px; min-width: 0; padding-left: 22px;
      border-left: 1px solid color-mix(in srgb, var(--rc) 22%, var(--line)); }
    body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx > .rrx-main .rrx-odds { flex: 0 0 auto; }
    body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx > .rrx-main .rrx-ramp { align-items: flex-end; }
    body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx > .rrx-main .rrx-tk { height: 44px; flex: 0 0 44px; min-height: 44px; }
    body:is(.page-macro, .page-china, .page-canada) .ms-front > .rrx > .rrx-side { gap: 7px; padding-left: 20px; }
  }

/* ── AI BRIEF v2 (aib2-*) — shared token spine ──────────────────────────────── */
.aib2{
  /* accent defaults to a stable Western blue (never red-flips in ZH); macro
     overrides to its green brief accent on its own dialog root. */
  --aib2-acc:var(--info,#3b82f6);
  --aib2-mut:var(--muted,rgba(255,255,255,.55));
  --aib2-surf:rgba(255,255,255,.035);
  --aib2-hair:rgba(255,255,255,.09);
  --aib2-track:rgba(255,255,255,.12);
  /* tone palette — engine-computed key_facts + stance tints. These are SEMANTIC
     quality tints (good/warn/bad), NOT price direction, so they use FIXED hexes and
     must NOT bind to --up/--down (which swap red<->green under html[data-lang="zh"]).
     This matches the sibling china chip idiom (.cnx-chip.turn = fixed green,
     .cnx-chip.hot = fixed red) — a "good" reading stays green in EN and ZH alike. */
  /* Bound to the HEALTH tokens rather than fixed hexes: --ok/--act encode safety,
     never direction, so they already do not flip under 红涨绿跌 — which is exactly
     the property this block was hand-rolling. Binding also earns the light twins
     and the --ink-* text grades for free (the fixed pair measured 2.7:1 and 3.5:1
     on a white panel). Same intent, one source of truth. */
  --aib2-good:var(--ok,#45b873);
  --aib2-bad:var(--act,#e06464);
  --aib2-warn:var(--warn,#f59e0b);  /* amber — does not flip in ZH */
  --aib2-info:var(--info,#5b9bf0);  /* blue  — does not flip in ZH */
  color:var(--text);
}
[data-theme="light"] .aib2{
  --aib2-surf:rgba(0,0,0,.028);--aib2-hair:rgba(0,0,0,.09);--aib2-track:rgba(0,0,0,.12);
  --aib2-good:#1f9a55;--aib2-bad:#cf4040;  /* light-theme fixed variants (match theme.css) */
}

/* ── 1 · header strip ───────────────────────────────────────────────────────── */
.aib2-hdr{display:flex;align-items:flex-start;gap:14px;margin-bottom:18px;padding-bottom:15px;
  border-bottom:1px solid color-mix(in srgb,var(--aib2-acc) 16%,var(--aib2-hair));}
.aib2-icon{width:38px;height:38px;flex-shrink:0;border-radius:11px;
  background:linear-gradient(150deg,color-mix(in srgb,var(--aib2-acc) 22%,transparent),color-mix(in srgb,var(--aib2-acc) 8%,transparent));
  border:1px solid color-mix(in srgb,var(--aib2-acc) 30%,transparent);
  color:var(--aib2-acc);font-size:13px;font-weight:800;letter-spacing:.02em;
  display:flex;align-items:center;justify-content:center;}
.aib2-hdr-meta{flex:1;min-width:0;}
.aib2-hdr-title{font-size:15px;font-weight:700;color:var(--text);line-height:1.3;margin-bottom:4px;}
.aib2-hdr-sub{display:flex;align-items:center;gap:9px;flex-wrap:wrap;}
.aib2-hdr-date{font-size:12px;color:var(--aib2-mut);font-variant-numeric:tabular-nums;letter-spacing:.02em;}
.aib2-cadence{font-size:10.5px;font-weight:650;letter-spacing:.02em;
  padding:2px 9px;border-radius:999px;
  background:color-mix(in srgb,var(--aib2-acc) 11%,transparent);
  border:1px solid color-mix(in srgb,var(--aib2-acc) 24%,transparent);
  color:color-mix(in srgb,var(--aib2-acc) 82%,var(--text));}
.aib2-badge{margin-left:auto;align-self:center;font-size:10.5px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--aib2-acc);opacity:.85;text-align:right;line-height:1.45;
  white-space:normal;max-width:210px;flex-shrink:0;}
[data-theme="light"] .aib2-badge{opacity:.95;}

/* ── section spine — a labelled hairline naming each movement ────────────────── */
.aib2-sec{display:flex;align-items:center;gap:10px;margin:20px 0 11px;}
.aib2-sec:first-child{margin-top:4px;}
.aib2-sec::after{content:"";flex:1;height:1px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--aib2-acc) 26%,var(--aib2-hair)),transparent);}
.aib2-sec-label{font-size:10.5px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--aib2-mut);display:inline-flex;align-items:center;gap:7px;}
.aib2-sec-label::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--aib2-acc);}

/* ── 2 · the gist (glance tick-list) ────────────────────────────────────────── */
.aib2-gist{margin-bottom:16px;}
.aib2-gist-list{list-style:none;margin:0 0 12px;padding:0;display:flex;flex-direction:column;gap:9px;}
.aib2-gist-list li{position:relative;padding-left:20px;
  font-size:14.5px;line-height:1.55;color:var(--text);font-weight:500;}
.aib2-gist-list li::before{content:"";position:absolute;left:2px;top:.58em;
  width:7px;height:7px;border-radius:2px;transform:rotate(45deg);
  background:color-mix(in srgb,var(--aib2-acc) 62%,transparent);}
.aib2-gist-list li b{font-weight:750;color:var(--text);}
/* first gist item = the most important thing today — a touch louder */
.aib2-gist-list li:first-child{font-size:15px;font-weight:600;}

/* STANCE PILL — the signature. Accent-tinted directive; the stance verb is bold. */
.aib2-stance{display:flex;align-items:flex-start;gap:11px;
  padding:13px 16px;border-radius:13px;
  background:color-mix(in srgb,var(--aib2-acc) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--aib2-acc) 30%,transparent);
  border-left:4px solid color-mix(in srgb,var(--aib2-acc) 72%,transparent);
  box-shadow:0 1px 0 color-mix(in srgb,var(--aib2-acc) 8%,transparent);}
[data-theme="light"] .aib2-stance{background:color-mix(in srgb,var(--aib2-acc) 9%,#fff);}
.aib2-stance-mark{color:var(--aib2-acc);font-size:15px;line-height:1.4;flex-shrink:0;margin-top:1px;}
.aib2-stance-body{font-size:15px;line-height:1.5;color:var(--text);font-weight:600;}
.aib2-stance-body b{font-weight:800;
  /* the stance verb gets the accent so the eye lands on the directive first */
  color:color-mix(in srgb,var(--aib2-acc) 55%,var(--text));}
/* tone variants — protect/stand-aside lean amber; act leans green; ignore muted */
.aib2-stance--warn{--aib2-acc:var(--aib2-warn);}
.aib2-stance--go{--aib2-acc:var(--aib2-good);}
.aib2-stance--muted{--aib2-acc:var(--aib2-mut);}
.aib2-stance--muted .aib2-stance-body b{color:var(--text);}

/* v1 lead card (summary fallback when tldr absent) */
.aib2-lead{font-size:16.5px;font-weight:600;line-height:1.62;color:var(--text);
  padding:16px 18px;border-radius:13px;margin-bottom:16px;
  background:color-mix(in srgb,var(--aib2-acc) 7%,transparent);
  border:1px solid color-mix(in srgb,var(--aib2-acc) 18%,transparent);
  border-left:3px solid color-mix(in srgb,var(--aib2-acc) 60%,transparent);}
[data-theme="light"] .aib2-lead{background:color-mix(in srgb,var(--aib2-acc) 6%,#fff);}

/* ── 3 · key readings (key_facts chip rail) ─────────────────────────────────── */
.aib2-kf-rail{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px;}
.aib2-kf{display:inline-flex;align-items:baseline;gap:7px;
  padding:6px 12px;border-radius:999px;font-size:12.5px;line-height:1.3;
  background:var(--aib2-surf);border:1px solid var(--aib2-hair);max-width:100%;}
.aib2-kf-k{color:var(--aib2-mut);font-weight:600;white-space:nowrap;}
.aib2-kf-v{color:var(--text);font-weight:700;min-width:0;}
/* tone tints — the value carries the read; the chip border/wash confirms it */
.aib2-kf--good{background:color-mix(in srgb,var(--aib2-good) 10%,var(--aib2-surf));
  border-color:color-mix(in srgb,var(--aib2-good) 34%,transparent);}
.aib2-kf--good .aib2-kf-v{color:color-mix(in srgb,var(--aib2-good) 72%,var(--text));}
.aib2-kf--warn{background:color-mix(in srgb,var(--aib2-warn) 10%,var(--aib2-surf));
  border-color:color-mix(in srgb,var(--aib2-warn) 34%,transparent);}
.aib2-kf--warn .aib2-kf-v{color:color-mix(in srgb,var(--aib2-warn) 74%,var(--text));}
.aib2-kf--bad{background:color-mix(in srgb,var(--aib2-bad) 11%,var(--aib2-surf));
  border-color:color-mix(in srgb,var(--aib2-bad) 36%,transparent);}
.aib2-kf--bad .aib2-kf-v{color:color-mix(in srgb,var(--aib2-bad) 74%,var(--text));}
.aib2-kf--info{background:color-mix(in srgb,var(--aib2-info) 10%,var(--aib2-surf));
  border-color:color-mix(in srgb,var(--aib2-info) 32%,transparent);}
.aib2-kf--info .aib2-kf-v{color:color-mix(in srgb,var(--aib2-info) 78%,var(--text));}
.aib2-kf--neutral{/* uses base surf/hair; value stays --text */}

/* ── 4 · confidence meter ────────────────────────────────────────────────────── */
.aib2-conf{display:flex;align-items:center;gap:13px;margin-bottom:4px;
  padding:11px 14px;background:var(--aib2-surf);border:1px solid var(--aib2-hair);border-radius:11px;}
.aib2-conf-bar{display:flex;gap:4px;align-items:center;padding:4px;border-radius:7px;background:var(--aib2-track);cursor:help;}
.aib2-conf-seg{width:26px;height:6px;border-radius:3px;
  background:transparent;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--text) 8%,transparent);transition:background .2s;}
.aib2-conf-seg.on{background:var(--aib2-acc);box-shadow:none;}
.aib2-conf-label{font-size:12.5px;font-weight:650;color:var(--text);}
.aib2-conf-asof{font-size:11.5px;color:var(--aib2-mut);margin-left:auto;font-variant-numeric:tabular-nums;}

/* ── 5 · the full read (regime prose) ───────────────────────────────────────── */
.aib2-regime{font-size:14px;color:var(--text);line-height:1.72;margin-bottom:16px;opacity:.94;}

/* ── 6/7/8/9 · cards + grid ─────────────────────────────────────────────────── */
.aib2-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:13px;margin-bottom:12px;}
@media(max-width:560px){.aib2-grid{grid-template-columns:1fr;}}
.aib2-card{padding:14px 16px 15px;border-radius:12px;background:var(--aib2-surf);border:1px solid var(--aib2-hair);}
.aib2-card--full{margin-bottom:12px;}
.aib2-card--conflicts{border-left:3px solid var(--aib2-warn);}
.aib2-card--tx{border-left:3px solid var(--aib2-info);}
.aib2-card--playbook{border-left:3px solid var(--aib2-acc);}
.aib2-eyebrow{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--aib2-mut);margin-bottom:9px;display:flex;align-items:center;gap:6px;}
.aib2-card--conflicts .aib2-eyebrow{color:color-mix(in srgb,var(--aib2-warn) 78%,var(--aib2-mut));}
.aib2-card--tx .aib2-eyebrow{color:color-mix(in srgb,var(--aib2-info) 74%,var(--aib2-mut));}
.aib2-card--playbook .aib2-eyebrow{color:color-mix(in srgb,var(--aib2-acc) 74%,var(--aib2-mut));}
.aib2-items{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;}
.aib2-items li{position:relative;padding-left:14px;font-size:13px;color:var(--text);line-height:1.6;}
.aib2-items li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;border-radius:50%;
  background:color-mix(in srgb,currentColor 32%,transparent);}
.aib2-card--conflicts .aib2-items li::before{background:color-mix(in srgb,var(--aib2-warn) 55%,transparent);}
.aib2-card--tx .aib2-items li::before{background:color-mix(in srgb,var(--aib2-info) 55%,transparent);}
.aib2-items li b,.aib2-prose b,.aib2-watch-body b{font-weight:700;color:var(--text);}
.aib2-prose{font-size:13.5px;color:var(--text);line-height:1.72;}

/* what to watch */
.aib2-watch{list-style:none;margin:0;padding:0;}
.aib2-watch-row{display:flex;align-items:flex-start;gap:9px;font-size:13.5px;color:var(--text);line-height:1.6;padding:5px 0;}
.aib2-watch-row + .aib2-watch-row{border-top:1px solid var(--aib2-hair);}
.aib2-watch-mark{color:var(--aib2-acc);flex-shrink:0;margin-top:1px;font-size:13px;line-height:1.5;}

/* upcoming catalysts */
.aib2-cat-rail{display:flex;flex-wrap:wrap;gap:8px;}
.aib2-cat{display:inline-flex;align-items:baseline;gap:6px;padding:5px 12px;border-radius:999px;
  font-size:12.5px;font-weight:600;background:var(--aib2-surf);border:1px solid var(--aib2-hair);color:var(--text);}
.aib2-cat-d{color:var(--aib2-mut);font-variant-numeric:tabular-nums;font-weight:700;}
.aib2-cat-read{font-size:12.5px;color:var(--aib2-mut);line-height:1.55;margin-top:11px;}

/* ── 10 · degraded notice ────────────────────────────────────────────────────── */
.aib2-degraded{font-size:12px;color:var(--aib2-mut);margin:8px 0 4px;padding:9px 13px;border-radius:9px;
  background:color-mix(in srgb,var(--aib2-warn) 9%,transparent);
  border:1px solid color-mix(in srgb,var(--aib2-warn) 22%,transparent);
  border-left:3px solid var(--aib2-warn);}

/* ── responsive — 390px bleed guard ─────────────────────────────────────────── */
@media(max-width:560px){
  .aib2-hdr{flex-wrap:wrap;}
  /* the house-law badge takes its own wrapped row (aligned under the title,
     past the 38px icon + 14px gap) — without a flex-basis it stays on row 1
     and clips at the panel edge on narrow phones */
  .aib2-badge{flex-basis:calc(100% - 52px);margin-left:52px;text-align:left;max-width:none;align-self:flex-start;}
  .aib2-conf{flex-wrap:wrap;gap:9px;}
  .aib2-conf-asof{margin-left:0;width:100%;}
  .aib2-kf{width:100%;justify-content:space-between;}
}


  /* help-tip-framework:BEGIN — legacy help() "?" hover framework. Byte-identical
     twin in templates/dashboard.html.j2 AND templates/_us_act_now_board.html.j2
     (the shared board include ships it to hosts that have no page-level copy —
     sector_central leaked the whole tip sentence inline without it, 2026-08-06).
     Deliberately NOT in theme.css: editing theme.css re-stamps ~176 pages, and
     its span.help glyph metrics must keep outranking these bare-.help rules.
     Keep both copies in step — pinned by
     tests/test_us_act_now.py::test_help_tip_framework_is_byte_identical_in_both_copies. */
  .help { display: inline-flex; align-items: center; justify-content: center;
          width: 15px; height: 15px; border-radius: 50%; border: 1px solid var(--muted);
          color: var(--muted); font-size: 10px; font-weight: 600; cursor: help;
          position: relative; vertical-align: middle; margin-left: 5px; flex: none; }
  .help .tip { display: none; position: absolute; bottom: 140%; left: 50%;
               transform: translateX(-50%); width: 330px;
               background: var(--panel); border: 1px solid var(--line);
               padding: 10px 13px; border-radius: 8px;
               z-index: 60; font-size: 12px; line-height: 1.5; color: var(--text);
               text-align: left; font-weight: 400; text-transform: none;
               letter-spacing: normal; box-shadow: var(--popover-shadow);
               pointer-events: auto; cursor: auto; white-space: normal;
               max-height: min(60vh, 420px); overflow-y: auto; overscroll-behavior: contain; }
  /* invisible hover pad across the gap between the ? icon and the tip box —
     without it the :hover chain breaks mid-travel and the tip vanishes before
     the cursor can reach (and scroll) it. Lives on .help, not .tip: the tip
     is a scroll container (overflow-y:auto), which clips its own pseudos. */
  .help:hover::before { content: ''; position: absolute; bottom: 100%; left: -30px; right: -30px; height: 10px; }
  .help:hover .tip, .help.tip-open .tip { display: block; }
  th .help .tip, .help.below .tip { bottom: auto; top: 140%; }
  th .help:hover::before, .help.below:hover::before { bottom: auto; top: 100%; }
  /* keep tooltips on-screen near the right/left viewport edges */
  .help.edge-right .tip { left: auto; right: 0; transform: none; }
  .help.edge-left .tip { left: 0; right: auto; transform: none; }
  .help .tip.tip-wide { width: min(430px, calc(100vw - 32px)); }
  @media (max-width: 640px) {
    .help .tip.tip-wide { width: calc(100vw - 28px); font-size: 11.5px; line-height: 1.45; }
  }
  /* help-tip-framework:END */
  .tip-map { width: 360px !important; }
  .tip-seas { width: 350px !important; box-sizing: border-box; padding: 11px 14px; }
  .tip.tip-seas table { table-layout: fixed; width: 100%; margin: 0; }
  .tip.tip-seas th, .tip.tip-seas td { padding: 2px 5px; font-size: 11px; white-space: nowrap; }
  /* structured tooltip building blocks */
  .tip table { width: 100%; margin: 6px 0 2px; font-size: 11.5px; }
  .tip th, .tip td { padding: 3px 6px; border-bottom: 1px solid var(--line); }
  .tip .lad { display: block; padding: 3px 8px; border-radius: 5px; margin: 3px 0;
              font-size: 11.5px; }
  .tip .scale { display: flex; height: 12px; border-radius: 6px; overflow: hidden;
                margin: 6px 0 2px; font-size: 9.5px; font-weight: 700; }
  .tip .scale span { flex: 1; display: flex; align-items: center; justify-content: center;
                     color: #fff; }
  .tip .sl { display: flex; justify-content: space-between; font-size: 10px;
             color: var(--muted); margin-bottom: 4px; }
  .qgrid { display: grid; grid-template-columns: 58px 1fr 1fr; gap: 4px; margin: 8px 0; }
  .qax { color: var(--muted); font-size: 10.5px; align-self: center; text-align: center; }
  .qcell { border-radius: 6px; padding: 7px 6px; text-align: center; color: #fff;
           font-weight: 700; font-size: 11px; line-height: 1.25; }
  .qcell small { font-weight: 400; opacity: .85; }
  .qcell.qcur { outline: 2px solid #fff; }

  .dial { display: flex; gap: 4px; margin: 8px 0 12px; }
  .dial > span { flex: 1; text-align: center; padding: 6px 2px; border-radius: 6px;
               background: var(--panel2); color: var(--muted); font-size: 11px;
               font-weight: 600; letter-spacing: .04em; }
  .dial .active-DEFENSIVE { background: var(--act); color: #fff; }
  .dial .active-CAREFUL { background: var(--orange); color: #fff; }
  .dial .active-NEUTRAL { background: var(--muted); color: #fff; }
  .dial .active-CONSTRUCTIVE { background: var(--up); color: #fff; }
  .dial .active-AGGRESSIVE { background: var(--ok); color: #fff; }
  @media (max-width: 520px) { .dial > span { font-size: 8.5px; padding: 5px 1px; } }
  .reason { margin: 7px 0; padding-left: 24px; position: relative; line-height: 1.4; }
  /* +/−/i markers — own class (rsig) so they don't collide with the signal-atom .sig
     card (grid + ::before rail), which was hijacking them into a quarter-filled look. */
  .reason b.rsig { position: absolute; left: 0; top: 1px; width: 16px; height: 16px;
                  display: inline-flex; align-items: center; justify-content: center;
                  border-radius: 5px; font-size: 11px; font-weight: 800; line-height: 1; }
  .reason b.rsig-p { color: var(--ink-up, var(--up)); background: color-mix(in srgb, var(--up) 16%, transparent); }
  .reason b.rsig-m { color: var(--ink-down, var(--down)); background: color-mix(in srgb, var(--down) 16%, transparent); }
  .reason b.rsig-i { color: var(--ink-2, var(--muted)); background: color-mix(in srgb, var(--ink-2, var(--muted)) 14%, transparent); }
  /* lead the bullet with the read; demote the parenthetical stats so it scans */
  .reason .reason-main { font-weight: 600; color: var(--ink-1, var(--text)); }
  .reason .reason-det { color: var(--ink-3, var(--muted)); font-size: .92em; }

  .card { background: var(--panel2); border: 1px solid var(--line); border-radius: 8px;
          padding: 10px 12px; margin: 6px 0; }
  .card b.tk { font-size: 14px; }
  .calltag { float: right; font-size: 11px; font-weight: 700; padding: 1px 8px;
             border-radius: 9px; }
  /* .tag-lead/avoid/watch and .chip-pos/neg colours come from theme.css */
  .chip { display: inline-block; padding: 2px 9px; margin: 2px 3px 2px 0;
          border-radius: 10px; font-size: 12px; border: 1px solid var(--line); }

  /* action board */
  .actiongrid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; align-items: start; }
  @media (max-width: 1100px) { .actiongrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
  @media (max-width: 900px) { .actiongrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 560px) { .actiongrid { grid-template-columns: minmax(0, 1fr); } }
  /* V2 action board — lane column card, restyled to the china anv2 lane idiom
     (operator request 2026-07-11): panel card, 14px radius, 3px accent bar inside
     the header, colored uppercase lane titles, chips-below-name rows.
     Class names unchanged — fold JS (.actcol/.actbody/.act-fold) and the View-all
     modal (.acth-name/.acth-sub) query them. */
  .actcol { background: var(--panel); border: 1px solid var(--line); min-width: 0;
            border-radius: 14px; padding: 0; overflow: hidden;
            display: flex; flex-direction: column; --act-accent: var(--muted); }
  /* --act-accent stays fill-grade for the lane bar; --act-accent-ink is the
     text-grade twin for .acth-name (violet measured 4.19:1 dark / 3.89 light). */
  .act-buy  { --act-accent: var(--up); --act-accent-ink: var(--ink-up, var(--up)); }
  .act-soon { --act-accent: var(--info); --act-accent-ink: var(--ink-info, var(--info)); }
  .act-run  { --act-accent: #8b5cf6; --act-accent-ink: color-mix(in srgb, #8b5cf6 80%, var(--text)); }   /* neutral violet — NOT green/buy */
  .act-trim { --act-accent: var(--warn); --act-accent-ink: var(--ink-warn, var(--warn)); }
  .act-hold { --act-accent: var(--muted); --act-accent-ink: var(--muted); }
  html[data-theme="light"] .act-run { --act-accent-ink: color-mix(in srgb, #8b5cf6 72%, var(--text)); }
  /* ── Monoline marks (doctrine §5.8 — emoji are not UI icons) ──────────────
     Lane heads, row marks, the legend and the hover-card mark all draw from
     templates/_icons.html.j2 (24×24, stroke=currentColor), so each mark
     inherits its context's ink: the lane icons ride
     --act-accent-ink, which is what carries forward the per-lane colour
     identity the coloured dots used to supply — and the glyph now says what
     the lane DOES, which a coloured dot never did.
     The bottoming-watch strip (_us_bottoming_watch.html.j2, the board's own
     watch surface) reuses .acth-icon / .ai-bdg for its two marks instead of
     shipping a third icon rule, so it is sized from here.
     NO bare `.ic-svg {}` rule here on purpose: sector_central.html.j2 scopes
     its own copy under #si-confluence, and a global rule shipped from a panel
     would fight its host. Explicit selectors only, one size per context.
     .row-pop-mark is deliberately NOT scoped to #action-board — theme.js
     clones the hover card onto document.body, so an id-scoped rule would
     style the hidden source and miss the card the reader actually sees. */
  .ai-bdg .ic-svg, .acth-icon .ic-svg, .row-pop-mark .ic-svg,
  .ab-shock-ic .ic-svg, #action-board .help .tip .ic-svg {
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round; }
  .ai-bdg .ic-svg { width: 13px; height: 13px; display: block; }
  .acth-icon .ic-svg { width: 14px; height: 14px; display: block; }
  .row-pop-mark .ic-svg { width: 17px; height: 17px; display: block; }
  /* inline runs — a mark inside a sentence keeps the text baseline, never block */
  .ab-shock-ic { color: var(--ink-warn, var(--warn)); }
  .ab-shock-ic .ic-svg { width: 14px; height: 14px; display: inline-block; vertical-align: -.17em; }
  #action-board .help .tip .ic-svg { width: 12px; height: 12px; display: inline-block; vertical-align: -.14em; }
  /* Lane header — accent top bar via ::before (anv2-lane-hd idiom) */
  .acth { padding: 10px 13px 8px; border-bottom: 1px solid var(--line); position: relative; }
  .acth::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
                  border-radius: 14px 14px 0 0; background: var(--act-accent); }
  .acth-title-row { display: flex; align-items: center; gap: 5px; }
  .acth-icon { display: flex; line-height: 1; flex: none; color: var(--act-accent-ink, var(--act-accent)); }
  .acth-name { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
               color: var(--act-accent-ink, var(--act-accent)); flex: 0 1 auto; min-width: 0;
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .acth-count { flex: none; font-size: 11px; font-weight: 400; color: var(--muted); }
  .acth-count::before { content: "("; } .acth-count::after { content: ")"; }
  .acth-sub { font-size: 10.5px; color: var(--muted); line-height: 1.4; margin-top: 3px; }
  /* Lane body list */
  .actbody { padding: 6px 0; flex: 1; }
  /* V2 row — anv2-row anatomy: name row on top, chips row below, stat line last */
  .actitem { display: block; padding: 7px 13px;
             border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
             font-size: 13px; min-width: 0; overflow: hidden;
             text-decoration: none; color: inherit; cursor: pointer;
             transition: background 0.1s; position: relative; }
  .actitem:last-child { border-bottom: none; }
  .actitem:hover, .actitem:focus { background: color-mix(in srgb, var(--panel2) 55%, transparent); outline: none; }
  .actitem.hovered { background: color-mix(in srgb, var(--panel2) 80%, transparent); }
  .act-row-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
  /* Row kind mark. --muted, not text-at-85%: it is a type label (fund vs basket),
     never a signal, so it must stay subordinate to the name in BOTH themes —
     near-black at .85 on white is a heavier mark than the same rule on dark. */
  .ai-bdg { display: flex; flex: none; color: var(--muted); cursor: default; }
  .act-row-name { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--text);
                  line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* theme composite score — anv2-score idiom (big number, right of the name) */
  .act-row-score { flex: none; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums;
                   white-space: nowrap; }
  .act-score-hi  { color: var(--ink-up, var(--up)); }
  .act-score-mid { color: var(--ink-warn, var(--warn)); }
  .act-score-lo  { color: var(--ink-down, var(--down)); }
  /* V2 stat line — last line of the row; muted label, china-anv2-style colored value
     (var(--up)/var(--down) so the zh red/green flip rides along); hidden on mobile */
  .act-row-stat { display: block; font-size: 10.5px; color: var(--muted); line-height: 1.35; margin-top: 3px;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .act-row-stat .up { color: var(--ink-up, var(--up)); font-weight: 600; }
  .act-row-stat .dn { color: var(--ink-down, var(--down)); font-weight: 600; }
  @media (max-width: 560px) { .act-row-stat { display: none; } }
  .act-row-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; margin-top: 4px; }
  /* V2 action chip — anv2-chip idiom (uppercase 10px, 4px radius) */
  .ab-chip { font-size: 10px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
             padding: 2px 6px; border-radius: 4px; line-height: 15px; white-space: nowrap; flex: none; }
  .ab-chip--warn { background: color-mix(in srgb, var(--warn) 14%, transparent);
                   color: var(--ink-warn, var(--warn)); border: 1px solid color-mix(in srgb, var(--ink-warn, var(--warn)) 28%, transparent); }
  .ab-chip--pos  { background: color-mix(in srgb, var(--up) 14%, transparent);
                   color: var(--ink-up, var(--up)); border: 1px solid color-mix(in srgb, var(--ink-up, var(--up)) 28%, transparent); }
  .ab-chip--neg  { background: color-mix(in srgb, var(--down) 14%, transparent);
                   color: var(--ink-down, var(--down)); border: 1px solid color-mix(in srgb, var(--ink-down, var(--down)) 28%, transparent); }
  .ab-chip--info { background: color-mix(in srgb, var(--info) 14%, transparent);
                   color: var(--ink-info, var(--info)); border: 1px solid color-mix(in srgb, var(--ink-info, var(--info)) 28%, transparent); }
  .ab-chip--muted { background: color-mix(in srgb, var(--muted) 12%, transparent);
                    color: var(--muted); border: 1px solid color-mix(in srgb, var(--muted) 22%, transparent); }
  /* gate-override ✓ pill */
  .ab-chip--gate { background: color-mix(in srgb, var(--up) 10%, transparent);
                   color: var(--ink-up, var(--up)); border: 1px solid color-mix(in srgb, var(--up) 22%, transparent);
                   font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 4px;
                   line-height: 15px; flex: none; cursor: help; }
  /* theme item star/check/lens glyphs */
  .ai-book { flex: none; margin-left: 4px; font-size: 10px; font-weight: 800; cursor: help;
             color: var(--ink-up, var(--up)); white-space: nowrap; }
  .ai-val { flex: none; margin-left: 4px; font-size: 10.5px; font-weight: 800; color: var(--ink-up, var(--up)); cursor: help; }
  .ai-lens { flex: none; margin-left: 4px; font-size: 11px; color: var(--muted); cursor: help; }
  /* theme item name */
  .actitem.ai-theme .act-row-name { font-weight: 700; }
  /* legacy chips kept for non-board uses */
  .ew-chip { display: none; }  /* hidden in V2 board; moved to popover */
  .acttag, .actage, .acteta, .eqmini { display: none; }  /* moved to popover in V2 */
  /* action-board rows opt in to the shared row-pop engine via [data-rpop] */
  /* .notable is its own .panel since 2026-07-11 — panel chrome carries the separation */
  .sm { font-size: 12px; margin: 4px 0; }
  /* keep legacy references alive for non-board code */
  .actitem b { color: var(--text); }

  .gauge { position: relative; height: 10px; border-radius: 5px; margin: 6px 0 2px;
           background: linear-gradient(90deg, var(--down) 0%, var(--g-mid) 50%, var(--up) 100%); opacity:.9; }
  .gauge i { position: absolute; top: -4px; width: 4px; height: 18px; background: var(--text);
             border-radius: 2px; box-shadow: 0 0 0 1px var(--panel); }
  /* crowding gauge: both ENDS are danger zones */
  .pgauge { position: relative; height: 9px; border-radius: 5px; margin: 4px 0 2px;
            background: linear-gradient(90deg, var(--g-cold) 0%, var(--g-mid) 28%, var(--g-mid) 72%, var(--down) 100%);
            opacity: .9; min-width: 130px; }
  .pgauge i { position: absolute; top: -3px; width: 4px; height: 15px; background: var(--text);
              border-radius: 2px; box-shadow: 0 0 0 1px var(--panel); }
  .pends { display: flex; justify-content: space-between; font-size: 10px;
           color: var(--muted); }
  .plabel { display: inline-block; padding: 1px 9px; border-radius: 10px; font-size: 12px;
            font-weight: 600; background: var(--panel2); }
  .plabel-hot { color: var(--ink-down, var(--down)); } .plabel-cold { color: var(--ink-info, var(--info)); }
  .plabel-norm { color: var(--muted); }

  /* regime lifespan bar */
  .lifebar { position: relative; height: 16px; border-radius: 8px; overflow: hidden;
             background: var(--panel2); margin: 8px 0 4px; }
  .lifebar .zone { position: absolute; top: 0; bottom: 0; }
  .lifebar .marker { position: absolute; top: -2px; bottom: -2px; width: 4px;
                     background: var(--text); border-radius: 2px; z-index: 5;
                     box-shadow: 0 0 0 1px var(--panel); }
  .lifelabels { display: flex; justify-content: space-between; font-size: 11px;
                color: var(--muted); }

  /* regime stance verdict: let-winners-run … look-for-a-change */
  .stance { margin: 12px 0 2px; padding: 11px 13px; border-radius: 10px;
            border: 1px solid var(--line); border-left: 3px solid var(--muted);
            background: var(--panel2); }
  .stance-run   { border-left-color: var(--up);
                  background: color-mix(in srgb, var(--up) 7%, var(--panel2)); }
  .stance-hold  { border-left-color: var(--warn);
                  background: color-mix(in srgb, var(--warn) 7%, var(--panel2)); }
  .stance-shift { border-left-color: var(--orange);
                  background: color-mix(in srgb, var(--orange) 8%, var(--panel2)); }
  .stance-reset { border-left-color: var(--info);
                  background: color-mix(in srgb, var(--info) 9%, var(--panel2)); }
  .stance-hd { display: flex; align-items: center; gap: 9px; }
  .stance-ico { font-size: 17px; line-height: 1; flex: none; }
  .stance-v { font-size: 15px; font-weight: 800; letter-spacing: .01em; }
  .stance-sub { font-size: 12px; color: var(--muted); margin-top: 1px; }
  .stance-track { position: relative; height: 9px; border-radius: 5px; margin: 10px 0 0;
                  background: linear-gradient(90deg, var(--up) 0%, var(--warn) 52%, var(--down) 100%);
                  opacity: .9; }
  .stance-track i { position: absolute; top: -4px; width: 4px; height: 17px;
                    background: var(--text); border-radius: 2px; box-shadow: 0 0 0 2px var(--panel); }
  .stance-ends { display: flex; justify-content: space-between; font-size: 10.5px;
                 color: var(--muted); margin-top: 4px; }
  .stance-meta { font-size: 11px; color: var(--muted); margin-top: 6px;
                 font-variant-numeric: tabular-nums; }

  /* next-regime probability bars */
  .prob { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
  .prob .nm { width: 110px; font-weight: 600; font-size: 13px; flex: none; }
  .prob .bar { flex: 1; height: 14px; background: var(--panel2); border-radius: 7px;
               overflow: hidden; }
  .prob .bar i { display: block; height: 100%; border-radius: 7px; }
  .prob .pc { width: 44px; text-align: right; font-weight: 600; flex: none; }

  .legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; font-size: 12px; }
  .legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px;
              margin-right: 5px; vertical-align: -1px; }
  details.howto { margin-top: 10px; }
  details.howto summary { cursor: pointer; color: var(--ink-link, var(--link)); font-size: 13px; }
  details.howto div { background: var(--panel2); border-radius: 8px; padding: 12px 14px;
                      margin-top: 8px; font-size: 13px; line-height: 1.6; }
  ul.compact { margin: 4px 0; padding-left: 18px; } ul.compact li { margin: 3px 0; }

  /* ---- Regime Time Machine -------------------------------------------------- */
  #time-machine .tm-wrap { position: relative; margin: 4px 0 2px; }
  .tm-canvas { display: block; width: 100%; height: 56px; cursor: ew-resize;
               border-radius: 8px; touch-action: none; }
  .tm-range { -webkit-appearance: none; appearance: none; width: 100%; height: 16px;
              background: transparent; margin: 2px 0 0; cursor: ew-resize; }
  .tm-range::-webkit-slider-runnable-track { height: 4px; border-radius: 2px;
              background: var(--line); }
  .tm-range::-moz-range-track { height: 4px; border-radius: 2px; background: var(--line); }
  .tm-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none;
              width: 16px; height: 16px; margin-top: -6px; border-radius: 50%;
              background: var(--text); border: 2px solid var(--panel);
              box-shadow: 0 1px 4px rgba(0,0,0,.35); }
  .tm-range::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%;
              background: var(--text); border: 2px solid var(--panel); }
  .tm-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
                 margin: 8px 0 12px; }
  .tm-presets { display: inline-flex; flex-wrap: wrap; gap: 6px; }
  /* tm-btn — gbtn glass recipe (macro sweep 2026-07) */
  .tm-btn { font: inherit; font-size: 12px; font-weight: 600; color: var(--text);
            background: var(--gbtn-bg); border: 1px solid var(--gbtn-brd); border-radius: 8px;
            -webkit-backdrop-filter: blur(12px) saturate(140%); backdrop-filter: blur(12px) saturate(140%);
            box-shadow: inset 0 1px 0 var(--gbtn-sheen);
            padding: 5px 11px; cursor: pointer;
            transition: border-color .2s ease, background .2s ease, transform .16s ease, box-shadow .25s ease; }
  .tm-btn:hover { border-color: var(--gbtn-brd-hover); background: var(--gbtn-bg-hover); transform: translateY(-1px);
            box-shadow: inset 0 1px 0 var(--gbtn-sheen), 0 8px 20px -10px rgba(3,7,18,.55); }
  .tm-btn:active { transform: translateY(0) scale(.985); box-shadow: inset 0 1px 0 var(--gbtn-sheen); }
  @media (prefers-reduced-motion: reduce){ .tm-btn, .tm-btn:hover, .tm-btn:active { transform: none; } }
  .tm-play { display: inline-flex; align-items: center; gap: 7px; }
  .tm-play-ico { width: 0; height: 0; border-style: solid; border-width: 6px 0 6px 10px;
                 border-color: transparent transparent transparent var(--text);
                 transition: none; }
  .tm-play.is-playing .tm-play-ico { width: 9px; height: 11px; border: none;
                 border-left: 3px solid var(--text); border-right: 3px solid var(--text); }
  .tm-readout { background: var(--panel2); border: 1px solid var(--line); border-radius: 10px;
                padding: 12px 14px; }
  .tm-asof { display: flex; align-items: baseline; gap: 10px; margin-bottom: 9px; }
  .tm-date { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums;
             letter-spacing: .01em; }
  .tm-state-tag { font-size: 11px; font-weight: 700; text-transform: uppercase;
                  letter-spacing: .05em; padding: 2px 8px; border-radius: 10px; }
  .tm-state-tag.is-live { color: color-mix(in srgb, var(--up) 85%, var(--text));
                  background: color-mix(in srgb, var(--up) 16%, var(--panel)); }
  .tm-state-tag.is-hist { color: var(--muted);
                  background: color-mix(in srgb, var(--muted) 16%, var(--panel)); }
  .tm-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
  .tm-gauges { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 22px; margin: 12px 0 4px; }
  @media (max-width: 640px) { .tm-gauges { grid-template-columns: 1fr; } }
  .tm-glabel { display: flex; justify-content: space-between; font-size: 12.5px;
               font-weight: 600; margin-bottom: 2px; font-variant-numeric: tabular-nums; }
  .tm-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
  .tm-flag { font-size: 11.5px; font-weight: 600; padding: 2px 9px; border-radius: 10px;
             background: color-mix(in srgb, var(--c) 16%, var(--panel));
             color: color-mix(in srgb, var(--c) 82%, var(--text)); }
  .tm-nowarn { font-size: 12px; color: var(--muted); }

  /* ---- Sortable / filterable data tables ------------------------------------ */
  table.sortable th.th-sort { cursor: pointer; user-select: none; }
  table.sortable th.th-sort:hover { color: var(--text); }
  table.sortable th .sarrow { font-size: 9px; opacity: .32; margin-left: 3px;
                              font-weight: 700; }
  table.sortable th.sorted { color: var(--text); }
  table.sortable th.sorted .sarrow { opacity: .9; color: var(--ink-link, var(--link)); }
  /* .tbl-filter (live table filter) is styled centrally in theme.css */

  /* ---- hover-to-chart: reveal a definition + mini history on metric hover --- */
  .hovchart { position: relative; cursor: help; border-bottom: 1px dotted var(--muted);
              display: inline-block; }
  .hovchart > .tip { display: none; position: absolute; bottom: 150%; left: 50%;
              transform: translateX(-50%); width: 280px; background: var(--panel);
              border: 1px solid var(--line); padding: 10px 12px; border-radius: 8px;
              z-index: 60; font-size: 12px; line-height: 1.45; color: var(--text);
              text-align: left; font-weight: 400; text-transform: none;
              letter-spacing: normal; box-shadow: var(--popover-shadow);
              pointer-events: none; white-space: normal; }
  .hovchart:hover > .tip { display: block; }
  .hovchart.below > .tip { bottom: auto; top: 150%; }
  .hovchart.edge-right > .tip { left: auto; right: 0; transform: none; }
  .hovchart.edge-left > .tip { left: 0; right: auto; transform: none; }
  .nch { display: block; width: 100%; margin: 7px 0 5px; border-radius: 5px;
         background: var(--panel2); }
  .nph { font-weight: 700; font-size: 12px; }
  .npstat { display: flex; justify-content: space-between; gap: 8px; font-size: 10.5px;
            color: var(--muted); font-variant-numeric: tabular-nums; margin-top: 2px; }
  /* directional trend words next to nowcast metrics */
  .tw { font-size: 11.5px; font-weight: 600; white-space: nowrap; }
  .tw-good { color: var(--ink-up, var(--up)); } .tw-bad { color: var(--ink-orange, var(--orange)); }
  .tw-flat { color: var(--muted); }

  /* ---- collapsed jargon: a compact "details ▾" reveal inside a card --------- */
  .jarg { margin-top: 7px; font-size: 11.5px; }
  .jarg > summary { cursor: pointer; color: var(--ink-link, var(--link)); list-style: none;
                    font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
  .jarg > summary::-webkit-details-marker { display: none; }
  .jarg > summary::after { content: "▾"; font-size: 9px; opacity: .7; }
  .jarg[open] > summary::after { content: "▴"; }
  .jarg .jbody { margin-top: 6px; padding: 8px 10px; background: var(--panel);
                 border: 1px solid var(--line); border-radius: 7px; }
  .jarg .jrow { display: flex; gap: 8px; padding: 3px 0; border-bottom: 1px solid var(--line);
                font-size: 11.5px; }
  .jarg .jrow:last-child { border-bottom: none; }
  .jarg .jrow .jk { flex: none; width: 96px; color: var(--muted); }
  .jarg .jrow .jv { flex: 1; }
  .jarg .jrow .jn { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }

  /* ---- structured tooltip visuals (signal checklist, factor bars, odds) ----- */
  .sigtab { width: 100%; margin: 7px 0 3px; border-collapse: collapse; }
  .sigtab td { padding: 3px 5px; border-bottom: 1px solid var(--line); font-size: 11px;
               vertical-align: middle; }
  .sigtab td:last-child { text-align: right; white-space: nowrap; }
  .sig-on { color: var(--ink-up, var(--up)); font-weight: 700; } .sig-off { color: var(--muted); }
  .fbar { display: grid; grid-template-columns: 74px 1fr 42px; align-items: center;
          gap: 7px; margin: 4px 0; font-size: 11px; }
  .fbar .ft { color: var(--text); } .fbar .fn { text-align: right; font-weight: 700;
          font-variant-numeric: tabular-nums; }
  .fbar .fb { position: relative; height: 8px; background: var(--panel2);
          border-radius: 5px; overflow: hidden; }
  .fbar .fb i { position: absolute; top: 0; bottom: 0; left: 50%; }
  .oddsbar { display: flex; height: 26px; border-radius: 7px; overflow: hidden;
             margin: 8px 0 3px; font-size: 11px; font-weight: 700; }
  .oddsbar .ob-hit { background: color-mix(in srgb, var(--up) 75%, var(--panel));
             color: #fff; display: flex; align-items: center; justify-content: center; }
  .oddsbar .ob-miss { background: var(--panel2); color: var(--muted);
             display: flex; align-items: center; justify-content: center; }
  .ocmp { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 11px; }
  .ocmp .oc-now { color: var(--ink-up, var(--up)); font-weight: 700; }
  .ocmp .oc-alt { color: var(--muted); font-weight: 700; }

  /* ---- standout-stock cards ------------------------------------------------- */
  .nbgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
            gap: 10px; margin-top: 11px; }
  /* mobile: pack the standout cards 2-up so the list doesn't scroll on and on (paired with the
     3-row cap via data-showmore-rows + theme.js). Cards are already overflow-guarded + compact. */
  @media (max-width:680px){
    .nbgrid[data-showmore-rows]{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
    .nbgrid[data-showmore-rows] .nb-tk{ font-size:13px; }
    .nbgrid[data-showmore-rows] .nb-px{ font-size:12px; }
    /* 2-up columns are ~150px: row 1 is just ticker · sector · price. Cap the sector so it fits
       on one line beside them; flex-wrap stays as a last-resort guard against clipping. The name
       lives on the sub-line and shrinks to an ellipsis there. */
    .nbgrid[data-showmore-rows] .nb-top{ flex-wrap:wrap; row-gap:2px; }
    .nbgrid[data-showmore-rows] .nb-nm{ flex:1 1 0; }
    .nbgrid[data-showmore-rows] .nb-sec{ max-width:7.5em; }
    /* 2-up columns are ~150px: the conviction row (score + edge%ile + verdict) would otherwise
       crush the verdict into a ~30px column that wraps every word mid-character. Let the row
       wrap and drop the verdict to its own full-width line (readable whole words). */
    .nbgrid[data-showmore-rows] .nb-conv{ flex-wrap:wrap; row-gap:2px; }
    .nbgrid[data-showmore-rows] .nb-verdict{ flex:1 0 100%; overflow-wrap:normal; word-break:normal; }
    .nbgrid[data-showmore-rows] .nb-edge-pct{ font-size:8.5px; }
  }
  .nbcard { background: var(--panel2); border: 1px solid var(--line); border-radius: 10px;
            padding: 9px 11px 10px; position: relative;
            display: flex; flex-direction: column; gap: 3px; min-width: 0; overflow: hidden;
            transition: transform .12s, box-shadow .12s, border-color .12s;
            color: var(--text); cursor: pointer; }
  /* every flex/grid child may shrink below content width — kills horizontal bleed */
  .nbcard > * { min-width: 0; max-width: 100%; }
  .nbcard:hover { transform: translateY(-2px); box-shadow: 0 5px 18px rgba(0,0,0,.22);
            border-color: var(--link); }
  /* triage accent ring: cards with strong edge + entry open get a subtle highlight (no re-ordering) */
  .nbcard.nb-triage { box-shadow: 0 0 0 2px color-mix(in srgb, var(--up) 55%, transparent),
                      0 2px 8px rgba(0,0,0,.15); }
  /* head-link: the anchor inside the div card; wraps nb-top so Terminal interceptor still fires */
  .nb-head-link { display: block; text-decoration: none; color: inherit; }
  .nb-head-link:hover { text-decoration: none; }
  /* lane sub-heading separators (additive) — LEGACY path, kept byte-identical: an
     artifact with no row.stage still renders the old bottoming/continuation groups. */
  .nb-lane-hd { grid-column: 1 / -1; margin: 6px 0 2px; font-size: 10px; font-weight: 800;
                letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
                padding: 3px 6px; border-bottom: 1px solid var(--line); }

  /* ═══ PROPHET BOARD PRIORITY ENGINE — US board display layer (2026-08-02) ═══
     research/PROPHET_BOARD_PRIORITY_ENGINE_MASTERPLAN_BY_FABLE.md §0 G0.1/G0.4–G0.6.
     Everything below renders ONLY when the artifact carries row.stage; the legacy
     lane-partition path above is untouched so an old artifact renders unchanged.

     ── stage-bucket headings ──────────────────────────────────────────────────
     These replaced the lane headings as the board's PRIMARY structure, so they get
     more presence than .nb-lane-hd had: a coloured left bar plus a tint that fades
     out to the right, instead of a hairline underline. The bar is the non-verbal
     encoding of the bucket (canonized §7 pattern) and the label is the stance —
     "Live now", "Ran — don't chase" are complete instructions on their own; the
     lighter tail sentence is the ≤14-word Tier-1 subtitle. --sgc carries the tone
     so one rule set serves all five buckets. Tones are --pv-* and follow the active
     language convention: green-up/red-down in English, red-up/green-down in Chinese —
     except the two direction-NEUTRAL tones (--pv-wait, --muted), which mean the same
     thing in both and are the right home for a stance with no direction in it. */
  .nb-stage-hd { grid-column: 1 / -1; display: flex; align-items: baseline; flex-wrap: wrap;
                 gap: 3px 9px; margin: 15px 0 4px; padding: 5px 11px 5px 9px;
                 border-left: 3px solid var(--sgc, var(--muted)); border-radius: 0 8px 8px 0;
                 background: linear-gradient(90deg,
                   color-mix(in srgb, var(--sgc, var(--muted)) 12%, transparent), transparent 62%); }
  .nb-stage-hd:first-child { margin-top: 2px; }
  .nb-stage-hd .sh-l { font-size: 11.5px; font-weight: 800; letter-spacing: .05em;
                 text-transform: uppercase;
                 color: color-mix(in srgb, var(--sgc, var(--muted)) 52%, var(--text)); }
  .nb-stage-hd .sh-n { font-size: 10px; font-weight: 800; font-variant-numeric: tabular-nums;
                 padding: 1px 7px; border-radius: 999px;
                 background: color-mix(in srgb, var(--sgc, var(--muted)) 17%, transparent);
                 color: color-mix(in srgb, var(--sgc, var(--muted)) 55%, var(--text)); }
  .nb-stage-hd .sh-s { font-size: 11px; font-weight: 500; color: var(--muted);
                 text-transform: none; letter-spacing: 0; }
  html[data-lang="zh"] .nb-stage-hd .sh-l { letter-spacing: 0; }
  .sg-live       { --sgc: var(--pv-buy); }
  .sg-setting_up { --sgc: var(--pv-near); }
  .sg-ran        { --sgc: var(--muted); }
  /* Basing is the "watch — don't chase" shelf, so it takes the wait tone, not the
     avoid tone it used to inherit by sitting inside Blocked. --pv-wait is amber and
     is deliberately one of the two verb tones the zh 红涨绿跌 block does NOT remap
     (theme.css) — a directionless stance must read the same in both languages. */
  .sg-basing     { --sgc: var(--pv-wait); }
  .sg-blocked    { --sgc: var(--pv-avoid); }

  /* ── stage filter chips (G0.6) ─────────────────────────────────────────────
     Same segmented idiom as the China board's facet bar, with the count pills the
     stage headings use, so the panel counts one way throughout. Real <button>s
     with aria-pressed (a toggle group, not tabs — there is no tabpanel). */
  .pbf-bar { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px; border-radius: 11px;
             background: var(--panel2); border: 1px solid var(--line); margin: 2px 0 12px; }
  .pbf-bar button { font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
             display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
             border: 1px solid transparent; background: transparent; color: var(--muted);
             padding: 6px 13px; border-radius: 8px; line-height: 1.2;
             -webkit-tap-highlight-color: transparent;
             transition: color .14s ease, background .14s ease, border-color .14s ease; }
  .pbf-bar button:hover { color: var(--text); }
  .pbf-bar button:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
  .pbf-bar button[aria-pressed="true"] { background: var(--panel); color: var(--text);
             border-color: var(--line); box-shadow: var(--popover-shadow, 0 1px 3px rgba(0,0,0,.12)); }
  .pbf-n { font-size: 10px; font-weight: 800; font-variant-numeric: tabular-nums;
           padding: 1px 7px; border-radius: 999px;
           background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); }
  .pbf-bar button[aria-pressed="true"] .pbf-n {
           background: color-mix(in srgb, var(--link) 16%, transparent); color: var(--ink-link, var(--link)); }
  @media (max-width: 680px) { .pbf-bar button { min-height: 44px; padding: 6px 14px; font-size: 13px; } }
  /* the polite result announcement — visible to assistive tech only */
  .pbf-live { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
              overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

  /* ---- tier gate (docs/TIER_PREVIEW_PATTERN.md) — preview shell only; hydration
     removes every trace. Controls are baked FULL and marked inert (never omitted —
     the entitled viewer hydrates into the same DOM and would otherwise get no
     filters), per the pattern doc's "Controls" section. */
  .pbf-bar.gated { opacity: .45; pointer-events: none; user-select: none; }
  .us-gate-note { display: flex; align-items: flex-start; gap: 8px; margin: 2px 0 10px;
             padding: 10px 13px; border-radius: 11px; font-size: 12px; line-height: 1.5;
             color: var(--muted); background: color-mix(in srgb, var(--link) 7%, transparent);
             border: 1px solid color-mix(in srgb, var(--link) 20%, transparent); }
  .us-gate-note svg { width: 13px; height: 13px; flex: none; margin-top: 2px; color: var(--link); }
  .pg-more { margin: 6px 2px 2px; font-size: 11.5px; color: var(--muted); }
  .pg-more a { color: var(--link); text-decoration: none; font-weight: 600; }
  .pg-more a:hover { text-decoration: underline; }
  .us-tier-wall { margin: 10px 0 4px; border-radius: 16px; border: 1px solid var(--line);
             background: var(--panel); padding: 22px 24px 20px; text-align: center; }
  .us-tw-h { font-size: 17px; font-weight: 800; letter-spacing: -.01em; color: var(--text); margin-bottom: 8px; }
  .us-tw-p { font-size: 12.5px; line-height: 1.55; color: var(--muted); max-width: 440px; margin: 0 auto 16px; }
  .us-tw-acts { display: flex; flex-direction: column; align-items: center; gap: 8px; }
  .us-tw-btn { display: inline-flex; align-items: center; justify-content: center; padding: 10px 24px;
             border-radius: 11px; text-decoration: none; font-size: 13px; font-weight: 700; color: #fff;
             background: linear-gradient(135deg, var(--link), #8b5cf6); }
  .us-tw-note { font-size: 10.5px; color: var(--faint); }
  .us-tw-signed { margin-top: 10px; font-size: 11.5px; }
  .us-tw-signed a { color: var(--ink-link, var(--link)); text-decoration: none;
             border-bottom: 1px solid color-mix(in srgb, var(--link) 40%, transparent); }

  /* filter visibility. The hide half and the reveal half target DISJOINT sets
     (`:not([data-stage=X])` vs `[data-stage=X]`), so they never fight on specificity.
     The reveal half exists because .sm-hidden is `display:none!important` — without
     it, filtering to a bucket that sits below the show-more fold (Blocked always
     does) would show an EMPTY board. While a bucket is filtered the show-more bar
     is hidden too: its "Showing 12 of 71" counts the unfiltered board. */
  #us-standouts[data-stagef="live"]       [data-stage]:not([data-stage="live"]),
  #us-standouts[data-stagef="setting_up"] [data-stage]:not([data-stage="setting_up"]),
  #us-standouts[data-stagef="ran"]        [data-stage]:not([data-stage="ran"]),
  #us-standouts[data-stagef="basing"]     [data-stage]:not([data-stage="basing"]),
  #us-standouts[data-stagef="blocked"]    [data-stage]:not([data-stage="blocked"]) { display: none !important; }
  #us-standouts[data-stagef="live"]       .sm-hidden[data-stage="live"],
  #us-standouts[data-stagef="setting_up"] .sm-hidden[data-stage="setting_up"],
  #us-standouts[data-stagef="ran"]        .sm-hidden[data-stage="ran"],
  #us-standouts[data-stagef="basing"]     .sm-hidden[data-stage="basing"],
  #us-standouts[data-stagef="blocked"]    .sm-hidden[data-stage="blocked"] { display: flex !important; }
  #us-standouts[data-stagef]:not([data-stagef="all"]) .nb-grid-section .sm-bar { display: none !important; }
  /* P-MP1-SHELL §7 — the lifecycle ladder's filter, SAME idiom as data-stagef above
     (one rule per value; the hide/reveal halves target disjoint sets), keyed on
     data-life instead of data-stage. #us-life-grid is the migrated Setups grid
     (dashboard.html.j2, "us-life-grid" id) — scoped narrower than #us-standouts
     because the Candidates/Groups/Evidence sections on this same panel carry no
     data-life attribute and must never be touched by this filter. */
  #us-standouts[data-lifef="watch"]       #us-life-grid > [data-life]:not([data-life="watch"]),
  #us-standouts[data-lifef="ready"]       #us-life-grid > [data-life]:not([data-life="ready"]),
  #us-standouts[data-lifef="entered"]     #us-life-grid > [data-life]:not([data-life="entered"]),
  #us-standouts[data-lifef="delivering"]  #us-life-grid > [data-life]:not([data-life="delivering"]),
  #us-standouts[data-lifef="overtime"]    #us-life-grid > [data-life]:not([data-life="overtime"]),
  #us-standouts[data-lifef="invalidated"] #us-life-grid > [data-life]:not([data-life="invalidated"]),
  #us-standouts[data-lifef="resolved"]    #us-life-grid > [data-life]:not([data-life="resolved"]) { display: none !important; }
  /* ruling §6 two-total law — "the unfiltered board is the LIVE board": a
     resolved (graded-out) plan renders in the grid so its own terminal-cell
     filter can reach it, but sits OUT of the default/unfiltered view — the
     section total (live) and the grid population must reconcile without it. */
  #us-standouts:not([data-lifef="resolved"]) #us-life-grid > [data-life="resolved"] { display: none !important; }
  /* The reveal half — SAME reason data-stagef needs one above (:not([data-stagef=X])
     alone leaves a matching card that also carries .sm-hidden, tier_preview.js's
     `mx-tier-hidden`, or both hidden by that OTHER rule's own !important). A card the
     ladder filter selects must win over show-more's collapse; it may NOT win over the
     tier lock (a filter is not a paywall bypass), so only .sm-hidden is reversed here. */
  #us-standouts[data-lifef="watch"]       #us-life-grid > .sm-hidden[data-life="watch"],
  #us-standouts[data-lifef="ready"]       #us-life-grid > .sm-hidden[data-life="ready"],
  #us-standouts[data-lifef="entered"]     #us-life-grid > .sm-hidden[data-life="entered"],
  #us-standouts[data-lifef="delivering"]  #us-life-grid > .sm-hidden[data-life="delivering"],
  #us-standouts[data-lifef="overtime"]    #us-life-grid > .sm-hidden[data-life="overtime"],
  #us-standouts[data-lifef="invalidated"] #us-life-grid > .sm-hidden[data-life="invalidated"],
  #us-standouts[data-lifef="resolved"]    #us-life-grid > .sm-hidden[data-life="resolved"] { display: flex !important; }
  #us-standouts[data-lifef] #us-life-grid + .sm-bar { display: none !important; }
  /* ── P-MP1-SHELL §5/§6 — THE LIFECYCLE FACT ROW (.pv-life) + `.pv-mark`
     (template-scoped HERE, not in _prophet_card.html.j2's shared pv_css() —
     that macro is called by hk/china/canada/intl too, and §7/§12 item 3
     require those pages' bytes to stay byte-identical; keeping this CSS
     out of the shared macro is what makes that non-negotiable rather than
     merely tested for).
     .pv-life REPLACES the 4-dot Bottoming/Turning/Ready/Trend rail
     (.pv-stp/.pv-stl) on the lifecycle-sourced call path ONLY (pv_card's
     `lifecycle` param, additive/OFF by default — every existing caller keeps
     the 4-dot rail, §12 acceptance item 3). NAMED .pv-life, not .pv-live —
     that is a DIFFERENT, pre-existing chip (the ◐ intraday chip, P1 spec);
     the two strings are one character apart, do not conflate when editing.
     .pv-mark is THE STATIC LANE CHIP (Amendment 1, P-B5 vocabulary
     resolution) — a different primitive from `.mx-mark` (the six-weight
     lifecycle glyph, theme.css) despite sharing the `mark` word. Keyed on
     `lane` in {bottoming, continuation} ONLY (§12 acceptance item 5). Reuses
     the marks row's established chip geometry (.pv-mk-i) without adopting
     its per-`k` color grammar — a SHAPE fact, not a rank/recency/risk one. */
  .pv-life{display:flex;align-items:center;gap:6px;margin:7px 1px 0;min-width:0}
  .pv-life-w{font-size:10.5px;font-weight:700;color:var(--text);white-space:nowrap}
  .pv-newer{font-size:9.5px;font-weight:700;color:var(--ink-link,var(--info));white-space:nowrap;text-decoration:none;overflow:hidden;text-overflow:ellipsis}
  .pv-newer:hover{text-decoration:underline}
  .pv-mark{display:inline-flex;align-items:center;font-size:9.5px;font-weight:700;line-height:1.45;padding:1px 6px;border-radius:6px;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;color:var(--muted);background:color-mix(in srgb,var(--muted) 10%,transparent);border:1px solid color-mix(in srgb,var(--muted) 22%,transparent);cursor:help}
  /* ── P-MP1-SHELL §4b/§10 — ladder headline/footer wrapper (template-scoped,
     matches MP-1 §9 — theme.css owns only .mx-ladder--board/.mx-cell/.mx-cap/
     .mx-mark/.skel/.mx-error; this surrounding prose chrome is this page's own,
     same convention as .pv-mark/.pv-life above). Geometry ported verbatim from
     the ratified reference (mockups/refs/institutionalize/us_stocks/board.css
     :213-219,383-398,930-931) — gate G-C. */
  .ladder-headline { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 7px; }
  .ladder-n { font-size: 30px; font-weight: 800; letter-spacing: -.035em; line-height: 1;
              font-variant-numeric: tabular-nums; color: var(--text); }
  .ladder-nl { font-size: 14.5px; font-weight: 650; color: var(--text); }
  .ladder-sub { font-size: 11.5px; color: var(--muted); margin-left: 2px; }
  .ladder-absence { margin: 7px 0 0; font-size: 11.5px; color: var(--muted); line-height: 1.5;
              display: flex; align-items: baseline; gap: 7px; }
  .ladder-absence .mx-mark { display: inline-block; transform: translateY(-2px); }
  .ladder-foot { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
              margin: 8px 0 0; font-size: 11.5px; color: var(--muted); line-height: 1.5; }
  .ladder-clear { border: 1px solid var(--line); background: transparent; color: var(--muted);
              border-radius: 999px; padding: 3px 11px; font: inherit; font-size: 11px;
              font-weight: 650; cursor: pointer; }
  .ladder-clear:hover { color: var(--text); border-color: color-mix(in srgb, var(--text) 34%, var(--line)); }
  .sk-n { height: 18px; width: 26px; display: inline-block; }
  .sk-head { height: 30px; width: 62px; display: inline-block; }
  @media (max-width: 720px) {
    .ladder-n { font-size: 27px; }
    .ladder-absence { margin-top: 5px; }
    .ladder-foot { margin-top: 5px; font-size: 11px; }
    .ladder-headline { margin-bottom: 5px; }
  }
  /* ── P-MP1-SHELL §3 — CANDIDATES section anatomy (commissioning follow-up,
     gap 1). Template-scoped for the same reason as the ladder wrapper above:
     the reference calls .mx-sec/.cand-* "NEW primitive, lands in DS-PR-0" but
     it never actually shipped to theme.css. Geometry ported verbatim from
     mockups/refs/institutionalize/us_stocks/board.css:145-161,780-800,1008,1152.
     `.fig` (tabular-nums figure marker) is the reference's own utility class,
     also never shipped to theme.css — ported here rather than left dangling. */
  .fig { font-variant-numeric: tabular-nums; }
  .mx-sec { margin: 24px 0 0; }
  .mx-sec-hd { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
               padding-bottom: 8px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
  .mx-sec-h2 { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: .085em;
               text-transform: uppercase; color: var(--text); }
  .mx-sec-total { font-size: 12.5px; color: var(--muted); font-weight: 600; }
  .mx-sec-total b { color: var(--text); font-weight: 800; font-variant-numeric: tabular-nums; }
  .mx-sec-link { margin-left: auto; font-size: 11.5px; color: var(--ink-link); text-decoration: none; font-weight: 650; }
  .mx-sec-link:hover { text-decoration: underline; }
  .mx-sec-note { font-size: 11.5px; color: var(--muted); line-height: 1.5; margin: -6px 0 14px; }
  .cand-shelves { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 13px; }
  .cand-shelf { display: inline-flex; align-items: baseline; gap: 7px; padding: 6px 12px;
                border: 1px solid var(--line); border-radius: 999px;
                background: color-mix(in srgb, var(--panel2) 65%, transparent);
                font-size: 11.5px; font-weight: 650; color: var(--muted); }
  .cand-shelf b { color: var(--text); font-weight: 800; font-variant-numeric: tabular-nums; font-size: 12.5px; }
  .cand-shelf i { font-style: normal; font-size: 10px; opacity: .8; }
  .cand-rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 8px; }
  .cand-row { display: flex; align-items: baseline; gap: 8px; padding: 8px 11px;
              border: 1px solid var(--line); border-radius: 9px; background: var(--panel);
              font-size: 12px; min-width: 0; }
  .cand-tk { font-weight: 800; font-size: 12.5px; flex: none; }
  .cand-nm { color: var(--muted); font-size: 10.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cand-px { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 11.5px; flex: none; }
  @media (max-width: 720px) {
    .mx-sec { margin: 12px 0 0; }
    .mx-sec-hd { padding-bottom: 5px; margin-bottom: 7px; }
    .cand-rows { grid-template-columns: 1fr; }
  }
  /* NOTE: the `.pbf-empty` rules that used to sit here were removed 2026-08-02 — no
     template, macro or script has ever emitted that class, so the "honest emptiness"
     note they styled never rendered. It cannot render either: a bucket with zero rows
     emits no filter chip at all (the chip row is gated on its own count), so there is
     no way to filter INTO an empty bucket from this surface. Dead CSS on a stylesheet
     that ships on every render reads at review like a shipped feature. */

  /* ── ran section (G0.4 display) ────────────────────────────────────────────
     Deliberately NOT a fourth table: two tables already follow this panel, and the
     ran lane is a "these are gone" list, not a comparison. Quiet one-line rows,
     panel-tinted rather than panel-filled, so they read as visible-but-not-entries. */
  .pbr { margin-top: 17px; }
  .pbr-hd { display: flex; align-items: baseline; flex-wrap: wrap; gap: 3px 9px; }
  .pbr-t { font-size: 11.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
           color: var(--muted); }
  html[data-lang="zh"] .pbr-t { letter-spacing: 0; }
  .pbr-n { font-size: 10px; font-weight: 800; font-variant-numeric: tabular-nums;
           padding: 1px 7px; border-radius: 999px;
           background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); }
  .pbr-s { font-size: 11px; color: var(--muted); line-height: 1.5; margin: 4px 0 8px; }
  .pbr-l { display: flex; flex-direction: column; gap: 5px; }
  .pbr-r { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 9px; padding: 6px 10px;
           border: 1px solid var(--line); border-radius: 8px; text-decoration: none;
           background: color-mix(in srgb, var(--panel2) 45%, transparent);
           color: var(--text); font-size: 11px; min-width: 0; }
  .pbr-r:hover { border-color: color-mix(in srgb, var(--muted) 45%, var(--line)); }
  .pbr-tk { font-weight: 800; font-size: 11.5px; flex: none; }
  .pbr-nm { color: var(--muted); min-width: 0; flex: 1 1 7em;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .pbr-m { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; flex: none; }
  /* `az-up`/`az-dn` are semantic-only class names in this file — every existing use
     pairs them with a scoped colour rule (.nb-az.az-up, .oc-pct.az-up, .ts-tbl td.az-up)
     and there is no bare .az-up rule to inherit, so this one is required or the move
     since the signal renders colourless.  --up/--down (NOT --pv-*) is correct here:
     this IS a directional figure, so it must flip red/green under html[data-lang="zh"]. */
  .pbr-m .az-up { color: var(--ink-up, var(--up)); font-weight: 700; }
  .pbr-m .az-dn { color: var(--ink-down, var(--down)); font-weight: 700; }
  /* theme_confirmed: the name's own signal is old but its THEME only just turned.
     A touch of warmth — an amber wash and one amber line — deliberately a quieter
     register than the featured aura, which stays the board's only green glow. */
  .pbr-r.pbr-warm { border-color: color-mix(in srgb, var(--warn) 34%, var(--line));
           background: linear-gradient(90deg, color-mix(in srgb, var(--warn) 10%, transparent),
                       transparent 58%), color-mix(in srgb, var(--panel2) 45%, transparent); }
  .pbr-wl { flex: 1 1 100%; font-size: 10.5px; font-weight: 700;
            color: color-mix(in srgb, var(--warn) 60%, var(--text)); }
  /* board order / priority framing footnote */
  .pb-fn { margin: 9px 0 0; font-size: 11px; color: var(--muted); line-height: 1.55; }
  /* ═══ W-L1 BOARD STATE STAMP ═══════════════════════════════════════════════
     Contract: research/WL1_PROVISIONAL_BOARD_DESIGN_SPEC.md §4.2.
     ONE axis, asked once: where does this board stand relative to the nightly board
     of record?
       data-boardstate="ahead"   provisional blue, DASHED — built from today's close;
                                 the overnight pass has not countersigned it
       data-boardstate="behind"  muted, SOLID            — the record did not arrive
                                 (or the market is shut); this is the last confirmed board
       attribute ABSENT          no stamp at all         — the board IS the record
     Absence is the third state and it is load-bearing: a reader never has to read a
     badge to learn that nothing is unusual.
     Dashed=pending is not invented here — .pv-trg-soon already ships it for the
     'imminent' trigger chip; the blue is the P1 .pv-live hue (--prov, theme.css §4.1)
     reused ON PURPOSE, because the ◐ strip and this stamp name the same epistemic tier. */
  .pbs { display: inline-flex; align-items: center; gap: 5px; font-size: 10px; font-weight: 800;
         letter-spacing: .06em; text-transform: uppercase; line-height: 1.35; padding: 2.5px 9px;
         border-radius: 6px; white-space: nowrap; flex: none; }
  /* squarer than the board's 999px pills on purpose: this is a stamp on the whole board,
     not another chip in the chip row. 6px matches the .pv-mk marks family. */
  .pbs-ahead { color: var(--prov-ink); background: color-mix(in srgb, var(--prov) 11%, transparent);
               border: 1px dashed color-mix(in srgb, var(--prov) 62%, transparent); }
  .pbs-behind { color: var(--muted); background: color-mix(in srgb, var(--muted) 9%, transparent);
                border: 1px solid color-mix(in srgb, var(--muted) 34%, transparent); }
  .pbs-dt { font-variant-numeric: tabular-nums; }
  .pbs[hidden] { display: none; }   /* a class-level display out-specifies the UA [hidden] rule
                                       — the .pv-live[hidden] trap, one line earlier this time */
  /* THE UNSEALED EDGE — the one place this design spends boldness.
     A board-level state has to survive a full-page scroll-past, and the house has already
     measured that a rim treatment ALONE does not (see the .pv-featured note in
     _prophet_card.html.j2). So the panel's own top edge goes perforated while the board is
     uncountersigned. Long dash (15/9), never a fine dot — a fine dotted line reads as a
     broken border, a long dash reads as a deliberate perforation. Costs zero height: it
     rides the existing 1px border.
     Static by choice: 15 cards and a strip that already animates its rows in are enough
     movement on this page, so there is no animation here and therefore no
     prefers-reduced-motion kill block to keep in sync (the strongest form of that
     compliance is having nothing to disable). If motion is ever added here, the kill block
     must name ::before explicitly. */
  .panel[data-boardstate] { position: relative; }
  .panel[data-boardstate="ahead"]::before {
    content: ""; position: absolute; left: -1px; right: -1px; top: -1px;
    height: 2px; border-radius: 14px 14px 0 0; pointer-events: none;
    background: repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--prov) 78%, transparent) 0 15px, transparent 15px 24px); }
  /* SLOT B — one line under the header. Four mutually exclusive contents (provisional
     stance / confirmation receipt / last-confirmed stance / markets-closed stance), never
     two at once, so the header height moves by at most a rounding wobble and the board
     below never shoves. NOT a second footnote: .pb-fn stays the panel's single permanent
     methodology note (doctrine Law 4).
     Deliberately NOT .nb-stale-note's amber-on-tint banner: quiet honesty, not a caution —
     no fill, no border, muted ink.
     min-height RESERVES the slot (the .pv-mk precedent). The evening state arrives on the
     live plane under a reader who is already looking at the board, so the slot has to hold
     its line BEFORE the payload lands or the flip shoves the grid; an empty slot is
     therefore exactly as tall as a one-line slot.
     text-wrap:pretty is load-bearing, not polish: without it the trailing `?` help icon
     wrapped alone onto a second line on the two longest notes, and that ALSO cost 18.8px
     of header height on those states — measured 18.8px spread before, 1.5px after. */
  .pbs-note { font-size: 11.5px; line-height: 1.5; margin: 7px 0 1px; color: var(--muted);
              max-width: 94ch; min-height: 1.5em; text-wrap: pretty; }
  .pbs-note b { font-weight: 700; color: var(--text); }
  .pbs-fig { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }
  .pbs-note .help { margin-left: 5px; vertical-align: 1px; }
  .pbs-nv[hidden] { display: none; }
  /* ── W-L1d — WHAT THE PROVISIONAL BOARD PUTS AWAY ──────────────────────────────
     While tonight's cards are mounted, the nightly grid, its show-more bar, the stage
     filter and the grid/table toggle are all hidden: each of them is a view of columns
     this board deliberately does not carry (spec §10.3 — "a filter over absent buckets
     is a broken control", and the table has a whole score column with nothing to put in
     it). Nothing is emptied or rebuilt — hiding is the entire mechanism, so restoring is
     one attribute per element and the nightly board can never come back half-swapped.

     It has to be a RULE and not an inline style for two independent reasons: a
     class-level `display` out-specifies the UA [hidden] rule (the .pv-live[hidden] trap,
     fifty lines up), AND show-more's own reflow pass rewrites .sm-bar's INLINE display
     whenever the column count changes — so a resize would silently un-hide a bar that is
     counting the wrong board. This is the whole CSS cost of W-L1d; the cards themselves
     add none (spec §10.2). */
  #us-standouts .nbgrid[hidden], #us-standouts .sm-bar[hidden],
  #us-standouts .pbf-bar[hidden], #us-standouts .st-view-toggle[hidden],
  #us-standouts #us-board-sub[hidden], #us-standouts .pb-fn[hidden] { display: none !important; }
  /* ── THE CHIP RAIL — W-L1d's one geometric decision ────────────────────────────
     The evening payload carries NO sparkline, on purpose: the sparks are 86% of the
     artifact on a 120-second poll for a key that changes once a day, and an evening spark
     would draw bandless anyway because the buy-zone band derives from the omitted `entry`
     leg. So .pv-nochart's 74px reserves a chart that is not coming to THIS card — the
     chart comes with the morning board — and an empty 74px hue wash with two chips
     floating at the top of it reads exactly like an image that failed to load. Measured
     on the real page before this rule existed, and it is the reason the rule exists.

     Collapsing it to the chip rail's own height is the honest geometry AND the design:
     the evening card is deliberately lighter than the morning card at every slot — no
     score, no stage rail, no marks, no zone range, and now no chart — so a reader can see
     at a glance that this board is holding less back than it is holding out. Do not fill
     this space with a meter, a bar or a runway gauge: the lane owns two legs, both of
     them already have a word on the card, and anything else here would be ornament
     invented to cover an absence (§10.4 — the absence is the point).

     Scoped to [data-provboard] so the nightly card, which does have a chart, never sees
     it. 8px clears .pv-ov's own top offset above the chip and leaves the same below. */
  #us-standouts .nbgrid[data-provboard] .pv-nochart { height: 36px; }
  @media (max-width: 680px) {
    .pbs { font-size: 9.5px; padding: 2px 7px; }
    .pbs-note { font-size: 11px; }
    /* At this width the header row's free space is measured in characters. The EN subtitle
       is long enough to sit on its own line already, in every state — but the ZH one fits
       beside the title until the stamp arrives and pushes it down, which moved the whole
       card grid 25.25px UNDER A READER at exactly the moment the evening state landed
       (measured, verify_wl1.py). Pinning the subtitle to its own line makes the header's
       LINE COUNT independent of whether a stamp is present, which is what the invariance
       gate is actually asking for, and it makes ZH behave the way EN already does here. */
    .pb-hdrow > .muted { flex: 1 0 100%; }
  }
  /* per-card expander toggle bar */
  .nb-more-btn { display: flex; align-items: center; justify-content: center; gap: 4px;
                 width: 100%; margin-top: 4px; padding: 4px 0; min-height: 32px;
                 border: none; background: transparent; cursor: pointer;
                 font-size: 9px; font-weight: 700; letter-spacing: .03em;
                 color: var(--muted); border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
                 border-radius: 0; }
  .nb-more-btn:hover { color: var(--ink); }
  /* Per-card detail — anchored dropdown POPOVER (was an inline expand-in-place).
     At rest the content is DOM-present but hidden (contract: server-rendered-but-collapsed).
     When the card is open, .nb-more becomes a FIXED floating panel whose top/left the toggle
     JS computes from the button rect (flip-up / clamp-to-edge). position:fixed is deliberate:
     it escapes the card's overflow:hidden clip AND the hover-transform containing-block trap. */
  .nb-more { display: none; margin-top: 4px; }
  .nbcard.nb-open { transform: none; }   /* kill hover lift so fixed coords stay viewport-true */
  .nbcard.nb-open .nb-more {
    display: block; margin: 0; position: fixed; z-index: 200;
    width: min(360px, calc(100vw - 20px));
    max-height: min(72vh, 560px); overflow-y: auto; overscroll-behavior: contain;
    padding: 12px 13px 13px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    box-shadow: 0 1px 2px rgba(0,0,0,.10), 0 18px 46px -12px rgba(0,0,0,.55),
                0 0 0 1px color-mix(in srgb, var(--link) 12%, transparent);
    animation: nbMorePop .13s ease-out;
  }
  @keyframes nbMorePop { from { opacity: 0; transform: translateY(-7px) scale(.985); }
                         to   { opacity: 1; transform: translateY(0) scale(1); } }
  /* sticky close (×), pinned to the popover's top-right even while its body scrolls */
  .nb-more-x { position: sticky; top: -2px; float: right; z-index: 1;
               margin: -4px -5px 2px 8px; width: 26px; height: 26px;
               display: flex; align-items: center; justify-content: center;
               border: none; border-radius: 7px; background: var(--panel); color: var(--muted);
               font-size: 18px; line-height: 1; cursor: pointer; }
  .nb-more-x:hover { color: var(--text); background: color-mix(in srgb, var(--line) 55%, transparent); }
  /* state accent as a TOP gradient stripe (RIPENING-shelf idiom) — not a left border */
  .nbcard::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; pointer-events: none;
                    background: linear-gradient(90deg, var(--muted), transparent); opacity: .6; }
  .nbcard.nb-up::before { background: linear-gradient(90deg, var(--up), color-mix(in srgb, var(--up) 30%, transparent)); opacity: 1; }
  .nbcard.nb-down::before { background: linear-gradient(90deg, var(--down), color-mix(in srgb, var(--down) 30%, transparent)); opacity: 1; }
  .nbcard.nb-caution::before { background: linear-gradient(90deg, var(--warn), color-mix(in srgb, var(--warn) 30%, transparent)); opacity: 1; }
  .nb-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 3px; }
  .nb-tk { font-weight: 800; font-size: 14px; color: var(--text); letter-spacing: .01em; flex: none; }
  .nb-nm { font-size: 10px; color: var(--muted); overflow: hidden; text-overflow: ellipsis;
           white-space: nowrap; flex: 1 1 auto; min-width: 0; }
  /* price PINNED right + never shrinks → the old "chips shove the price past the card's
     clipped edge" bug is structurally impossible now (chips live in .nb-tags below). */
  .nb-px { font-weight: 700; font-size: 13px; color: var(--text); flex: none; margin-left: auto;
           font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* row-1 sector/theme identity chip (sits next to the ticker — the ONE place the theme name
     shows now). Borrows .nb-spot colour/link styling; this only resets margin + caps width.
     Scoped to .nb-top so it out-specifies .nb-spot's own margin/max-width (defined later).
     11em fits every shortened label whole (row 1 is just ticker · sector · price now). */
  .nb-top .nb-sec { flex: none; max-width: 11em; margin: 0; }
  .nb-sec .sp-tag { overflow: hidden; text-overflow: ellipsis; }
  .nb-sec .sp-ar { flex: none; font-size: 8px; opacity: .9; }
  .nb-sec-plain { font-size: 9.5px; font-weight: 700; color: var(--muted); max-width: 7.5em;
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* status/label chips relocated off the single-line top row into their own wrapping band, so a
     busy card wraps its chips downward instead of clipping the price. "labels under the ticker".
     Named .nb-chiprow (not .nb-tags) — .nb-tags already exists for the news-headline pills. */
  .nb-chiprow { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 1px 0 0; min-width: 0; }
  .nb-sub { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 10px;
            color: var(--muted); min-width: 0; }
  .nb-gics { color: var(--muted); opacity: .85; white-space: nowrap; overflow: hidden;
             text-overflow: ellipsis; max-width: 100%; }
  .nb-offh { margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
  /* one shared legend under the section header — replaces the identical per-card
     trust-tier + percentile-rank caveat that used to repeat on all ~140 cards */
  .nb-legend { display: flex; flex-wrap: wrap; align-items: baseline; gap: 5px 10px;
               margin: 6px 0 2px; padding: 6px 11px; border-radius: 9px; font-size: 11px;
               line-height: 1.45; color: var(--muted); background: var(--panel);
               border: 1px solid var(--line); }
  .nb-legend .lg-k { font-weight: 800; color: var(--ink); letter-spacing: .01em; }
  .nb-legend b { font-weight: 700; color: var(--ink); }
  .nb-legend .lg-sep { color: var(--line); }
  .nb-spark { width: 100%; height: 42px; border-radius: 5px; }
  .nbcard .nch { background: transparent; margin: 4px 0 2px; }
  .nb-bot { display: flex; align-items: center; flex-wrap: wrap; gap: 3px 6px; margin-top: 1px; font-size: 10px; }
  .nb-state { font-size: 10px; font-weight: 800; letter-spacing: .02em; padding: 1px 7px;
              border-radius: 8px; }
  .nb-up .nb-state { color: var(--ink-up, var(--up)); background: color-mix(in srgb, var(--up) 15%, var(--panel)); }
  .nb-down .nb-state { color: var(--ink-down, var(--down)); background: color-mix(in srgb, var(--down) 15%, var(--panel)); }
  .nb-caution .nb-state { color: var(--ink-warn, var(--warn)); background: color-mix(in srgb, var(--warn) 15%, var(--panel)); }
  .nb-score { font-size: 11px; font-weight: 800; margin-left: auto;
              font-variant-numeric: tabular-nums; }
  .nb-score.s-up { color: var(--ink-up, var(--up)); } .nb-score.s-down { color: var(--ink-down, var(--down)); }
  .nb-score.s-flat { color: var(--muted); }
  .nb-meta { display: flex; align-items: center; gap: 7px; font-size: 10px;
             color: var(--muted); margin-top: 1px; }
  .nb-eta { font-weight: 700; color: var(--g-cold); }
  .nb-grade { font-weight: 700; }
  /* sector-neutral momentum (alpha) line on each standout card */
  .nb-alpha { display: flex; align-items: center; gap: 6px; font-size: 9.5px;
              margin-top: 2px; flex-wrap: wrap; }
  .nb-az { font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
           padding: 0 5px; border-radius: 7px; background: var(--panel);
           border: 1px solid var(--line); color: var(--muted); }
  .nb-az.az-up { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--ink-up, var(--up)) 38%, var(--line)); }
  .nb-az.az-dn { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--ink-down, var(--down)) 38%, var(--line)); }
  .nb-rk { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .nb-comp { font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
             padding: 0 5px; border-radius: 7px; background: var(--panel);
             border: 1px solid var(--line); color: var(--muted); cursor: help; }
  .nb-comp.cmp-pos { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 38%, var(--line)); }
  .nb-comp.cmp-neg { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 38%, var(--line)); }
  .nb-size { font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
             padding: 0 5px; border-radius: 7px; background: var(--panel);
             border: 1px solid var(--line); color: var(--muted); cursor: help; }
  .nb-size.sz-up { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 38%, var(--line));
                   background: color-mix(in srgb, var(--up) 8%, var(--panel)); }
  .nb-size.sz-dn { color: var(--ink-warn, var(--warn, #c79a2e)); border-color: color-mix(in srgb, var(--warn, #c79a2e) 42%, var(--line));
                   background: color-mix(in srgb, var(--warn, #c79a2e) 8%, var(--panel)); }
  .nb-disp { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
             margin: 2px 0 10px; padding: 6px 11px; border-radius: 9px; font-size: 11.5px;
             background: var(--panel); border: 1px solid var(--line); cursor: help; }
  .nb-disp b { font-weight: 800; }
  .nb-disp .disp-ic { font-size: 13px; }
  .nb-disp .disp-meta { color: var(--muted); font-size: 10.5px; font-variant-numeric: tabular-nums;
                        margin-left: auto; }
  .nb-disp.disp-lean_in { border-color: color-mix(in srgb, var(--up) 42%, var(--line));
                          background: color-mix(in srgb, var(--up) 7%, var(--panel)); }
  .nb-disp.disp-lean_in b { color: var(--ink-up, var(--up)); }
  .nb-disp.disp-lean_out { border-color: color-mix(in srgb, var(--warn, #c79a2e) 42%, var(--line));
                           background: color-mix(in srgb, var(--warn, #c79a2e) 7%, var(--panel)); }
  .nb-disp.disp-lean_out b { color: var(--ink-warn, var(--warn, #c79a2e)); }
  .nb-ent { font-weight: 700; padding: 0 5px; border-radius: 7px; }
  .ent-good { color: var(--ink-up, var(--up)); background: color-mix(in srgb, var(--up) 14%, var(--panel)); }
  /* dark-zh: 红涨绿跌 makes this a red-on-red-tint pair, which lands at 4.41:1 on
     the 14% tint (green clears easily; red sits lower in the dark). Thinning the
     tint to 8% is the W3 lever — the ink stays vivid, dark-EN is untouched. */
  html[data-lang="zh"]:not([data-theme="light"]) .ent-good { background: color-mix(in srgb, var(--up) 8%, var(--panel)); }
  .ent-warn { color: var(--ink-warn, var(--warn)); background: color-mix(in srgb, var(--warn) 16%, var(--panel)); }
  /* insider Form-4 buy-cluster confirmer chip */
  .nb-ins { font-weight: 800; padding: 0 5px; border-radius: 7px; color: var(--ink-up, var(--up));
            background: color-mix(in srgb, var(--up) 13%, var(--panel)); white-space: nowrap; }
  .ts-ins { font-weight: 800; font-size: 10px; color: var(--ink-up, var(--up)); white-space: nowrap;
            padding: 0 4px; border-radius: 6px;
            background: color-mix(in srgb, var(--up) 13%, var(--panel)); }
  /* theme/sector SPOTLIGHT tilt chip (engine.spotlight) — narrative alignment of the pick.
     A small, declared nudge: it re-orders within a tier, never overrides the risk vetoes. */
  .nb-spot { display: inline-flex; align-items: center; gap: 4px; font-size: 9.5px; font-weight: 700;
             padding: 1px 6px; border-radius: 7px; margin: 3px 0 0; white-space: nowrap; max-width: 100%;
             overflow: hidden; text-overflow: ellipsis; border: 1px solid var(--line);
             color: var(--muted); background: var(--panel); text-decoration: none; }
  .nb-spot-link { cursor: pointer; }
  .nb-spot-link:hover { filter: brightness(1.08); border-color: currentColor; }
  .nb-spot.spot-up { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 40%, var(--line));
                     background: color-mix(in srgb, var(--up) 11%, var(--panel)); }
  .nb-spot.spot-dn { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 32%, var(--line));
                     background: color-mix(in srgb, var(--down) 10%, var(--panel)); }
  .nb-spot .sp-tag { overflow: hidden; text-overflow: ellipsis; }
  /* ---- sector-pulse heat chip on standout cards (DISPLAY-ONLY, no rank power) ---- */
  .nb-pulse-heat { display: inline-flex; align-items: center; gap: 3px; font-size: 9px; font-weight: 700;
                   padding: 1px 6px; border-radius: 7px; white-space: nowrap; max-width: 9em;
                   overflow: hidden; text-overflow: ellipsis; border: 1px solid var(--line);
                   color: var(--muted); background: var(--panel); cursor: help; flex: none; }
  .nb-pulse-heat.ph-heating { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 38%, var(--line));
                              background: color-mix(in srgb, var(--up) 10%, var(--panel)); }
  .nb-pulse-heat.ph-hot { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 55%, var(--line));
                          background: color-mix(in srgb, var(--up) 15%, var(--panel)); font-weight: 800; }
  .nb-pulse-heat.ph-cooling { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 32%, var(--line));
                              background: color-mix(in srgb, var(--down) 9%, var(--panel)); }
  .nb-pulse-heat.ph-broken { color: var(--muted); border-color: var(--line); opacity: .75; }
  /* ---- unified Conviction Profile on each standout card ---------------- */
  .nb-conv { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; row-gap: 3px; margin: 3px 0 1px; min-width: 0; }
  .nb-cscore { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums;
               min-width: 30px; flex: none; text-align: center; padding: 1px 5px; border-radius: 8px;
               border: 1px solid var(--line); color: var(--ink); }
  .nb-cscore.band-high { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 45%, var(--line));
                         background: color-mix(in srgb, var(--up) 12%, var(--panel)); }
  .nb-cscore.band-constructive { color: var(--g-cold);
                         border-color: color-mix(in srgb, var(--g-cold) 40%, var(--line)); }
  .nb-cscore.band-neutral { color: var(--muted); }
  .nb-cscore.band-low { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 35%, var(--line)); }
  /* verdict on its OWN full-width line + break only at spaces (no more "Constructi-ve"
     mid-word chop). It has the whole card width here, so it reads as whole words. */
  .nb-verdict { font-size: 10.5px; font-weight: 700; line-height: 1.3; color: var(--ink);
                flex: 1 0 100%; min-width: 0; overflow-wrap: normal; word-break: normal; hyphens: none; }
  .nb-val { flex: none; }
  /* edge percentile: a compact 2-line stacked chip ("Edge" / "NN%ile"), colour-tiered so a
     top-decile edge (≥80) reads green at a glance. Hover = what it means (data-tip). */
  .nb-edge-pct { display: inline-flex; flex-direction: column; align-items: center; flex: none;
                 line-height: 1.05; padding: 1px 6px; border-radius: 7px; cursor: help;
                 border: 1px solid var(--line); background: var(--panel);
                 font-variant-numeric: tabular-nums; text-align: center; }
  .nb-edge-pct .ep-k { font-size: 7px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
  .nb-edge-pct .ep-v { font-size: 11px; font-weight: 800; color: var(--ink); white-space: nowrap; }
  .nb-edge-pct .ep-u { font-size: 7px; font-weight: 700; color: var(--muted); margin-left: 1px; }
  .nb-edge-pct.edge-hi { border-color: color-mix(in srgb, var(--up) 55%, var(--line));
                         background: color-mix(in srgb, var(--up) 12%, var(--panel)); }
  .nb-edge-pct.edge-hi .ep-v { color: var(--ink-up, var(--up)); }
  .nb-edge-pct.edge-hi .ep-k { color: color-mix(in srgb, var(--up) 65%, var(--muted)); }
  .nb-edge-pct.edge-lo { opacity: .82; }
  .nb-edge-pct.edge-lo .ep-v { color: var(--muted); }
  /* multi-timeframe bottoming-alignment chip (weekly+3d+daily turning up) */
  .nb-align { display: flex; align-items: center; gap: 5px; margin: 2px 0 1px; min-width: 0;
              font-size: 9.5px; font-weight: 700; letter-spacing: .01em;
              padding: 2px 7px; border-radius: 7px; border: 1px solid var(--line);
              color: var(--ink-up, var(--up)); background: color-mix(in srgb, var(--up) 9%, var(--panel)); }
  .nb-align.nba-near { color: var(--ink-warn, var(--warn)); background: color-mix(in srgb, var(--warn) 9%, var(--panel)); }
  .nb-align .nba-line { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .nb-align .nba-tag { margin-left: auto; flex: none; font-size: 8px; font-weight: 800;
                       text-transform: uppercase; letter-spacing: .04em; opacity: .85; }
  .nb-axes { display: flex; gap: 4px; margin-top: 2px; }
  .nb-ax { flex: 1; }
  .nb-ax .axl { font-size: 8px; color: var(--muted); letter-spacing: .03em; }
  .nb-ax .axt { height: 3px; border-radius: 2px; background: var(--line); margin-top: 1px; overflow: hidden; }
  .nb-ax .axf { height: 100%; background: var(--g-cold); border-radius: 2px; }
  .nb-ax.ax-na .axf { background: transparent; }
  /* ---- Caution icon + popover (replaces old pill-row) ---- */
  .nb-cau { position: relative; display: inline-flex; }
  .nb-cau-btn {
    display: inline-flex; align-items: center; gap: 3px;
    padding: 0 5px 0 4px; height: 18px; border-radius: 9px; border: none; cursor: pointer;
    font-size: 9px; font-weight: 700; line-height: 1;
    color: var(--ink-warn, var(--warn)); background: color-mix(in srgb, var(--warn) 14%, var(--panel));
    text-decoration: none;
    animation: nb-cau-pulse 2.5s ease-in-out infinite;
  }
  @media (prefers-reduced-motion: reduce) { .nb-cau-btn { animation: none; } }
  @keyframes nb-cau-pulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: .55; }
  }
  .nb-cau-badge {
    display: inline-flex; align-items: center; justify-content: center;
    width: 13px; height: 13px; border-radius: 50%; font-size: 8px; font-weight: 800;
    background: var(--warn); color: var(--panel);
  }
  .nb-cau-pop {
    display: none; position: absolute; z-index: 120; bottom: calc(100% + 5px); left: 0;
    min-width: 180px; max-width: min(260px, calc(100vw - 24px));
    padding: 7px 9px; border-radius: 8px;
    background: var(--panel); border: 1px solid color-mix(in srgb, var(--warn) 40%, var(--line));
    box-shadow: 0 4px 16px rgba(0,0,0,.18);
    font-size: 10px; font-weight: 600; line-height: 1.45; color: var(--ink-warn, var(--warn));
    pointer-events: none;
  }
  .nb-cau-pop .cau-row { display: block; padding: 2px 0; }
  .nb-cau-pop .cau-row + .cau-row { border-top: 1px solid color-mix(in srgb, var(--warn) 20%, var(--line)); padding-top: 4px; margin-top: 2px; }
  /* display-only (unvalidated) folded rows — Options/IV positioning — read muted vs real cautions */
  .nb-cau-pop .cau-row.cau-unval { color: var(--muted); font-weight: 500; }
  /* Show on hover/focus (desktop) */
  .nb-cau:hover .nb-cau-pop,
  .nb-cau:focus-within .nb-cau-pop,
  .nb-cau.nb-cau-open .nb-cau-pop { display: block; pointer-events: auto; }
  /* Flip to below if near top of viewport (added by JS) */
  .nb-cau.pop-below .nb-cau-pop { bottom: auto; top: calc(100% + 5px); }
  /* Clamp to right edge */
  .nb-cau.pop-right .nb-cau-pop { left: auto; right: 0; }
  /* The card clips overflow; release it while the popover is showing or the top of a
     tall popover is cut off at the card edge */
  .nbcard:has(.nb-cau:hover), .nbcard:has(.nb-cau:focus-within),
  .nbcard:has(.nb-cau-open) { overflow: visible; }
  .nb-tier { font-size: 8px; color: var(--muted); margin-top: 3px; letter-spacing: .02em; }
  /* ---- Entry-timing gauge (the SECOND gauge: "buy now / wait / extended") ---- */
  .nb-entry { margin: 3px 0 1px; padding: 4px 7px; border-radius: 8px;
              background: var(--panel); border: 1px solid var(--line);
              border-top: 2px solid var(--muted); }
  .nbe-buy_now, .nbe-partial { border-top-color: var(--up);
              background: color-mix(in srgb, var(--up) 8%, var(--panel)); }
  .nbe-buy_soon, .nbe-watch, .nbe-await_confluence { border-top-color: var(--g-cold); }
  .nbe-wait_pullback, .nbe-hold, .nbe-bounce_wait { border-top-color: var(--warn); }
  .nbe-extended, .nbe-topping { border-top-color: var(--warn);
              background: color-mix(in srgb, var(--warn) 9%, var(--panel)); }
  .nbe-exit, .nbe-avoid, .nbe-blocked { border-top-color: var(--down);
              background: color-mix(in srgb, var(--down) 8%, var(--panel)); }
  .nbe-head { display: flex; align-items: center; gap: 5px; }
  .nbe-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }
  .nbe-dot.a3 { background: var(--up); box-shadow: 0 0 0 3px color-mix(in srgb, var(--up) 22%, transparent); }
  .nbe-dot.a2 { background: var(--g-cold); }
  .nbe-dot.a1 { background: var(--warn); }
  .nbe-dot.a0 { background: var(--down); }
  .nbe-status { font-size: 10px; font-weight: 800; color: var(--ink); line-height: 1.2; }
  .nbe-zone { display: flex; align-items: baseline; gap: 5px; margin-top: 3px; }
  .nbe-lbl { color: var(--muted); font-size: 8px; font-weight: 700; letter-spacing: .04em;
             text-transform: uppercase; }
  .nbe-px { font-weight: 800; font-size: 11px; color: var(--text); font-variant-numeric: tabular-nums; }
  .nbe-pct { color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; }
  .nbe-cyc { font-size: 8.5px; color: var(--muted); margin-top: 3px; display: flex;
             align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }
  .nbe-bar { display: inline-block; width: 42px; height: 3px; border-radius: 2px;
             background: var(--line); overflow: hidden; }
  .nbe-bf { display: block; height: 100%; background: var(--g-cold); }
  .nb-val { font-size: 8.5px; font-weight: 700; padding: 0 5px; border-radius: 7px;
            color: var(--muted); background: var(--panel); border: 1px solid var(--line); }
  .nb-val.val-extreme, .nb-val.val-stretched { color: var(--ink-warn, var(--warn));
            border-color: color-mix(in srgb, var(--warn) 35%, var(--line)); }
  .nb-val.val-cheap { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 32%, var(--line)); }
  /* honesty notes — percentile-rank caveat + favourable-risk-cone read (AVGO/NVDA alignment) */
  .nb-note { font-size: 8.5px; line-height: 1.3; margin-top: 3px; padding: 2px 5px; border-radius: 6px;
             color: var(--muted); background: color-mix(in srgb, var(--ink) 4%, var(--panel)); }
  .nb-note-anticipation { color: var(--g-cold, var(--link));
             background: color-mix(in srgb, var(--link) 8%, var(--panel)); }
  /* per-leg EDGE basis chips (top-3 firing legs, tier-colored) */
  .nb-basis { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 2px; }
  .nbb { font-size: 8.5px; font-weight: 700; padding: 0 4px; border-radius: 6px;
         border: 1px solid var(--line); font-variant-numeric: tabular-nums; color: var(--muted); }
  .nbb-validated { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 35%, var(--line)); }
  .nbb-literature { color: var(--g-cold); border-color: color-mix(in srgb, var(--g-cold) 35%, var(--line)); }
  .nbb-screen { color: var(--ink-warn, var(--warn)); border-color: color-mix(in srgb, var(--warn) 35%, var(--line)); }
  /* the two new VERIFIERS — dealer-gamma "Options check" + the single-stock vol black hole */
  .nb-vf { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
  .nb-vchip { font-size: 8.5px; font-weight: 800; padding: 0 5px; border-radius: 6px;
              border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
  .vf-confirm { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 38%, var(--line));
                background: color-mix(in srgb, var(--up) 10%, var(--panel)); }
  .vf-caution { color: var(--ink-warn, var(--warn)); border-color: color-mix(in srgb, var(--warn) 38%, var(--line));
                background: color-mix(in srgb, var(--warn) 10%, var(--panel)); }
  .vf-neutral { color: var(--muted); }
  .vf-coil { color: var(--ink-link, var(--link)); border-color: color-mix(in srgb, var(--link) 38%, var(--line));
             background: color-mix(in srgb, var(--link) 10%, var(--panel)); }
  .vf-up { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 45%, var(--line));
           background: color-mix(in srgb, var(--up) 13%, var(--panel)); }
  .vf-down { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 40%, var(--line)); }
  .vf-exp { color: var(--ink-warn, var(--warn)); border-color: color-mix(in srgb, var(--warn) 35%, var(--line)); }
  /* SUE earnings-momentum confirmer chip (display context, never scored). Blue
     (--info) so it reads distinct from the green insider cluster + the green/red
     alpha, and is immune to the Asia red/green up/down swap. */
  .nb-sue { font-weight: 800; padding: 0 5px; border-radius: 7px; color: var(--ink-info, var(--info));
            white-space: nowrap; font-variant-numeric: tabular-nums;
            background: color-mix(in srgb, var(--info) 13%, var(--panel)); }
  /* Demand Desk L2 divergence flag (non-directional attention; immune to Asia red/green swap) */
  .nb-dmnd { font-weight: 800; padding: 0 5px; border-radius: 7px; white-space: nowrap;
             border: 1px solid var(--line); }
  .nb-dmnd.dmnd-up { color: var(--ink-warn, var(--warn)); border-color: color-mix(in srgb, var(--warn) 38%, var(--line));
             background: color-mix(in srgb, var(--warn) 12%, var(--panel)); }
  .nb-dmnd.dmnd-rk { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 38%, var(--line));
             background: color-mix(in srgb, var(--down) 11%, var(--panel)); }
  /* COILED wave-2-validated cohort-washout ranking bonus chip (display-only, US standouts) */
  .nb-coiled{flex:none;font-size:8px;font-weight:800;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;background:color-mix(in srgb,var(--link) 14%,transparent);color:var(--ink-link, var(--link));border:1px solid color-mix(in srgb,var(--link) 36%,transparent)}
  .nb-coiled.star{background:color-mix(in srgb,var(--up) 16%,transparent);color:var(--ink-up, var(--up));border-color:color-mix(in srgb,var(--up) 40%,transparent)}
  .nb-coiled.fire{box-shadow:0 0 6px color-mix(in srgb,var(--up) 45%,transparent);border-color:color-mix(in srgb,var(--up) 55%,transparent);color:var(--ink-up, var(--up));background:color-mix(in srgb,var(--up) 20%,transparent)}
  /* W6-C HOLD tracker chip — basing state after entry anchor (display-only, US standouts) */
  .nb-hold{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;background:var(--panel);color:var(--muted);border:1px solid var(--line)}
  .nb-hold.hold-launched{color:var(--ink-up, var(--up));background:color-mix(in srgb,var(--up) 10%,transparent);border-color:color-mix(in srgb,var(--up) 35%,transparent)}
  .nb-hold.hold-broken{color:var(--ink-down, var(--down));background:color-mix(in srgb,var(--down) 10%,transparent);border-color:color-mix(in srgb,var(--down) 35%,transparent)}
  /* W2 outcomes strip — recently surfaced → outcome */
  /* NOTE: the old .board-track-toggle glass pill + its .sm-bar relocation rules
     were removed with the Track-record popup revamp (2026-07-20). The receipt
     chip + dialog now live in the shared partial templates/_track_record_dlg.html.j2
     (all styles are self-scoped `trd-`). theme.js pinBoardTrackToggle() early-
     returns harmlessly now that #board-track-toggle no longer renders. */
  .prophet-board-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:10px 0 2px}
  .board-outcomes{margin-top:12px;border:1px solid var(--line);border-radius:8px;padding:8px 10px;background:var(--panel)}
  .board-outcomes-hdr{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:5px}
  .board-outcomes-title{font-weight:700;font-size:12px}
  .board-outcomes-sub{font-size:11px;color:var(--muted)}
  .outcomes-tbl{width:100%;border-collapse:collapse;font-size:11.5px}
  .outcomes-tbl th{text-align:left;font-weight:700;color:var(--muted);font-size:10px;padding:2px 4px 3px;border-bottom:1px solid var(--line)}
  .outcomes-tbl td{text-align:left;padding:3px 4px;border-bottom:1px solid color-mix(in srgb,var(--line) 50%,transparent);vertical-align:middle}
  /* headers are left-aligned, so the body cells must be too (the page-global `th,td{text-align:right}`
     otherwise right-shifts the data out from under its header). Numeric .r columns stay right on both. */
  .outcomes-tbl th.r,.outcomes-tbl td.r{text-align:right;font-variant-numeric:tabular-nums}
  .outcomes-tbl tr:last-child td{border-bottom:none}
  .oc-dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex-shrink:0}
  .oc-dot.running{background:var(--up)}
  .oc-dot.stopped{background:var(--down)}
  .oc-dot.flat{background:var(--muted)}
  .oc-pct.az-up{color:var(--ink-up,var(--up));font-weight:700}
  .oc-pct.az-dn{color:var(--ink-down,var(--down));font-weight:700}
  /* P2.4 board contract v2: lane chips (display-only, US standouts) */
  .nb-lane{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap}
  /* v2 lane taxonomy (bottoming/continuation/watch) + legacy names (trend/recovery) for backward compat */
  .lane-bottoming,.lane-trend{background:color-mix(in srgb,var(--up) 10%,transparent);color:var(--ink-up, var(--up));border:1px solid color-mix(in srgb,var(--up) 30%,transparent)}
  .lane-continuation{background:color-mix(in srgb,var(--cont,var(--warn)) 12%,transparent);color:var(--cont,var(--warn));border:1px solid color-mix(in srgb,var(--cont,var(--warn)) 35%,transparent)}
  .lane-watch{background:color-mix(in srgb,var(--muted) 10%,transparent);color:var(--muted);border:1px solid color-mix(in srgb,var(--muted) 25%,transparent)}
  .lane-recovery{background:color-mix(in srgb,var(--warn) 12%,transparent);color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 35%,transparent)}
  /* P2.4 above_trend context badge (display-only; T4 sub-partition context) */
  .nb-200dma{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;cursor:help}
  .dma-above{background:color-mix(in srgb,var(--muted) 8%,transparent);color:var(--muted);border:1px solid color-mix(in srgb,var(--muted) 20%,transparent)}
  .dma-below{background:color-mix(in srgb,var(--up) 8%,transparent);color:var(--ink-up, var(--up));border:1px solid color-mix(in srgb,var(--up) 25%,transparent)}
  /* P2.4 ext_z extension chip (display-only; F3 anti-chase context per P1.3) */
  .nb-extz{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;cursor:help;background:color-mix(in srgb,var(--muted) 8%,transparent);color:var(--muted);border:1px solid color-mix(in srgb,var(--muted) 18%,transparent)}
  .nb-extz.extz-warn{background:color-mix(in srgb,var(--warn) 10%,transparent);color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 30%,transparent)}
  /* P2.1a Anti-Chase Watch chip (shadow gate, R7 additive-lanes law) */
  .nb-antichase{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;cursor:help;background:color-mix(in srgb,var(--warn) 8%,transparent);color:var(--ink-warn, var(--warn));border:1px dashed color-mix(in srgb,var(--warn) 40%,transparent)}
  /* α laggard chip (alpha_entry=laggard, honest copy) */
  .ent-lag{background:color-mix(in srgb,var(--down) 10%,transparent);color:var(--ink-down, var(--down));border:1px solid color-mix(in srgb,var(--down) 28%,transparent);font-size:8px;font-weight:700;padding:1px 5px;border-radius:6px;white-space:nowrap}
  /* W8-B postcross lifecycle chip (SHAKEN; ARMED display removed per W8-A-OOS FAIL) */
  .nb-postcross{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap}
  .pc-shaken{background:color-mix(in srgb,var(--warn) 10%,transparent);color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 28%,transparent)}
  /* W9-A sector-capitulating safety chip (display-only; no rank power) */
  .nb-sector-cap{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;background:color-mix(in srgb,var(--warn) 8%,transparent);color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 22%,transparent)}
  /* RLT-R6 sector-stance disclosure: chip retired by prophet card v1 (fe7a7426c49) —
     the stance now rides the card's ⚠N flags popover; see the _fl.rows fold below. */
  /* W1.5 earnings-blackout chip (display-only; no rank power; hygiene context) */
  .nb-earn-soon{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;cursor:help;background:color-mix(in srgb,var(--warn) 10%,transparent);color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 28%,transparent)}
  /* Earnings-window candidates stay visible, below the primary picks. */
  .nb-ewatch{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 9px;margin:10px 0 2px;
    padding:8px 10px;border-top:1px solid var(--line);font-size:11.5px;cursor:help}
  .nb-ewatch-t{font-weight:800;color:var(--text)}
  .nb-ewatch-n{display:inline-flex;flex-wrap:wrap;gap:4px 9px}
  .nb-ewatch-n a{font-weight:800;text-decoration:none}
  .nb-ewatch-copy{color:var(--muted)}
  /* CSP-W5 board staleness badge */
  .nb-stale-note{font-size:11px;padding:5px 11px;margin:4px 0;border-radius:6px;font-weight:600;color:var(--ink-warn, var(--warn));border:1px solid color-mix(in srgb,var(--warn) 50%,var(--line));background:color-mix(in srgb,var(--warn) 9%,transparent)}
  /* CSP-W5 per-card muted note on expired pending rows */
  .nb-pending-expired{font-size:9.5px;padding:1px 5px;border-radius:4px;color:var(--muted);background:color-mix(in srgb,var(--muted) 8%,transparent);border:1px solid color-mix(in srgb,var(--muted) 20%,transparent);white-space:normal}
  /* B4 Conviction Delta — rows now live inside the Track-record-style dashboard. */
  .nb-delta-body{display:flex;flex-direction:column;gap:3px}
  .nb-delta-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:5px;padding:2px 0;border-top:1px solid var(--line)}
  .nb-delta-row:first-child{border-top:none}
  .nb-delta-tk{font-weight:700;font-size:11.5px;min-width:48px;flex:none}
  .nb-delta-verb{font-size:11px;padding:1px 6px;border-radius:4px;background:color-mix(in srgb,var(--muted) 12%,transparent);color:var(--fg);white-space:nowrap}
  .nb-delta-enter{background:color-mix(in srgb,var(--up) 14%,transparent);color:var(--ink-up, var(--up))}
  .nb-delta-leave{background:color-mix(in srgb,var(--down) 12%,transparent);color:var(--ink-down, var(--down))}
  .nb-delta-cleared{font-size:10.5px;color:var(--ink-up, var(--up));opacity:.85}
  .nb-delta-added{font-size:10.5px;color:var(--ink-warn, var(--warn));opacity:.85}
  /* W5b liquidity chip (display-only; no rank/gate power) */
  .nb-liq{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap;cursor:help}
  .nb-liq.liq-deep{color:var(--ink-up, var(--up));background:color-mix(in srgb,var(--up) 9%,transparent);border:1px solid color-mix(in srgb,var(--up) 28%,transparent)}
  .nb-liq.liq-ok{color:var(--g-cold);background:color-mix(in srgb,var(--g-cold) 9%,transparent);border:1px solid color-mix(in srgb,var(--g-cold) 28%,transparent)}
  .nb-liq.liq-thin{color:var(--ink-warn, var(--warn));background:color-mix(in srgb,var(--warn) 9%,transparent);border:1px solid color-mix(in srgb,var(--warn) 28%,transparent)}
  .nb-liq.liq-illiquid{color:var(--ink-down, var(--down));background:color-mix(in srgb,var(--down) 9%,transparent);border:1px solid color-mix(in srgb,var(--down) 28%,transparent)}
  /* W2 merge note: chip explanatory copy uses the repo-standard data-tip-en/data-tip-zh
     + theme.js popover (check_title_i18n.py-guarded); the bespoke .nb-chip-pop is retired. */
  .ts-sue { font-weight: 800; font-size: 10px; color: var(--ink-info, var(--info)); white-space: nowrap;
            padding: 0 4px; border-radius: 6px; font-variant-numeric: tabular-nums;
            background: color-mix(in srgb, var(--info) 13%, var(--panel)); }
  /* W3 evidence-stack chips (display-only; forward IC accruing; context framing only) */
  .nb-ev{flex:none;font-size:8px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:6px;white-space:nowrap}
  .nb-ev-gex{color:var(--ink-info, var(--info));background:color-mix(in srgb,var(--info) 10%,transparent);border:1px solid color-mix(in srgb,var(--info) 28%,transparent)}
  .nb-ev-alt{color:var(--ink-up, var(--up));background:color-mix(in srgb,var(--up) 8%,transparent);border:1px solid color-mix(in srgb,var(--up) 22%,transparent)}
  .nb-ev-news{color:var(--muted);background:color-mix(in srgb,var(--muted) 8%,transparent);border:1px solid color-mix(in srgb,var(--muted) 18%,transparent)}
  .nb-ev-sm{color:var(--ink-up, var(--up));background:color-mix(in srgb,var(--up) 8%,transparent);border:1px solid color-mix(in srgb,var(--up) 22%,transparent)}
  .nb-ev-conf{color:var(--ink-link, var(--link));font-weight:900;background:color-mix(in srgb,var(--link) 10%,transparent);border:1px solid color-mix(in srgb,var(--link) 30%,transparent)}
  .nb-stop{font-size:9px;color:var(--muted);margin-top:2px}
  .nb-stop .stop-unscored{opacity:.55}
  /* broad "Top setups" board (selection × timing across the S&P 1500) */
  .topsetups { margin-top: 14px; }
  .ts-more { margin-left: auto; font-size: 11px; font-weight: 700; white-space: nowrap; }
  .ts-tbl { width: 100%; border-collapse: collapse; margin-top: 7px; font-size: 11.5px; }
  .ts-tbl th { text-align: left; font-weight: 700; color: var(--muted); font-size: 10px;
               text-transform: uppercase; letter-spacing: .03em; padding: 3px 8px;
               border-bottom: 1px solid var(--line); }
  /* The α headers are SYMBOLS, and uppercase folds α to Greek capital Alpha — which
     renders as a plain Latin "A", so "edge (α)" and "α (tiebreak)" ship as
     "EDGE (A)" / "A (TIEBREAK)" and stop naming the thing they hold. A wrong label
     is a wrong number wearing words. Only this header opts out of the case
     transform; the rest of the row keeps the uppercase idiom. Caught on the HK port
     of this table (templates/hk.html.j2), which carries the same one-line fix. */
  .ts-tbl th.c-edge { text-transform: none; }
  /* left by default to sit under the left-aligned headers (else the page-global th,td{right}
     right-shifts the text columns); .r columns stay right on both header + body (rule below). */
  .ts-tbl td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--line); }
  .ts-tbl th.r, .ts-tbl td.r { text-align: right; font-variant-numeric: tabular-nums; }
  .ts-row { cursor: pointer; transition: background .12s; }
  .ts-row:hover { background: var(--panel2); }
  .ts-tk { font-weight: 800; color: var(--text); }
  /* The ticker is a real anchor so theme.js's capture-phase Terminal intercept can
     see it (and so middle-/cmd-click still opens a tab). It must not read as a blue
     link inside the row — the row itself is the affordance. */
  .ts-tk-a { color: inherit; text-decoration: none; }
  .ts-nm { font-size: 10px; color: var(--muted); }
  .ts-tbl td.az-up { color: var(--ink-up, var(--up)); font-weight: 700; }
  .ts-tbl td.az-dn { color: var(--ink-down, var(--down)); font-weight: 700; }
  /* confluence buy-signal chip (the hard gate the board now requires) */
  .ts-buy { font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 6px; white-space: nowrap; border: 1px solid var(--line); }
  .ts-buy.ok { color: var(--ink-up, var(--up)); border-color: var(--up); background: color-mix(in srgb, var(--up) 14%, var(--panel)); }
  .ts-buy.soon { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 55%, var(--line)); }
  /* ── strip tables on phones (UX handoff §17: primary decisions never x-scroll) ──
     Both prophet-panel strips (⚡ fresh triggers, 9 cols · 🏃 market leaders, 6 cols,
     7 when the artifact stamps themes) are wider than a 390px panel, so .tbl-scroll
     clipped their header mid-word and hid whole columns behind an in-panel x-scroll.
     At the board's own 680px mobile break the tertiary columns demote to the row's
     stock page (every row is a tap-through); what stays — ticker+name, edge (α), and
     the stance column (buy / entry) — keeps its visible header as its label.
     .tbl-scroll remains underneath as the fail-safe if a future column outgrows the
     budget. */
  @media (max-width: 680px){
    .topsetups .ts-tbl .c-sector, .topsetups .ts-tbl .c-rank,
    .topsetups .ts-tbl .c-cycle,  .topsetups .ts-tbl .c-trend,
    .topsetups .ts-tbl .c-factor, .topsetups .ts-tbl .c-setup,
    .topsetups .ts-tbl .c-offhigh, .topsetups .ts-tbl .c-state,
    .topsetups .ts-tbl .c-theme { display: none; }
  }
  .ts-empty { margin-top: 9px; font-size: 11.5px; color: var(--muted); line-height: 1.5; }
  /* major-index health (macro page hero) */
  .idx-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 12px; }
  @media (max-width: 900px) { .idx-grid { grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 480px) { body.page-macro .idx-grid { grid-template-columns: 1fr; } }
  body.page-macro .idx-grid > * { min-width: 0; }
  @media (max-width: 560px) {
    body.page-macro #now-board .nb-sum { grid-template-columns: auto 1fr; }
    body.page-macro #now-board .nb-meta { grid-column: 1 / -1; white-space: normal; }
  }
  .idx-tile { background: var(--panel2); border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px; }
  .idx-top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 4px; }
  .idx-px { font-variant-numeric: tabular-nums; color: var(--muted); }
  .idx-row, .idx-trend { display: flex; justify-content: space-between; font-size: 12px; gap: 8px; }
  .idx-trend { margin-top: 3px; color: var(--muted); }
  .idx-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .idx-tkr { font-size: 10px; font-weight: 600; letter-spacing: .04em; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; margin-left: 5px; }
  .idx-chg { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; white-space: nowrap; }
  .idx-grid .pos { color: var(--ink-up, var(--up)); } .idx-grid .neg { color: var(--ink-down, var(--down)); } .idx-grid .warn { color: var(--ink-warn, var(--warn)); }
  .idx-risk { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
  @media (max-width: 900px) { .idx-risk { grid-template-columns: 1fr; } }
  .idx-gauge, .idx-alloc { background: var(--panel2); border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px; }
  .idx-alloc { display: block; text-decoration: none; color: inherit; border-color: var(--link); }
  .idx-alloc:hover { background: var(--panel); }
  .idx-gk { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
  .idx-gv { font-size: 24px; font-weight: 800; color: var(--text); } .idx-gv small { font-size: 12px; font-weight: 600; color: var(--muted); }
  /* integrated de-risk score model (leg breakdown) */
  .rm-bar { height: 22px; border-radius: 7px; overflow: hidden; display: flex; background: var(--panel2); border: 1px solid var(--line); margin: 6px 0; }
  .rm-bar div { height: 100%; }
  .rm-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; margin-top: 8px; }
  .rm-tbl td, .rm-tbl th { padding: 5px 8px; border-bottom: 1px solid var(--line); text-align: right; }
  .rm-tbl td.l, .rm-tbl th.l { text-align: left; }
  .rm-dot { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 6px; vertical-align: middle; }

  /* ── W8-R6: US Standout table view (mirrors CN implementation) ────────
     NOTE: These .st-* rules are NOT scoped to body.page-stocks (matching the
     china.html.j2 pattern where the same rules are emitted unscoped).  The HTML
     data block and JS init ARE gated (_su guard / mode != macro), so the rules
     are dead CSS on macro.html — no functional impact.  Mirror this intentional
     pattern when editing china.html.j2 to keep implementations in sync. */
  .st-view-toggle { display:inline-flex; gap:3px; padding:3px; border-radius:8px;
    background:var(--panel2,color-mix(in srgb,var(--muted) 10%,var(--panel)));
    border:1px solid var(--line); margin-left:10px; vertical-align:middle; }
  .st-view-toggle button { font:inherit; font-size:12px; font-weight:700; cursor:pointer;
    border:1px solid transparent; background:transparent; color:var(--muted);
    padding:4px 9px; border-radius:5px; line-height:1; transition:all .12s; }
  .st-view-toggle button[aria-selected="true"] { background:var(--panel); color:var(--text);
    border-color:var(--line); box-shadow:0 1px 3px rgba(0,0,0,.1); }
  #us-stocktable-wrap { display:none; }
  #us-standouts.st-table-mode #us-stocktable-wrap { display:block; }
  #us-standouts.st-table-mode .nb-grid-section { display:none; }
  /* P0 #6185 — source view: exactly one population is on screen at a time. */
  #us-standouts[data-prophet-src="plans"] #us-candidates { display:none; }
  #us-standouts[data-prophet-src="candidates"] #us-plan-block { display:none; }
  /* the Grid/Table view toggle switches the CANDIDATE table; there is no plan
     table yet (P-MP1-DENSE), so it must never appear under a Plans label. */
  #us-standouts[data-prophet-src="plans"] #us-st-view-toggle { display:none; }
  /* count chips row (id matches stocktable.js hard-coded lookup) */
  #st-count-chips { display:inline-flex; gap:5px; flex-wrap:wrap; align-items:center; margin:8px 0; }
  .st-chip { display:inline-block; font-size:10px; font-weight:700; padding:2px 9px;
    border-radius:999px; white-space:nowrap; }
  .st-chip-lane { background:color-mix(in srgb,var(--link) 14%,transparent);
    color:var(--ink-link, var(--link)); border:1px solid color-mix(in srgb,var(--link) 30%,transparent); }
  /* filter row */
  /* filter-row + column-chooser chrome (.stf-*) is injected by stocktable.js since v3 */
  /* table wrapper — horizontal scroll, sticky first col */
  .st-table-wrap { overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%;
    border:1px solid var(--line); border-radius:9px; }
  .st-table { border-collapse:collapse; width:100%; font-size:12px;
    font-variant-numeric:tabular-nums; }
  .st-table thead { position:sticky; top:0; z-index:4;
    background:var(--panel2,color-mix(in srgb,var(--muted) 9%,var(--panel))); }
  .st-table th { padding:7px 10px; font-size:11px; font-weight:700; color:var(--muted);
    text-align:left; white-space:nowrap; border-bottom:2px solid var(--line);
    user-select:none; }
  .st-table th.st-sortable { cursor:pointer; }
  .st-table th.st-sortable:hover { color:var(--text); }
  .st-table td { padding:6px 10px; border-bottom:1px solid var(--line);
    text-align:left; white-space:nowrap; vertical-align:middle; }
  .st-table td.st-r, .st-table th.st-r { text-align:right; }
  .st-table tbody tr:last-child td { border-bottom:none; }
  .st-table tbody tr:hover td { background:color-mix(in srgb,var(--link) 5%,transparent); }
  /* sticky first column */
  .st-sticky-col { position:sticky; left:0; z-index:2; background:var(--panel); }
  thead .st-sticky-col { z-index:5;
    background:var(--panel2,color-mix(in srgb,var(--muted) 9%,var(--panel))); }
  /* row accents by lane */
  .st-row-bottoming td { background:color-mix(in srgb,var(--up) 4%,transparent); }
  .st-row-bottoming td.st-sticky-col { background:color-mix(in srgb,var(--up) 8%,var(--panel)); }
  .st-row-bottoming td:first-child { box-shadow:inset 3px 0 0 var(--up); }
  .st-row-continuation td:first-child { box-shadow:inset 3px 0 0 var(--link); }
  .st-row-trend td:first-child { box-shadow:inset 3px 0 0 color-mix(in srgb,var(--link) 55%,var(--up)); }
  .st-row-recovery td:first-child { box-shadow:inset 3px 0 0 color-mix(in srgb,var(--g-cold) 65%,var(--muted)); }
  .st-row-watch td:first-child { box-shadow:inset 3px 0 0 var(--muted); }
  .st-row-watch td { color:var(--muted); }
  /* sort arrow */
  .st-sarrow { font-size:8px; margin-left:2px; opacity:.28; }
  .st-sarrow-idle { font-size:8px; }
  .st-table th:has(.st-sarrow:not(.st-sarrow-idle)) .st-sarrow { opacity:.9; color:var(--ink-link, var(--link)); }
  /* cell colors */
  .st-pos { color:var(--ink-up, var(--up)); font-weight:600; }
  .st-neg { color:var(--ink-down, var(--down)); font-weight:600; }
  .st-muted { color:var(--muted); }
  .st-new-dot::before { content:"NEW"; display:inline-block; font-size:8px; font-weight:800;
    background:var(--up); color:#fff; padding:0 4px; border-radius:4px; margin-right:4px;
    vertical-align:1px; }
  html[data-lang="zh"] .st-new-dot::before { content:"新"; font-size:10px; }
  /* th tooltip */
  .st-th-tip { display:inline-flex; align-items:center; justify-content:center;
    width:13px; height:13px; border-radius:50%; border:1px solid var(--muted);
    color:var(--muted); font-size:9px; font-weight:700; cursor:help;
    position:relative; vertical-align:1px; margin-left:3px; }
  .st-th-tip::after { content:attr(data-tip-en); display:none; position:absolute;
    bottom:150%; left:50%; transform:translateX(-50%); width:220px; max-width:90vw;
    background:var(--panel); border:1px solid var(--line); border-radius:8px;
    padding:7px 10px; font-size:11px; font-weight:400; color:var(--text); text-align:left;
    white-space:normal; box-shadow:var(--popover-shadow,0 3px 12px rgba(0,0,0,.18)); z-index:30; }
  html[data-lang="zh"] .st-th-tip::after { content:attr(data-tip-zh); }
  .st-th-tip:hover::after { display:block; }
  /* mobile: table scrolls, first col sticky */
  @media (max-width:680px) {
    .st-table { font-size:11px; }
    .st-table td, .st-table th { padding:5px 7px; }
  }

  /* ======================================================================
     MACRO TERMINAL — scoped enhancement layer (macro.html only)
     Everything here is gated under body.page-macro, which is emitted ONLY for
     mode != 'stocks' (line ~528). The US Stock Dashboard + every other page
     are byte-untouched. NO theme.css edits — all colour routes through the
     existing theme vars so dark/light AND the zh Asia red/green swap propagate
     at paint. Aesthetic: a Bloomberg-grade macro terminal — hairline-precise,
     tabular, monochrome-by-default; the regime reads in 2 seconds and every
     figure reads in one, with colour spent only on signal.
     ====================================================================== */
  body.page-macro {
    /* terminal numeral face — SYSTEM mono stack, no web-font dependency */
    --num: var(--font-mono, ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Mono",
           "JetBrains Mono", "Roboto Mono", Menlo, Consolas, monospace);
    /* hairlines + inset surface, layered on the existing palette */
    --hair: color-mix(in srgb, var(--line) 72%, transparent);
    --hair-strong: var(--line);
    --tile: color-mix(in srgb, var(--panel2) 86%, var(--panel));
    /* ink ramp — lift BODY copy off the ~40% muted soup; reserve --muted for
       genuine captions only (the single highest-leverage readability fix) */
    --ink-1: var(--text);
    --ink-2: color-mix(in srgb, var(--text) 64%, transparent);
    --ink-3: var(--muted);
    --rule: 1px;
    --pad: 20px;
    --ms: inset 0 1px 0 0 color-mix(in srgb, var(--text) 9%, transparent),
          0 1px 1px rgba(0,0,0,.28), 0 14px 30px -18px rgba(0,0,0,.55);

    /* ═══ BILLION-DOLLAR MAKEOVER — one shared design system ═══════════════
       The page used to re-invent its type sizes (~29 distinct px values) and
       spacing in every block. These tokens are the single source of truth so
       every module shares one scale, one rhythm, one material language. */
    /* deepened terminal canvas — richer "screen" black, scoped to this page */
    --bg:#0a0c11; --panel:#14171e; --panel2:#1b1f28;
    /* type scale — the 11-step ramp this page invented is now the SITE ramp and
       lives at :root in theme.css (design-system packet PR-0(a)). Promoted
       verbatim, so this page's type is byte-unchanged; it now inherits it. */
    /* spacing grid (4px base) — kill the 7/9/11/13/17/19px grab-bag */
    --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px;
    /* radii + the eyebrow tracking constant */
    --r-sm:8px; --r-md:10px; --r-lg:14px; --trk:.18em;
    /* the single regime/accent rail used on every section header */
    --rail: var(--link);
  }
  html[data-theme="light"] body.page-macro {
    /* Light = a design target, not a tint (round-3 depth pass). The old canvas
       was #f6f7fa: a white panel on it measured 1.07:1, so every card dissolved
       into the page and the dashboard read as one flat sheet. The estate depth
       recipe deepens the canvas to #e8ebf1 (1.19:1 under a white panel, +81%
       separation) and moves the remaining depth into a real two-stop shadow —
       contact + ambient — instead of a heavier border. --line is deliberately
       NOT lowered to the recipe hairline here: it drives 233 INTERNAL rules on
       this page (vs 29 for --hair), and an internal rule has no shadow to lean
       on, so it keeps the estate's raised value. The recipe hairline is applied
       where it belongs — the panel EDGE (--mx5-glass-border below). */
    --bg:#e8ebf1; --panel:#ffffff; --panel2:#eef1f6;
    --ink-2: color-mix(in srgb, var(--text) 70%, transparent);
    --hair: color-mix(in srgb, var(--line) 90%, transparent);
    --ms: 0 1px 2px rgba(23,32,55,.05), 0 8px 24px -12px rgba(23,32,55,.10);
  }

  /* ---- type scale: one confident hierarchy, every size from the scale ---- */
  body.page-macro { font-size: var(--fs-body); line-height: 1.55; }
  body.page-macro h1 { font-size: var(--fs-h1); font-weight: 800; letter-spacing: -.02em;
    color: var(--ink-1); }
  /* THE section-header system — every panel title reads identically: a regime
     rail, a strong sentence-case title, a hairline rule to the panel edge. This
     single shared rhythm is what turns the islands into one product. */
  body.page-macro h2 { font-size: var(--fs-h2); font-weight: 700; letter-spacing: -.01em;
    text-transform: none; color: var(--ink-1); line-height: 1.3; }
  body.page-macro .panel > h2 { margin: 0 0 var(--sp-4); padding: 0 0 var(--sp-3);
    border-bottom: var(--rule) solid var(--hair-strong);
    display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
  body.page-macro .panel > h2::before { content: ""; flex: none; align-self: center;
    width: 3px; height: 18px; border-radius: 2px;
    background: linear-gradient(180deg, var(--rail), color-mix(in srgb, var(--rail) 35%, transparent)); }
  html[data-lang="zh"] body.page-macro h2 { letter-spacing: 0; }
  body.page-macro h3 { font-size: var(--fs-h3); font-weight: 700; letter-spacing: 0;
    color: var(--ink-1); text-transform: none; }
  /* lift inline body greys; keep a true-caption class at the dimmer --ink-3 */
  body.page-macro .muted { color: var(--ink-2); }
  body.page-macro .kv { color: var(--ink-2); }
  body.page-macro .sm { color: var(--ink-2); }
  body.page-macro .cap, body.page-macro .muted.cap { font-size: var(--fs-label); font-weight: 700;
    letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }

  /* ---- numerals: the terminal signature — figures tabular + mono ---- */
  body.page-macro .num, body.page-macro .num-lg, body.page-macro .num-xl,
  body.page-macro .kv b, body.page-macro .idx-gv, body.page-macro .prob .pc,
  body.page-macro .tm-date, body.page-macro .sc-v, body.page-macro .stance-meta,
  body.page-macro th, body.page-macro td:not(:first-child):not(.l),
  body.page-macro .sig-val, body.page-macro .v-num, body.page-macro .v-chip,
  body.page-macro .mtile-val, body.page-macro .vixnum {
    font-family: var(--num); font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1; letter-spacing: -.01em; }
  body.page-macro .num-xl { font-size: 34px; font-weight: 800; line-height: 1;
    letter-spacing: -.02em; color: var(--ink-1); }
  body.page-macro .num-lg { font-size: 22px; font-weight: 800; line-height: 1.05; }
  /* keep help-tooltip tables as readable prose — the numeral mono face must not
     bleed into the explanatory sentences in their cells (.tip tables are prose) */
  body.page-macro .tip td:not(:first-child):not(.l), body.page-macro .tip th {
    font-family: inherit; font-variant-numeric: normal; letter-spacing: normal; }

  /* ---- panel: crisp module — hairline frame, faint machined top edge ---- */
  body.page-macro .grid { gap: var(--sp-4); }
  @media (min-width: 1100px) { body.page-macro .grid { gap: var(--sp-5) var(--sp-5); } }
  body.page-macro .panel { background: var(--panel);
    border: var(--rule) solid var(--hair-strong); border-radius: var(--r-lg);
    padding: var(--pad) calc(var(--pad) + 2px); box-shadow: var(--ms); }

  /* ---- tables: terminal treatment ---- */
  body.page-macro table { font-size: var(--fs-sm); }
  body.page-macro th { font-size: var(--fs-micro); font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--ink-3);
    border-bottom: var(--rule) solid var(--hair-strong); }
  body.page-macro td { border-bottom: var(--rule) solid var(--hair); color: var(--ink-1); }
  body.page-macro tbody tr:hover td, body.page-macro tr:hover td {
    background: color-mix(in srgb, var(--link) 6%, transparent); }

  /* ---- inset tiles: a class hook (opt-in) instead of attribute-matching ---- */
  body.page-macro .mtile-x { background: var(--tile);
    border: var(--rule) solid var(--hair); border-radius: 9px; }

  /* ---- gauges: crisper needle ---- */
  body.page-macro .gauge { height: 8px; border-radius: 4px;
    outline: var(--rule) solid var(--hair); outline-offset: -1px; }
  body.page-macro .gauge i { width: 3px; height: 16px; top: -4px; background: var(--ink-1);
    box-shadow: 0 0 0 1.5px var(--panel), 0 0 8px color-mix(in srgb, var(--ink-1) 60%, transparent); }
  body.page-macro .prob .bar, body.page-macro .lifebar { background: var(--tile); }
  body.page-macro .prob .pc { font-size: 17px; }

  /* ======================= HERO (command center) ======================= */
  body.page-macro #regime-radar { padding: 19px 21px; }
  body.page-macro .hero-bar { display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 26px; }
  body.page-macro .hero-main { padding: 2px 28px; min-width: 0;
    border-left: var(--rule) solid var(--hair); border-right: var(--rule) solid var(--hair); }

  /* LEFT — 2x2 quadrant locator (growth↑ top, inflation→ right; lit cell only) */
  body.page-macro .hero-loc { display: grid; gap: 7px; justify-items: start; }
  body.page-macro .qmini { display: grid; grid-template-columns: repeat(2, 31px);
    grid-template-rows: repeat(2, 31px); gap: 5px; }
  body.page-macro .qm { border-radius: 6px;
    background: color-mix(in srgb, var(--qc) 14%, var(--tile));
    border: var(--rule) solid color-mix(in srgb, var(--qc) 28%, var(--hair));
    transition: box-shadow .2s ease; }
  body.page-macro .qm.on { background: var(--qc);
    box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--qc),
                0 0 18px color-mix(in srgb, var(--qc) 55%, transparent); }
  body.page-macro .loc-axes { display: flex; justify-content: space-between; width: 100%;
    gap: 8px; font-family: var(--num); font-size: 8px; letter-spacing: .05em;
    color: var(--ink-3); text-transform: uppercase; font-weight: 700; }

  /* CENTER — the read */
  body.page-macro .hero-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--ink-3); display: flex; align-items: center;
    gap: 7px; flex-wrap: wrap; }
  body.page-macro .hero-eyebrow .num { color: var(--ink-2); }
  body.page-macro .hero-regime { display: flex; align-items: center; gap: 12px; margin: 7px 0 6px; }
  body.page-macro .hr-dot { width: 13px; height: 13px; border-radius: 50%; flex: none; }
  body.page-macro h1.hr-name { font-size: 33px; font-weight: 800; letter-spacing: -.02em;
    line-height: 1; color: var(--ink-1); margin: 0; }
  html[data-lang="zh"] body.page-macro h1.hr-name { font-size: 31px; letter-spacing: 0; }
  body.page-macro .hero-says { margin: 0; font-size: 14px; color: var(--ink-2);
    max-width: 52ch; line-height: 1.5; }
  body.page-macro .hero-says b { color: var(--ink-1); font-weight: 700; }

  /* RIGHT — vitals strip: 4 cells, each LABEL · VALUE · plain-English MEANING */
  body.page-macro .hero-vitals { display: grid;
    grid-template-columns: repeat(2, minmax(120px, 1fr)); gap: 13px 20px; }
  body.page-macro .vital { display: grid; gap: 4px; align-content: start; }
  body.page-macro .v-top { display: flex; align-items: center; gap: 5px; }
  body.page-macro .v-label { font-family: var(--num); font-size: 9.5px; font-weight: 700;
    letter-spacing: .1em; color: var(--ink-3); text-transform: uppercase; }
  body.page-macro .v-num { color: var(--ink-1); }
  body.page-macro .v-num small { font-size: 14px; color: var(--ink-3); font-weight: 600;
    font-family: var(--num); }
  body.page-macro .v-mean { font-size: 11px; color: var(--ink-2); line-height: 1.35; }
  body.page-macro .v-meter { height: 4px; border-radius: 2px; background: var(--tile);
    position: relative; overflow: hidden; }
  body.page-macro .v-meter::after { content: ""; position: absolute; inset: 0 auto 0 0;
    width: var(--p, 0%); background: var(--mc, var(--ink-2)); border-radius: 2px; }
  body.page-macro .v-chip { font-size: 12.5px; font-weight: 700; padding: 3px 10px;
    border-radius: 7px; width: max-content; border: var(--rule) solid var(--hair);
    background: var(--tile); color: var(--ink-1); }
  body.page-macro .liq-expanding { color: var(--ink-up, var(--up));
    border-color: color-mix(in srgb, var(--up) 45%, var(--hair));
    background: color-mix(in srgb, var(--up) 13%, var(--tile)); }
  body.page-macro .liq-contracting { color: var(--ink-down, var(--down));
    border-color: color-mix(in srgb, var(--down) 45%, var(--hair));
    background: color-mix(in srgb, var(--down) 13%, var(--tile)); }
  body.page-macro .v-chip.state-WEAKENING { color: var(--ink-warn, var(--warn));
    border-color: color-mix(in srgb, var(--warn) 45%, var(--hair));
    background: color-mix(in srgb, var(--warn) 11%, var(--tile)); }
  body.page-macro .v-chip.state-TRANSITIONING { color: var(--ink-orange, var(--orange));
    border-color: color-mix(in srgb, var(--orange) 45%, var(--hair));
    background: color-mix(in srgb, var(--orange) 11%, var(--tile)); }
  body.page-macro .v-chip.state-NEW_REGIME { color: var(--ink-act, var(--act));
    border-color: color-mix(in srgb, var(--act) 45%, var(--hair));
    background: color-mix(in srgb, var(--act) 11%, var(--tile)); }

  @media (max-width: 900px) {
    body.page-macro .hero-bar { grid-template-columns: 1fr; gap: 16px; }
    body.page-macro .hero-main { border: 0; padding: 14px 0;
      border-top: var(--rule) solid var(--hair); border-bottom: var(--rule) solid var(--hair); }
    body.page-macro h1.hr-name { font-size: 28px; }
    body.page-macro .hero-vitals { grid-template-columns: repeat(2, 1fr); }
  }

  /* ======================= SIGNAL ATOM (one language everywhere) =======================
     3px state rail · LABEL (mono caption) · VALUE (tabular) · MEANING (plain English).
     State->colour declared in ONE place; the zh swap propagates via --up/--down/--qN. */
  body.page-macro .sig { display: grid; grid-template-columns: 3px 1fr;
    background: var(--tile); border: var(--rule) solid var(--hair);
    border-radius: 9px; overflow: hidden; }
  body.page-macro .sig::before { content: ""; background: var(--sc, var(--ink-3)); }
  body.page-macro .sig-body { padding: 10px 12px; display: grid; gap: 3px; }
  body.page-macro .sig-label { font-family: var(--num); font-size: 9.5px; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
  body.page-macro .sig-val { font-size: 16px; font-weight: 800; color: var(--ink-1); }
  body.page-macro .sig-mean { font-size: 12px; color: var(--ink-2); line-height: 1.4; }
  body.page-macro .sig.is-good   { --sc: var(--up); }     /* direction → swaps in zh */
  body.page-macro .sig.is-bad    { --sc: var(--down); }   /* direction → swaps in zh */
  body.page-macro .sig.is-warn   { --sc: var(--warn); }   /* health → not swapped   */
  body.page-macro .sig.is-danger { --sc: var(--act); }
  body.page-macro .sig.is-ok     { --sc: var(--ok); }
  body.page-macro .sig.is-flat   { --sc: var(--ink-3); }
  body.page-macro .sig.is-q1 { --sc: var(--q1); } body.page-macro .sig.is-q2 { --sc: var(--q2); }
  body.page-macro .sig.is-q3 { --sc: var(--q3); } body.page-macro .sig.is-q4 { --sc: var(--q4); }
  body.page-macro .sig.is-good .sig-val { color: var(--ink-up, var(--up)); }
  body.page-macro .sig.is-bad  .sig-val { color: var(--ink-down, var(--down)); }

  /* inline headwind/tailwind chip — named .wind (NOT .tw — that's the trendword macro) */
  body.page-macro .wind { font-family: var(--num); font-size: 11px; font-weight: 700;
    letter-spacing: .02em; padding: 1px 7px; border-radius: 5px;
    background: color-mix(in srgb, var(--wc, var(--ink-3)) 15%, var(--tile));
    color: var(--wc, var(--ink-2));
    border: var(--rule) solid color-mix(in srgb, var(--wc, var(--ink-3)) 35%, transparent); }
  body.page-macro .wind.tail { --wc: var(--up); }
  body.page-macro .wind.head { --wc: var(--down); }
  body.page-macro .wind.neu  { --wc: var(--ink-3); }

  /* respect reduced-motion: the locator cell's glow can fade its colour on a
     theme/language toggle (the quad vars swap in zh) — neutralise that motion */
  @media (prefers-reduced-motion: reduce) {
    body.page-macro .qm { transition: none; }
  }

  /* ===== HERO enlargement + "New here?" tuck (desktop) ===== */
  body.page-macro #regime-radar { position: relative; }
  body.page-macro .qmini { grid-template-columns: repeat(2, 41px); grid-template-rows: repeat(2, 41px); gap: 6px; }
  body.page-macro h1.hr-name { font-size: 42px; }
  body.page-macro .hr-dot { width: 15px; height: 15px; }
  body.page-macro .hero-says { font-size: 14.5px; max-width: 52ch; }
  /* "New here?" → compact, de-emphasised, right-tucked so the hero is the star;
     it expands in place (a thin help line), never crowding the locator/headline */
  body.page-macro #regime-radar > .howto { margin: 11px 0 0; text-align: right; }
  body.page-macro #regime-radar > .howto > summary { display: inline-block; font-size: 12px;
    font-weight: 600; color: var(--ink-3); }
  body.page-macro #regime-radar > .howto > summary:hover { color: var(--ink-link, var(--link)); }
  body.page-macro #regime-radar > .howto[open] > div { text-align: left; }

  /* ===== Foldable panel (Data health, dormant Dislocation): click header to open/close ===== */
  body.page-macro details.fold > summary { list-style: none; cursor: pointer; display: flex;
    align-items: center; gap: 9px; font-size: 14px; font-weight: 700; color: var(--ink-1);
    line-height: 1.35; }
  body.page-macro details.fold > summary::-webkit-details-marker { display: none; }
  body.page-macro details.fold > summary::before { content: ""; flex: none; width: 3px; height: 14px;
    border-radius: 1.5px; background: var(--link); }
  /* Wave E — Data health: status dot reflecting live health (green OK / amber attention) */
  body.page-macro details.fold.health-strip > summary::before { width: 9px; height: 9px; border-radius: 50%; }
  body.page-macro details.fold.health-ok > summary::before { background: var(--up, #22d97a);
    box-shadow: 0 0 7px color-mix(in srgb, var(--up, #22d97a) 55%, transparent); }
  body.page-macro details.fold.health-warn > summary::before { background: var(--warn, #f59e0b);
    box-shadow: 0 0 7px color-mix(in srgb, var(--warn, #f59e0b) 55%, transparent); }
  body.page-macro details.fold > summary .fold-stat { font-weight: 500; color: var(--ink-2);
    font-size: 12.5px; }
  body.page-macro details.fold > summary .fold-caret { margin-left: auto; flex: none; font-size: 11px;
    color: var(--ink-3); transition: transform .22s ease; }
  body.page-macro details.fold[open] > summary .fold-caret { transform: rotate(180deg); }
  body.page-macro details.fold[open] > summary { margin-bottom: 13px; padding-bottom: 11px;
    border-bottom: var(--rule) solid var(--hair); }
  body.page-macro details.fold > summary:hover .fold-caret { color: var(--ink-link, var(--link)); }

  /* ===== Combined "Now" board — pure-CSS radio tabs (no JS) ===== */
  body.page-macro .cb-tabs { display: flex; flex-wrap: wrap; align-items: stretch; gap: 6px; margin-top: 2px; }
  body.page-macro .cb-radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
  body.page-macro .cb-tab { display: inline-flex; align-items: center; gap: 7px; padding: 8px 15px;
    border-radius: 9px; border: var(--rule) solid var(--hair); background: var(--panel);
    cursor: pointer; font-size: 13px; font-weight: 700; color: var(--ink-2); user-select: none;
    transition: color .15s, background .15s, border-color .15s; }
  body.page-macro .cb-tab:hover { color: var(--ink-1); border-color: color-mix(in srgb, var(--link) 45%, var(--hair)); }
  body.page-macro .cb-radio:checked + .cb-tab { color: var(--ink-1); background: var(--tile);
    border-color: color-mix(in srgb, var(--link) 55%, var(--hair));
    box-shadow: inset 0 -2px 0 0 var(--link); }
  body.page-macro .cb-radio:focus-visible + .cb-tab { outline: 2px solid color-mix(in srgb, var(--link) 70%, transparent); outline-offset: 2px; }
  /* a full-width hairline divider that wraps right after the tab row, above the panes */
  body.page-macro .cb-tabs::after { content: ""; order: 1; flex-basis: 100%; height: var(--rule);
    background: var(--hair); margin: 9px 0 0; }
  body.page-macro .cb-pane { order: 2; display: none; flex-basis: 100%; width: 100%; min-width: 0; padding-top: 14px; }
  body.page-macro #cb-alerts:checked ~ .cb-p-alerts,
  body.page-macro #cb-news:checked ~ .cb-p-news,
  body.page-macro #cb-relief:checked ~ .cb-p-relief { display: block; }
  body.page-macro .cb-count { font-size: 11px; font-weight: 800; padding: 0 7px; border-radius: 8px;
    background: color-mix(in srgb, var(--act) 18%, var(--tile)); color: var(--ink-act, var(--act));
    font-family: var(--num); font-variant-numeric: tabular-nums; }
  body.page-macro .cb-live { width: 8px; height: 8px; border-radius: 50%; background: var(--up);
    box-shadow: 0 0 8px var(--up); flex: none; }
  body.page-macro .cb-sub { font-size: 12.5px; font-weight: 700; color: var(--ink-2); margin: 0 0 9px;
    display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
  body.page-macro .cb-sub a { margin-left: auto; }
  /* `.alert.alert-dislocation` removed 2026-07-30 — nothing has emitted that class
     since the alerts pane moved to the `.ms-sig` idiom; it styled an element that no
     longer exists. The live announcement is the `.ms-sig sev-act` entry in the alerts
     popover, which takes its colour from `sev-act` like every other alert. */
  /* No `#dislocation` rule here any more: the stress-filter readout left this page
     for macro_signals.html on 2026-07-30, so both announcement surfaces below link
     out cross-page rather than scrolling to an in-page anchor. */
  /* fused equity-internal RISK STATE banner (engine/risk_state.py). When the state is
     elevated+ (alert) it FLOATS above the regime hero and pulses loudly; at 'caution'
     it renders inline in the risk section (informative, not dominating). It is now the
     only floating risk surface on the page — the acute dislocation filter above no
     longer floats. The early-warning that LEADS the credit gauge; the dislocation
     strip is the late, falling-knife filter. */
  body.page-macro #risk-state { scroll-margin-top: 16px; border-left: 4px solid var(--rs); }
  body.page-macro #risk-state.rs-float { order: -1; }
  /* Perf: loud-state pulse = pseudo animating ONLY opacity (compositor); the old
     box-shadow keyframes repainted the panel every frame (2026-07-21 mobile audit). */
  body.page-macro #risk-state.rs-loud, body.page-macro #risk-radar.rr-loud { position: relative; }
  body.page-macro #risk-state.rs-loud::after, body.page-macro #risk-radar.rr-loud::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    box-shadow: 0 0 16px 2px var(--rs-glow);
    opacity: 0; animation: mmGlowBreathe 2.2s ease-in-out infinite; }
  @media (prefers-reduced-motion: reduce) {
    body.page-macro #risk-state.rs-loud::after, body.page-macro #risk-radar.rr-loud::after {
      animation: none; opacity: .6; } }
  body.page-macro #risk-state .rs-head { font-size: 19px; font-weight: 800; color: var(--rs); letter-spacing: .2px; }
  body.page-macro #risk-state .rs-score { font-variant-numeric: tabular-nums; }
  body.page-macro #risk-state .rs-driver { display:flex; align-items:baseline; gap:8px; padding:3px 0; }
  body.page-macro #risk-state .rs-bar { height:6px; border-radius:3px; background:var(--rs); opacity:.85; }
  /* ---- Sector heat strip (macro-only, DISPLAY-ONLY) ---- */
  .sh-strip { padding: 8px 14px 10px; }
  .sh-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
  .sh-title { font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
              color: var(--ink-2); }
  .sh-asof { font-size: 10px; margin-left: auto; font-variant-numeric: tabular-nums; }
  .sh-chips { display: flex; flex-wrap: wrap; gap: 5px 6px; align-items: center; }
  .sh-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 20px;
             font-size: 11px; font-weight: 700; border: 1px solid var(--line); color: var(--muted);
             background: var(--panel2); text-decoration: none; white-space: nowrap;
             transition: filter .1s; }
  .sh-chip:hover { filter: brightness(1.07); border-color: currentColor; }
  .sh-heat { color: var(--ink-up, var(--up)); border-color: color-mix(in srgb, var(--up) 38%, var(--line));
             background: color-mix(in srgb, var(--up) 9%, var(--panel)); }
  .sh-cool { color: var(--ink-down, var(--down)); border-color: color-mix(in srgb, var(--down) 30%, var(--line));
             background: color-mix(in srgb, var(--down) 8%, var(--panel)); }
  .sh-arr { font-size: 9px; flex: none; }
  .sh-rk { font-size: 9px; opacity: .7; font-variant-numeric: tabular-nums; }
  .sh-div { color: var(--muted); font-size: 12px; padding: 0 2px; }
  /* Market Risk Radar v2 (engine/risk_radar.py) — the PRIMARY top-of-page risk read. Floats above
     the regime hero (below the acute dislocation filter) and pulses when the gated loud banner fires. */
  body.page-macro #risk-radar { scroll-margin-top: 16px; border-left: 4px solid var(--rr); }
  body.page-macro #risk-radar.rr-float { order: -1; }
  /* rr-loud pulse: shares the compositor pseudo defined beside #risk-state above */
  body.page-macro #risk-radar .rr-head { font-size: 20px; font-weight: 800; color: var(--rr); letter-spacing: .2px; }
  body.page-macro #risk-radar .rr-prob { font-variant-numeric: tabular-nums; }
  body.page-macro #risk-radar .rr-scare { border: 1px solid var(--line); border-radius: 8px; padding: 6px 9px; }
  body.page-macro #risk-radar .rr-chip { display: inline-block; font-size: 10.5px; padding: 1px 6px; border-radius: 6px; background: var(--panel2); border: 1px solid var(--line); color: var(--muted); margin: 0 3px 3px 0; }

  @media (max-width: 900px) {
    body.page-macro .qmini { grid-template-columns: repeat(2, 34px); grid-template-rows: repeat(2, 34px); }
    body.page-macro h1.hr-name { font-size: 30px; }
    body.page-macro #regime-radar > .howto { text-align: left; }
    body.page-macro .cb-tab { padding: 7px 12px; font-size: 12.5px; }
  }

  /* ── TS-U3: live basket tape band (dtp-* namespace; stocks page only) ─── */
  /* own grid panel below the standout stocks (2026-07-11) — id beats .panel
     specificity so the zero padding wins; the .dtp rows carry their own. */
  #dash-tape-band { background:var(--panel2); display:none; margin:0; padding:0; overflow:hidden; }
  #dash-tape-band.visible { display:block; }
  .ftr-t1-help { display:inline-flex; align-items:center; justify-content:center; width:14px; height:14px; border-radius:50%; border:1px solid var(--line); color:var(--muted); font-size:9.5px; font-weight:700; cursor:help; line-height:1; vertical-align:middle; }
/* page-scoped fold — every V2 action lane shows only its top 3 rows initially */
.actbody.act-fold.is-collapsed > a.actitem:nth-child(n+4),
.actbody.act-fold.is-collapsed > div:nth-child(n+4) { display: none; }
/* Hide the Show-more button when the lane holds fewer rows than its cap.
   All five lanes now share the same top-three contract. */
.actcol:not(:has(.actbody.act-fold > a.actitem:nth-child(4))):not(:has(.actbody.act-fold > div:nth-child(4))):not(:has(.ab-trim-fold > a.actitem:nth-child(4))):not(:has(.ab-trim-fold > div:nth-child(4))) .lst-more.act-more { display: none; }
.ab-trim-fold.is-collapsed > a.actitem:nth-child(n+4),
.ab-trim-fold.is-collapsed > div:nth-child(n+4) { display: none; }
/* Stand-aside keeps its stable id and uses the shared cap-3 fold. */
.lst-collapse.lst-cap3.is-collapsed > a.actitem:nth-child(n+4),
.lst-collapse.lst-cap3.is-collapsed > div:nth-child(n+4) { display: none; }
/* Sector-setups table (unchanged) */
#sectors table.act-fold.is-collapsed > tbody > tr:nth-child(n+8), #sectors table.act-fold.is-collapsed > tr:nth-child(n+8) { display:none; }

  /* ── TS-U3: per-stock turn setups table ─────────────────────────────────── */
  .dash-mtf-section { margin-top:14px; }
  /* rest-state fold: 12 rows visible, the rest behind the JS "Show all" toggle */
  .dash-mtf-collapse.is-collapsed tbody tr:nth-child(n+13) { display:none; }
  .dash-mtf-more { margin-top:8px; }
  .dash-mtf-tbl { width:100%; border-collapse:collapse; margin-top:7px; font-size:11.5px; }
  .dash-mtf-tbl th { text-align:left; font-weight:700; color:var(--muted); font-size:10px; text-transform:uppercase; letter-spacing:.03em; padding:3px 6px; border-bottom:1px solid var(--line); }
  .dash-mtf-tbl td { text-align:left; padding:4px 6px; border-bottom:1px solid var(--line); }
  .dash-mtf-tbl tr:hover { background:color-mix(in srgb,var(--muted) 4%,transparent); }
  .dash-mtf-badge { display:inline-flex; align-items:center; padding:1px 6px; border-radius:10px; font-size:9px; font-weight:800; letter-spacing:.04em; white-space:nowrap; }
  .dash-mtf-badge.confirmed { background:color-mix(in srgb,var(--up) 14%,transparent); border:1px solid color-mix(in srgb,var(--up) 36%,transparent); color:var(--ink-up, var(--up)); }
  .dash-mtf-badge.watch { background:color-mix(in srgb,var(--info) 12%,transparent); border:1px solid color-mix(in srgb,var(--info) 30%,transparent); color:var(--ink-info, var(--info,var(--link))); }
  .dash-mtf-badge.none { background:color-mix(in srgb,var(--muted) 8%,transparent); border:1px solid color-mix(in srgb,var(--muted) 18%,transparent); color:var(--muted); }
  .dash-mtf-leg { display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:4px; font-size:9px; font-weight:700; }
  .dash-mtf-leg.on { background:color-mix(in srgb,var(--up) 18%,transparent); color:var(--ink-up,var(--up)); border:1px solid color-mix(in srgb,var(--ink-up,var(--up)) 30%,transparent); }
  .dash-mtf-leg.off { background:color-mix(in srgb,var(--muted) 8%,transparent); color:var(--muted); border:1px solid color-mix(in srgb,var(--muted) 18%,transparent); }
  .dash-mtf-leg.partial { background:color-mix(in srgb,var(--warn) 10%,transparent); color:var(--ink-warn, var(--warn)); border:1px solid color-mix(in srgb,var(--warn) 25%,transparent); }
  /* U7: ring state — running trend (histogram positive, no recent cross; does not count toward K) */
  .dash-mtf-leg.trend { background:transparent; color:var(--ink-up, var(--up)); border:1.5px solid color-mix(in srgb,var(--up) 50%,transparent); }
  .dash-mtf-legs { display:flex; gap:3px; align-items:center; }
  .dash-mtf-since { font-size:10px; color:var(--muted); font-variant-numeric:tabular-nums; }
  .dash-mtf-baskets { font-size:10px; color:var(--muted); max-width:160px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .dash-mtf-phase { font-size:10px; color:var(--muted); }
  .dash-mtf-absent { font-size:12px; color:var(--muted); padding:10px 0; }
  .dash-mtf-k { font-weight:700; font-variant-numeric:tabular-nums; font-size:11px; }

  /* ── TS-R6: two-reads reconciliation chip ───────────────────────────────── */
  .two-reads-chip { display:inline-flex; align-items:flex-start; gap:4px; padding:2px 8px; border-radius:6px; font-size:10px; font-weight:600;
    /* was white-space:nowrap — the chip is flex:none inside .actitem{overflow:hidden},
       so in the TAKE PROFITS lane the pill ran past the card's rounded corner and the
       label was cut mid-word ('broad sector AC'). The file's own .ab-chip--wrap note
       warns that white-space alone is not enough; the shrink pair is what fixes it.
       DOCTRINE §3: full display names WRAP, never truncate. */
    white-space:normal; line-height:1.35; flex:0 1 auto; min-width:0; max-width:100%; background:color-mix(in srgb,var(--info) 9%,var(--panel2)); border:1px solid color-mix(in srgb,var(--info) 28%,var(--line)); color:var(--ink-info, var(--info,var(--link))); cursor:help; }
  .two-reads-chip .tr-sep { opacity:.45; margin:0 2px; }
