
/* ============== TOKENS — "Swiss Modernism 2.0" ==============
 * Light-first, grid-based, typography-driven dashboard. White fields, 1px hairlines,
 * generous whitespace, one red accent. Red=涨 / green=跌 + red/amber/grey severity
 * stay sacred. Depth comes from spacing and subtle elevation, not heavy borders.
 * AA-recomputed 2026-06-16 from the live tokens (resting + hover/active pairs); see audit. */
:root{
  /* - neutrals & ink (concrete, light hero) - */
  --bg:#FAFAFA;             /* the page field — near-white, +0 step */
  --surface:#FFFFFF;        /* +1 stepped module surface (header/footer strip, dialogs) */
  --surface-2:#F3F4F6;      /* +2 inset cells, sticky theads, count tags, I1-2 chip */
  --surface-3:#E5E7EB;      /* +3 :active press on INK-ONLY controls — never under a colored value */
  --border:#E5E7EB;         /* 1px hairline — internal grid/row/cell rules only */
  --border-strong:#868D9A;  /* sub-divider (zone-head, KPI dividers) — >=3:1 */
  --border-heavy:#111827;   /* module box outline */
  --ink-hero:#111827;       /* loudest ink (hero numerals, module IDs) */
  --ink:#111827;            /* primary text / titles */
  --ink-dim:#4B5563;        /* secondary text */
  --muted:#5F6775;          /* mono labels, timestamps, status codes (AA floor 5.68:1 on bg) */
  --zebra:#F3F4F6;          /* even table rows */
  --backdrop:rgba(0,0,0,.35);   /* dimming scrim behind the 3 elevated surfaces */
  --shadow-card:0 1px 2px rgba(0,0,0,.04);
  --shadow-elevated:0 20px 40px rgba(0,0,0,.12);
  --primary:#111827;
  --on-primary:#FFFFFF;

  /* - accent: single red accent for CTAs, severity, and A-share up - */
  --accent:#DC2626;             /* red accent fill */
  --accent-ink:#C81E1E;         /* red accent text/border */
  --accent-soft:rgba(220,38,38,.08);  /* hover/active tint (row hover + tape press hold) */
  --btn-ink:#FFFFFF;            /* text on primary/accent fills */
  --focus:#111827;              /* inner band of the 2px focus ring */

  /* - semantic: price axis (RED=up/涨, GREEN=down/跌; sacred) - */
  --up:#C81E1E;             /* up — body-size red text/cell */
  --up-strong:#B91C1C;      /* up at large/hero (KPI numeral >=24px) */
  --down:#147336;           /* down — AA-correct A-share green */

  /* - semantic: importance/severity axis (RED=I4-5, AMBER=I3, GREY=I1-2) - */
  --crit:#C81E1E;           /* I4-5 severity red (separate role from --up) */
  --crit-soft:rgba(220,38,38,.10);      /* decoupled from --up-soft */
  --warn:#B45309;           /* I3 — bronze amber for AA as text on concrete */
  --warn-soft:rgba(180,83,9,.12);
  --calm:#5F6775;           /* I1-2 neutral grey (never green) */

  /* - typography: JetBrains Mono for figures/system labels, Archivo for Latin UI,
   *   and Noto Sans SC as the CJK fallback. - */
  --mono:"JetBrains Mono","IBM Plex Mono",ui-monospace,"SF Mono","Cascadia Code",Consolas,monospace;
  --font-cjk:"Noto Sans SC","Source Han Sans SC","PingFang SC","Microsoft YaHei",sans-serif;
  --font:"Archivo","Inter Tight","Helvetica Neue","Helvetica","Arial",var(--font-cjk);
  --fs-2xs:11px; --fs-xs:12px; --fs-sm:13px; --fs-md:14px;
  --fs-lg:16px; --fs-2xl:24px;
  --fs-score-sm:20px;       /* drawer scores numeral */
  --fs-score:24px;          /* board ledger numeral / signal-rail score */
  --fs-data:42px;           /* brutalist hero numerals — KPI band, board count, header clock */
  --fs-tk:30px;             /* ticker-rail KPI numeral (between --fs-score and --fs-data) */
  --lh-tight:1.05;          /* hero numerals, single-line module ids */
  --lh-snug:1.25;           /* titles, KPI captions, drawer headline */
  --lh-body:1.45;           /* prose, multi-line summaries, table cells */

  /* - shape: Swiss hard edges, 0px radius except 2px focus-ring caps - */
  --r-0:0px;                /* everything structural — modules, panels, tags, inputs, buttons, tabs, dialogs */
  --r-micro:2px;            /* the ONLY curved things — state-square, spine cap, focus-ring corners */

  /* - spacing grid (4px base) - */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px;
  --row-gap:var(--sp-3);    /* rail→content gutter (=12px) */
  --read-measure:68ch;      /* per-row reading-text measure (title/summary/event); the right data rail uses the rest of the full width */

  /* - motion: state/feedback only, 150–300ms, respect reduced-motion - */
  --ease:cubic-bezier(.2,0,.2,1);
  --ease-out:cubic-bezier(.2,0,.2,1);
  --ease-out-quart:cubic-bezier(0.25,1,0.5,1);
  --ease-out-expo:cubic-bezier(0.16,1,0.3,1);
  --ease-io:ease-in-out;    /* the one symmetric loop: skeleton pulse */
  --dur-1:150ms;            /* hover/focus/press/sort/poll-tick state feedback */
  --dur-2:200ms;            /* drawer slide / dialog open */
  --dur-3:1200ms;           /* skeleton pulse (the one perpetual loop) */

  /* - sizing & geometry - */
  --strip-h:56px;           /* header status strip (rails sticky at top:var(--strip-h)) */
  --bar-h:32px;             /* footer status bar */
  --scroll-h-sm:280px;      /* compact watch-hits scroll */
  --spine-w:3px;            /* row severity / tier spine */
  --spine-w-sub:1px;        /* event-sub guide / fine divider */
  --spark-dim:.35;          /* single-board/low-value sparkline bar opacity */
  --row-py:10px;            /* nominal row vertical metric; drives --spine-inset only (actual row padding is --sp-3) */
  --row-lh:1.4;             /* row title line-height */
  --spine-inset:calc(var(--row-py) - 2px);          /* spine vertical inset, derived from row padding */
  --row-inset:calc(var(--sp-3) - var(--spine-w));   /* text-column left rail (empty + skeleton align to row text) */

  /* - z-index - */
  --z-module-head:20; --z-table-head:30; --z-sticky:50; --z-popover:150; --z-overlay:200; --z-dialog:201;
  color-scheme:light;
}
:root[data-theme="dark"]{
  /* === Swiss Modernism 2.0 — dark variant (slate, not inverted) === */
  /* - neutrals: warm near-black + luminance-stepped surfaces (depth = borders + light, not shadow) - */
  --bg:#0F172A;             /* warm near-black (NOT blue-black, NOT pure #000) */
  --surface:#1E293B;        /* +1 stepped module surface */
  --surface-2:#334155;      /* +2 inset cells, sticky theads, count tags */
  --surface-3:#475569;      /* +3 :active press on ink-only controls */
  --border:#334155;         /* 1px hairline */
  --border-strong:#64748B;  /* sub-divider >=3:1 */
  --border-heavy:#94A3B8;   /* module box outline */
  --ink-hero:#F8FAFC;
  --ink:#F8FAFC;            /* 13.98:1 on --bg */
  --ink-dim:#CBD5E1;
  --muted:#A3B0C2;
  --zebra:#1E293B;
  --backdrop:rgba(0,0,0,.55);
  --shadow-card:0 1px 2px rgba(0,0,0,.2);
  --shadow-elevated:0 20px 40px rgba(0,0,0,.4);
  --primary:#F8FAFC;
  --on-primary:#0F172A;

  /* - accent: red serves fill+ink+focus+warn on dark - */
  --accent:#EF4444;
  --accent-ink:#FCA5A5;
  --accent-soft:rgba(239,68,68,.12);   /* red soft wash */
  --btn-ink:#0F172A;        /* text on bright accent/primary fill */
  --focus:#F8FAFC;

  /* - semantic: price axis (sacred, self-luminous on the dark field) - */
  --up:#FCA5A5;             /* 涨 */
  --up-strong:#EF4444;      /* 涨 at large/hero */
  --down:#34D399;           /* 跌 */

  /* - semantic: importance/severity axis - */
  --crit:#FCA5A5;
  --crit-soft:rgba(248,113,113,.16);
  --warn:#FBBF24;
  --warn-soft:rgba(251,191,36,.16);
  --calm:#94A3B8;

  color-scheme:dark;
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
html{scroll-behavior:smooth}
h1,h2,h3,h4,.card-title,.rail-title,.sig-title,.event-card-title,.inline-detail h2{text-wrap:balance}
p,.content,.detail-lede,.detail-rationale,.control-hint,.pane-meta{text-wrap:pretty}
body{
  font-family:var(--font);
  background:var(--bg);
  color:var(--ink);
  font-size:var(--fs-sm);
  line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
button,input,select{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0;color:inherit;text-align:left}
input,select{outline:none}
a{color:var(--accent-ink)}

/* one global keyboard focus ring (non-color-only) */
.skip-link{position:absolute;left:-9999px;z-index:var(--z-dialog);padding:var(--sp-2) var(--sp-4);background:var(--surface);border:2px solid var(--focus);color:var(--ink);font-size:var(--fs-sm);font-weight:600;text-decoration:none}
.skip-link:focus{position:fixed;top:var(--sp-2);left:var(--sp-2)}
:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--focus),0 0 0 4px var(--ink-hero);
  border-radius:var(--r-micro);
}
/* full-bleed ledger rows are square: the ring follows the row, not a 6px control radius */
.stream-item:focus-visible,.board-card:focus-visible,.evt-toggle:focus-visible,.bt-row:focus-visible,.event-sub-item:focus-visible{border-radius:var(--r-micro)}
/* tab panes take programmatic focus (skip link / tab switch) as a reading-order
 * anchor, not an interactive target — never draw the pane-sized ring */
.tab-pane:focus,.tab-pane:focus-visible{box-shadow:none;outline:none}

/* ============== LOCK SCREEN (boxed overlay #1) ============== */
.locked{
  min-height:100dvh;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:var(--sp-6);
}
.lock-card{
  width:min(420px,100%);
  background:var(--surface);
  border:1px solid var(--border-heavy);
  border-radius:var(--r-0);
  box-shadow:var(--shadow-card);
  padding:var(--sp-6) var(--sp-5);
}
.lock-error{color:var(--crit);font-size:var(--fs-sm);margin-top:var(--sp-2);text-align:left}
.lock-logo{
  width:28px;height:28px;
  border-radius:var(--r-0);
  background:var(--surface-2);
  border:1px solid var(--border);
  color:var(--ink);
  display:inline-flex;align-items:center;justify-content:center;
}
.lock-logo svg{width:22px;height:22px;display:block}
.lock-card h1{
  font-size:var(--fs-2xl);
  font-weight:700;
  line-height:var(--lh-snug);
  letter-spacing:-.02em;
  margin:var(--sp-3) 0 var(--sp-2);
}
.lock-card p{color:var(--muted);margin-bottom:var(--sp-5);font-size:var(--fs-sm)}
.lock-form{display:grid;grid-template-columns:1fr auto;gap:var(--sp-2)}
.lock-form input{
  min-height:44px;
  border-radius:var(--r-0);
  background:var(--bg);
  border:1px solid var(--border);
  padding:0 var(--sp-4);
  color:var(--ink);
  transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
}
.lock-form input::placeholder{color:var(--muted)}

/* ============== BUTTONS ============== */
.btn{
  min-height:44px;
  padding:0 var(--sp-4);
  border-radius:var(--r-0);
  background:var(--primary);
  color:var(--on-primary);
  font-weight:600;
  font-size:var(--fs-sm);
  display:inline-flex;
  align-items:center;
  gap:var(--sp-2);
  white-space:nowrap;
  border:1px solid transparent;
  transition:background var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
/* primary fill button: state change via subtle border keyline */
.btn:hover{border-color:var(--ink-dim)}
.btn:active{background:var(--ink-dim)}
.btn:disabled{opacity:.4;cursor:default}
.btn .icon-trail{display:inline-flex;align-items:center;justify-content:center}
.btn svg{width:15px;height:15px}

.icon-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-width:44px;min-height:44px;
  padding:var(--sp-2);
  border-radius:var(--r-0);
  color:var(--muted);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.icon-btn:hover{background:var(--surface-2);color:var(--ink)}
.icon-btn svg{width:16px;height:16px}
.icon-btn-text{font-weight:600;font-size:var(--fs-sm)}   /* text glyph (e.g. lang switch) */
.icon-btn-text.icon-btn-xs{font-size:var(--fs-xs)}       /* lang "EN" text glyph */

/* ============== SWISS BUTTON & FILTER SYSTEM ============== */
/* Hard-cornered, 1px-hairline instrument controls. Modifiers layer on the
 * existing .btn base so primary CTA behavior is unchanged. */

/* -- Sizes -- */
/* one instrument rhythm: 34px is the only small-control height (28px retired) */
.btn--sm{min-height:34px;padding:0 var(--sp-3);font-size:var(--fs-xs)}
.btn--lg{min-height:44px;padding:0 var(--sp-5);font-size:var(--fs-md)}

/* -- Secondary / outlined action -- */
.btn--secondary{
  background:transparent;
  color:var(--ink);
  border-color:var(--border-strong);
}
.btn--secondary:hover{background:var(--surface-2)}
.btn--secondary:active{background:var(--surface-3);color:var(--ink)}
.btn--secondary:disabled{opacity:.4;border-color:var(--border)}

/* -- Segmented button group (single-choice) -- */
/* no overflow:hidden — the corners are already square and clipping would cut
   the two-tone focus ring on the segments */
.btn-group{
  display:inline-flex;
  align-items:stretch;
  border:1px solid var(--border-strong);
  border-radius:var(--r-0);
}
.btn-group .btn--segment{
  min-height:34px;
  padding:0 var(--sp-3);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  font-weight:600;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:var(--ink-dim);
  background:transparent;
  border:0;
  border-right:1px solid var(--border);
  border-radius:0;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.btn-group .btn--segment:last-child{border-right:0}
/* explicit border-color: the base .btn:hover ink-dim keyline must not tint the divider */
.btn-group .btn--segment:hover{background:var(--surface-2);color:var(--ink);border-color:var(--border)}
.btn-group .btn--segment:active{background:var(--surface-3);color:var(--ink);border-color:var(--border)}
.btn-group .btn--segment.is-active{
  background:var(--primary);
  color:var(--on-primary);
  border-color:var(--border);
}
.btn-group .btn--segment.is-active:active{background:var(--ink-dim)}
.btn-group .btn--segment:disabled{opacity:.4}
/* focused segment lifts above its siblings so the ring is never overlapped */
.btn-group .btn--segment:focus-visible{position:relative;z-index:1}

/* -- Filter pills (multi-toggle or single-toggle) -- */
.btn--filter,
.btn--filter-accent{
  min-height:34px;
  padding:0 var(--sp-3);
  font-size:var(--fs-xs);
  font-weight:600;
  background:transparent;
  color:var(--ink-dim);
  border:1px solid var(--border);
  border-radius:var(--r-0);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
/* the accent pill is an action chip (e.g. back-to-live): red ink identity at rest */
.btn--filter-accent{color:var(--accent-ink);border-color:var(--accent-ink)}
/* explicit border-color so the base .btn:hover ink-dim keyline never leaks in */
.btn--filter:hover{background:var(--surface-2);color:var(--ink);border-color:var(--border-strong)}
.btn--filter-accent:hover{background:var(--accent-soft);color:var(--accent-ink);border-color:var(--accent-ink)}
/* press: ink-only chips darken to --surface-3 with the label promoted to ink;
   the accent chip carries a colored label, so it HOLDS the accent-soft wash
   (AA: accent-ink fails on surface-3). Both override the base .btn:active
   ink-dim fill, which would crush chip labels dark-on-dark. */
.btn--filter:active{background:var(--surface-3);color:var(--ink);border-color:var(--border-strong)}
.btn--filter-accent:active{background:var(--accent-soft);color:var(--accent-ink);border-color:var(--accent-ink)}
.btn--filter.is-active,
.btn--filter[aria-pressed="true"]{
  background:var(--primary);
  color:var(--on-primary);
  border-color:var(--primary);
}
.btn--filter-accent.is-active,
.btn--filter-accent[aria-pressed="true"]{
  background:var(--accent);
  color:var(--btn-ink);
  border-color:var(--accent);
}
/* pressed active chips step like the active segment (fill, never surface-3) */
.btn--filter.is-active:active,
.btn--filter[aria-pressed="true"]:active{background:var(--ink-dim);color:var(--on-primary);border-color:var(--ink-dim)}
.btn--filter-accent.is-active:active,
.btn--filter-accent[aria-pressed="true"]:active{background:var(--accent-ink);color:var(--btn-ink);border-color:var(--accent-ink)}
/* chips carrying the red industry count: the count follows the chip ink on
   fill/press so no red numeral ever lands on a dark or surface-3 ground */
.btn--filter.is-active .industry-count,
.btn--filter[aria-pressed="true"] .industry-count,
.btn--filter:active .industry-count{color:inherit}
.btn--filter:disabled,
.btn--filter-accent:disabled{opacity:.4}

/* -- Disabled: one vocabulary — dim, default cursor, inert (hover restyles
   guarded). The busy variant re-enables pointer-events so cursor:wait shows. -- */
.btn:disabled,.btn--secondary:disabled,.btn-group .btn--segment:disabled,
.btn--filter:disabled,.btn--filter-accent:disabled,
.select-btn select:disabled,.icon-btn:disabled,.input-group__clear:disabled{
  opacity:.4;cursor:default;pointer-events:none;
}
.btn[aria-busy="true"]:disabled{opacity:.72;cursor:wait;pointer-events:auto}
.btn[aria-busy="true"]:disabled:hover{border-color:transparent}

/* -- Filter pill row -- */
.filter-row{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--sp-2);
}
.filter-row .btn--filter,
.filter-row .btn--filter-accent{flex:none}
.filter-row--inline{margin-top:var(--sp-1);min-height:0}
.filter-row--inline:empty{display:none}

/* -- Search input group -- */
.input-group{
  position:relative;
  display:inline-flex;
  align-items:center;
  min-height:34px;
  background:var(--surface);
  border:1px solid var(--border-strong);  /* same enclosure weight as select/segment fields */
  border-radius:var(--r-0);
  transition:border-color var(--dur-1) var(--ease);
}
.input-group:focus-within{border-color:var(--focus)}
/* group ring only for the input itself — a focused clear button carries its own ring */
.input-group:has(.input:focus-visible){
  box-shadow:0 0 0 2px var(--focus),0 0 0 4px var(--ink-hero);
  border-radius:var(--r-micro);
}
.input-group .input:focus-visible{box-shadow:none}
.input-group__icon{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  padding-left:var(--sp-3);
  color:var(--muted);
}
.input-group__icon svg{width:14px;height:14px}
.input-group .input{
  flex:1;
  min-height:34px;
  padding:0 var(--sp-3);
  background:transparent;
  border:0;
  color:var(--ink);
  font-size:var(--fs-sm);
}
.input-group .input::placeholder{color:var(--muted)}
.input-group .input:focus{outline:none}
/* the custom clear button is the single clear affordance — hide the UA one */
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration{-webkit-appearance:none;appearance:none}
.input-group__clear{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:28px;height:28px;
  margin-right:var(--sp-1);
  color:var(--muted);
  border-radius:var(--r-0);
  flex:none;
}
.input-group__clear:hover{background:var(--surface-2);color:var(--ink)}
.input-group__clear:active{background:var(--surface-3);color:var(--ink)}
.input-group__clear[hidden]{display:none}

/* -- Native select dressed as a secondary button -- */
.select-btn{
  position:relative;
  display:inline-flex;
  align-items:center;
}
.select-btn select{
  appearance:none;-webkit-appearance:none;
  min-height:34px;
  padding:0 30px 0 14px;
  background:transparent;
  color:var(--ink);
  border:1px solid var(--border-strong);
  border-radius:var(--r-0);
  font-size:var(--fs-sm);
  font-weight:600;
  cursor:pointer;
  transition:background var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
.select-btn select:hover{background:var(--surface-2)}
.select-btn select:active{background:var(--surface-3)}
.select-btn select:focus{border-color:var(--focus);outline:none}
.select-btn select:disabled{opacity:.4;border-color:var(--border)}
.select-btn:has(select:disabled)::after{opacity:.4}
.select-btn::after{
  content:"";
  position:absolute;
  right:var(--sp-3);top:50%;
  width:11px;height:11px;
  transform:translateY(-50%);
  pointer-events:none;
  background-color:var(--muted);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' fill='none' stroke='black' stroke-width='1.5'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' fill='none' stroke='black' stroke-width='1.5'/%3E%3C/svg%3E") center/contain no-repeat;
}
.select-btn option{background:var(--surface);color:var(--ink)}

/* -- Date picker button -- */
.date-btn{position:relative;display:inline-flex;flex-direction:column;gap:var(--sp-1)}
.date-btn__label{font-size:var(--fs-xs);font-weight:500;color:var(--muted)}
.date-btn .btn--secondary{gap:var(--sp-2)}
.date-btn .btn--secondary svg{width:14px;height:14px;color:var(--muted)}
/* the value is a date figure — mono tnum per the numeral grammar */
.date-btn__value{
  font-family:var(--mono);
  font-weight:600;
  font-variant-numeric:tabular-nums slashed-zero lining-nums;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.date-btn__input{
  position:absolute;
  opacity:0;
  width:1px;height:1px;
  pointer-events:none;
}

/* -- Dropdown button (custom menu) -- */
.dropdown{position:relative;display:inline-flex}
.dropdown__trigger{gap:var(--sp-2);padding-right:10px}
.dropdown__caret{
  display:inline-flex;
  width:11px;height:11px;
  color:var(--muted);
  transition:transform var(--dur-1) var(--ease);
}
.dropdown[open] .dropdown__caret,
.dropdown.is-open .dropdown__caret{transform:rotate(180deg)}
.dropdown__menu{
  position:absolute;
  top:calc(100% + 4px);
  right:0;
  min-width:160px;
  z-index:var(--z-popover);
  margin:0;padding:4px;
  list-style:none;
  background:var(--surface);
  border:1px solid var(--border-heavy);
  border-radius:var(--r-0);
  box-shadow:var(--shadow-elevated);
}
.dropdown__menu[hidden]{display:none}
.dropdown__menu li{
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-3);
  font-size:var(--fs-sm);
  color:var(--ink);
  cursor:pointer;
  transition:background var(--dur-1) var(--ease);
}
.dropdown__menu li:hover{background:var(--accent-soft)}
.dropdown__menu li[aria-selected="true"]{
  background:var(--accent-soft);
  box-shadow:inset 2px 0 0 var(--focus);
}

/* ============== APP SHELL — status strip ============== */
#app{display:none;min-height:100dvh;flex-direction:column}
.topbar{
  position:sticky;
  top:0;
  z-index:var(--z-sticky);
  background:var(--surface);
  border-bottom:1px solid var(--border-heavy);
}
.topbar-inner{
  max-width:1440px;
  margin:0 auto;
  padding:0 var(--sp-5);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-2);
  min-height:var(--strip-h);
}
/* topbar groups: brand, tabs, and status/controls are distinct visual zones */
.topbar-group{display:flex;align-items:center;gap:var(--sp-2)}
.topbar-start{flex:none;gap:var(--sp-3)}
.topbar-center{flex:1 1 auto;justify-content:center;min-width:min-content;gap:var(--sp-1)}
.topbar-end{flex:none;gap:0}
.nav-brand{display:flex;align-items:center;gap:var(--sp-2);margin:0}
.nav-logo{
  width:22px;height:22px;
  border-radius:var(--r-0);
  background:var(--surface-2);
  border:1px solid var(--border);
  color:var(--ink);
  display:inline-flex;align-items:center;justify-content:center;
}
.nav-logo svg{width:18px;height:18px;display:block}
.nav-brand-text{font-size:var(--fs-md);font-weight:600;letter-spacing:-.01em}
.nav-tabs{display:flex;align-items:stretch;gap:2px;align-self:stretch}
.tab-btn{
  display:inline-flex;
  align-items:center;
  min-height:44px;
  padding:0 var(--sp-3);
  font-size:var(--fs-sm);
  font-weight:500;
  color:var(--muted);
  box-shadow:inset 0 -2px 0 transparent;
  transition:color var(--dur-1) var(--ease),background var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
  white-space:nowrap;
}
.tab-btn:hover{color:var(--ink);background:var(--surface-2)}
.tab-btn.active{color:var(--ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--focus)}
.tab-btn.active:focus-visible{box-shadow:0 0 0 2px var(--focus),0 0 0 4px var(--ink-hero)}
/* status cluster: compact instrument panel on the right */
.nav-status{
  display:flex;
  align-items:center;
  gap:var(--sp-1);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  font-weight:500;
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  white-space:nowrap;
}
.nav-status b{color:var(--ink-dim);font-weight:600}
.status-cluster{
  display:flex;
  align-items:center;
  gap:var(--sp-1);
  padding:2px var(--sp-2);
  background:var(--surface-2);
  border-radius:var(--r-0);
}
.controls-cluster{
  display:flex;
  align-items:center;
  gap:var(--sp-1);
  padding-left:var(--sp-1);
  border-left:1px solid var(--border-strong);
}

.nav-vr{width:1px;height:14px;background:var(--border-strong);flex:none}
/* strip field: uppercase-mono caption beside the live value */
.strip-field{display:inline-flex;align-items:center;gap:var(--sp-2)}
.strip-label{
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
}
#bj-clock{color:var(--ink);font-weight:600;min-width:8ch}
/* market status cluster: one chip per market (A / H / US) */
.mkt-cluster{
  display:inline-flex;align-items:center;gap:2px;
  padding:1px;border-radius:var(--r-0);
  background:var(--surface);border:1px solid var(--border);
}
.mkt-chip{
  display:inline-flex;align-items:center;gap:var(--sp-1);
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  color:var(--ink-dim);background:transparent;white-space:nowrap;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.mkt-chip + .mkt-chip{border-left:1px solid var(--border)}
.mkt-chip.is-open{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}
.mkt-chip.is-open + .mkt-chip{border-left-color:var(--primary)}
.mkt-dot{
  width:5px;height:5px;border-radius:var(--r-micro);
  background:var(--muted);flex:none;
}
.mkt-chip.is-open .mkt-dot{background:var(--on-primary)}
/* legacy single market tag (kept for other surfaces) */
.mkt-tag{
  display:inline-flex;align-items:center;
  padding:2px var(--sp-2);border-radius:var(--r-0);
  font-family:var(--mono);font-size:var(--fs-xs);font-weight:600;
  background:var(--surface-2);color:var(--ink-dim);
  border:1px solid var(--border);white-space:nowrap;
}
.mkt-tag.is-open{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}
/* poll-state square: state-driven, never animated (replaces the pulse ring) */
.state-square{
  width:8px;height:8px;
  border-radius:var(--r-micro);
  background:var(--accent);
  flex:none;
}
.state-square[data-state="live"]{
  background:var(--accent);
  box-shadow:inset 0 0 0 1px var(--btn-ink);
}
.state-square[data-state="stale"]{background:var(--warn)}
.state-square[data-state="error"]{background:var(--crit)}
.state-square[data-state="partial"]{background:transparent;box-shadow:inset 0 0 0 2px var(--warn)}
.state-square[data-state="paused"]{background:transparent;box-shadow:inset 0 0 0 1px var(--muted)}
/* poll-tick: one-shot background flash on the updated-at cell (no brightness) */
@keyframes pollTick{0%{background:var(--accent-soft)}100%{background:transparent}}
#status{border-radius:var(--r-micro);padding:0 var(--sp-1);border:1px solid transparent}
/* SEC: <TAB> section code — display mirror of the active tab (functional) */
.sec-code{display:inline-flex;align-items:center;gap:var(--sp-2);font-family:var(--mono);white-space:nowrap}
.sec-code .sec-label{
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
}
.sec-code b{
  font-family:var(--mono);font-size:var(--fs-xs);font-weight:600;color:var(--ink-dim);
  letter-spacing:.04em;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
/* one-word poll-state echo beside the state square (muted mono, bracketed) */
.state-word{
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);white-space:nowrap;
}
.state-word::before{content:"[ "}
.state-word::after{content:" ]"}
.state-word:empty{display:none}
/* measured poll round-trip latency (mono value, muted unit) */
.lat-ms{color:var(--ink-dim);font-weight:600}
.lat-ms .unit{color:var(--muted);font-weight:500;margin-left:.15ch}
/* the zh latency label (延迟) is CJK — never letter-space/uppercase CJK glyphs */
:lang(zh) [data-i18n="latLabel"]{letter-spacing:0;text-transform:none}

/* ============== FOOTER STATUS BAR (32px, boxed above by 1px heavy rule) ============== */
.statusbar{
  position:fixed;
  left:0;right:0;bottom:0;
  z-index:var(--z-sticky);
  height:var(--bar-h);
  background:var(--surface);
  border-top:1px solid var(--border-heavy);
}
.statusbar-inner{
  max-width:1440px;
  height:100%;
  margin:0 auto;
  padding:0 var(--sp-5);
  display:flex;
  align-items:center;
  gap:var(--sp-3);
  overflow-x:auto;
  scrollbar-width:none;
  white-space:nowrap;
}
.statusbar-inner::-webkit-scrollbar{display:none}
.statusbar-inner,.statusbar-inner dl,.statusbar-inner dt,.statusbar-inner dd{margin:0}
.sb-field{display:inline-flex;align-items:center;gap:var(--sp-2);flex:none;padding:0 var(--sp-3)}
.sb-field:first-child{padding-left:0}
.sb-field + .sb-field{border-left:1px solid var(--border-strong)}
.sb-label{
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
}
.sb-field dd{margin:0}
.sb-field b,.sb-field dd{
  font-family:var(--mono);font-size:var(--fs-xs);font-weight:600;
  color:var(--ink-dim);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
#sb-feed[data-feed="STALE"]{color:var(--warn)}
#sb-feed[data-feed="PARTIAL"]{color:var(--warn)}
#sb-feed[data-feed="FAULT"]{color:var(--crit)}
.sb-poll-paused{color:var(--muted)}

.error-banner{
  display:none;
  align-items:center;
  gap:var(--sp-3);
  max-width:1440px;
  margin:var(--sp-3) auto 0;
  padding:var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  border-radius:var(--r-0);
  background:var(--crit-soft);
  border:1px solid var(--crit);
  color:var(--crit);
  font-size:var(--fs-xs);
  font-family:var(--mono);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.error-banner .retry-btn{
  margin-left:auto;
  padding:var(--sp-2) var(--sp-3);
  border-radius:var(--r-0);
  border:1px solid var(--crit);
  color:var(--crit);
  font-weight:600;
  font-size:var(--fs-xs);
  transition:background var(--dur-1) var(--ease);
}
.error-banner .retry-btn:hover{background:var(--surface)}
.error-banner .retry-btn:active{background:var(--surface-2)}

/* market-relevance emphasis in the detail score grid — red accent,
 * the single allowed data-axis exception (see DESIGN.md Color). */
.score-cell .mr-hi{color:var(--accent-ink);font-weight:600}

/* center column = a vertical stack of boxed modules on the bare concrete field */
.app-main{
  width:100%;
  max-width:none;
  margin:0;
  display:flex;
  flex-direction:column;
  gap:var(--sp-5);
  flex:1;
  min-width:0;
}

/* ============== Swiss module grid (boxed modules with whitespace gutter) ============== */
/* exposed gutter = whitespace between modules; modules use 1px outlines */
.wt-grid{display:grid;grid-template-columns:minmax(240px,320px) minmax(0,1fr) minmax(180px,220px);gap:var(--sp-5);align-items:start;max-width:1520px;margin:0 auto;padding:var(--sp-5) var(--sp-5) calc(var(--bar-h) + var(--sp-5));flex:1;width:100%}
.wt-grid > .app-main{max-width:none;margin:0}
@media (min-width:1440px){
  .wt-grid{grid-template-columns:minmax(280px,340px) minmax(0,1fr) minmax(200px,240px);max-width:1680px}
}
/* rails are boxed modules too, sticky below the 56px header strip */
.wt-rail{position:sticky;top:calc(var(--topbar-h,57px) + var(--sp-5));align-self:start;max-height:calc(100dvh - var(--topbar-h,57px) - var(--bar-h) - var(--sp-6));overflow-y:auto;scrollbar-width:thin;background:var(--surface);border:1px solid var(--border-heavy);border-radius:var(--r-0);padding:var(--sp-4)}
/* no tracking on the head container — it would leak onto the count-pill numerals (never track a tabular column) */
.wt-rail-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-2);font-size:var(--fs-xs);font-weight:600;color:var(--muted);padding:0 0 var(--sp-2) var(--sp-3);margin-bottom:var(--sp-2);border-bottom:1px solid var(--border-strong)}
.rail-head-text{display:flex;flex-direction:column;min-width:0}
.wt-rail-head + .wt-rail-head{margin-top:var(--sp-5)}
.wt-rail-head--sig{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  align-items:start;
  column-gap:var(--sp-2);
  row-gap:var(--sp-1);
  padding-bottom:var(--sp-3);
}
.wt-rail-head--sig .rail-head-text{display:contents}
.wt-rail-head--sig .mod-id{grid-column:1;grid-row:1;min-width:0}
.wt-rail-head--sig .rail-title{grid-column:1 / -1;grid-row:2}
.wt-rail-head--sig .rail-head-actions{grid-column:2;grid-row:1}
.rail-title{font-size:var(--fs-sm);font-weight:600;color:var(--ink);letter-spacing:0;line-height:var(--lh-snug)}
.rail-kicker{display:block;margin-top:2px;font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;letter-spacing:.06em;color:var(--muted);text-transform:uppercase}
.rail-head-actions{display:inline-flex;align-items:center;gap:var(--sp-2)}
.rail-help,.rail-fold-btn{min-width:28px;min-height:28px;color:var(--muted)}
.rail-fold-icon{transition:transform var(--dur-1) var(--ease)}
.wt-rail-left[data-collapsed="true"] .rail-fold-icon{transform:rotate(-90deg)}
@media (pointer: coarse){.rail-help,.rail-fold-btn{min-width:44px;min-height:44px}}
.empty-hint{display:block;margin-top:var(--sp-2);font-size:var(--fs-xs);color:var(--muted)}
/* signal rail rows (ranked, condensed, operator-scan grammar) */
.sig-row{
  position:relative;
  display:grid;
  grid-template-columns:48px minmax(0,1fr);
  gap:var(--sp-3);
  align-items:start;
  width:100%;
  padding:var(--sp-3) 0 var(--sp-3) var(--sp-3);
  text-align:left;
  background:none;
  transition:background var(--dur-1) var(--ease),transform var(--dur-1) var(--ease);
}
.sig-row + .sig-row{border-top:1px solid var(--border)}
.sig-row:hover{background:var(--accent-soft)}
@media (hover:hover) and (pointer:fine){
  .sig-row:hover{transform:translateX(2px)}
}
.sig-scorebox{display:flex;flex-direction:column;align-items:flex-end;gap:2px;min-width:0}
.sig-rank{
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  line-height:1;
  letter-spacing:.06em;
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.sig-score{line-height:1}
.sig-meta{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.sig-facts{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--sp-2);
  min-width:0;
  font-family:var(--mono);
  font-size:var(--fs-xs);
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.sig-source,.sig-sources,.sig-ago,.sig-similar{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sig-source,.sig-sources{max-width:18ch}
.sig-similar{color:var(--ink-dim);font-weight:600}
.sig-context{
  font-size:var(--fs-xs);
  color:var(--muted);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.sig-title{font-size:var(--fs-md);font-weight:600;line-height:var(--lh-body);color:var(--ink);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.sig-time-row{display:flex;flex-wrap:wrap;gap:var(--sp-2);font-family:var(--mono);font-size:var(--fs-xs);color:var(--muted);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
/* ticker rail kpis */
.tk-kpi{padding:var(--sp-2) 0}
.tk-kpi + .wt-rail-head{margin-top:var(--sp-5)}
.tk-v{display:block;font-family:var(--mono);font-size:var(--fs-tk);font-weight:700;line-height:1;color:var(--ink-hero);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;letter-spacing:-.02em}
.tk-kpi.up .tk-v{color:var(--up)}
/* same caption grammar as .kpi-label — a hero numeral always sits beside a tiny uppercase-mono caption */
.tk-l{display:block;margin-top:var(--sp-1);font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
:lang(zh) .tk-l{letter-spacing:0;text-transform:none}
.tk-clock{margin-top:var(--sp-5);font-family:var(--mono);font-size:var(--fs-xs);color:var(--muted);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.tk-clock b{color:var(--ink-dim);font-weight:600}
.rail-list{display:flex;flex-direction:column}
.rail-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--sp-2);align-items:center;padding:var(--sp-2) 0 var(--sp-2) var(--sp-3);border-top:1px solid var(--border)}
.rail-row--seal{grid-template-columns:auto minmax(0,1fr)}
.rail-row:first-child{border-top:0}
.rail-row:hover{background:var(--accent-soft)}
.rail-main{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.rail-name{font-size:var(--fs-sm);font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-meta,.rail-time{font-family:var(--mono);font-size:var(--fs-xs);color:var(--muted);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.rail-row .cell-percent{font-size:var(--fs-sm);min-width:6ch}
.rail-stat-grid{display:grid;gap:var(--sp-2);padding:var(--sp-2) 0}
.rail-stat{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);padding:0 0 0 var(--sp-3)}
.rail-stat dt{font-size:var(--fs-xs);color:var(--muted)}
.rail-stat dd{font-family:var(--mono);font-size:var(--fs-sm);font-weight:700;color:var(--ink-hero);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.rail-stat dd.up{color:var(--up)}
/* ============== HELP DIALOG ============== */
#help-dialog{
  position:relative;
  width:min(520px,92vw);
  max-height:min(720px,90vh);
  margin:auto;
  padding:0;
  border:1px solid var(--border-heavy);
  background:var(--surface);
  box-shadow:var(--shadow-elevated);
  overflow:hidden;
}
#help-dialog .help-dialog-inner{
  padding:var(--sp-6);
  overflow-y:auto;
  max-height:min(720px,90vh);
}
#help-dialog h2{
  font-size:var(--fs-2xl);
  font-weight:700;
  line-height:var(--lh-snug);
  letter-spacing:-.02em;
  margin:var(--sp-1) 44px var(--sp-4) 0;
}
#help-dialog h3{
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--muted);
  margin:var(--sp-5) 0 var(--sp-2);
}
#help-dialog .help-list{
  display:flex;
  flex-direction:column;
  gap:var(--sp-2);
}
#help-dialog .help-list > div{
  display:grid;
  grid-template-columns:80px minmax(0,1fr);
  gap:var(--sp-3);
  align-items:baseline;
}
#help-dialog .help-list dt{
  font-family:var(--mono);
  font-weight:600;
  color:var(--ink-hero);
}
#help-dialog .help-list dd{color:var(--ink-dim)}
#help-dialog .help-legend{
  list-style:none;
  display:flex;
  flex-direction:column;
  gap:var(--sp-2);
}
#help-dialog .help-legend li{
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  color:var(--ink-dim);
}
#help-dialog .help-legend .dot{width:var(--sp-2);height:var(--sp-2);border-radius:var(--r-micro);display:inline-block}

@media (max-width:1024px){
  .wt-grid{grid-template-columns:1fr}
  .wt-grid > .app-main{border-left:0;border-right:0}
  .wt-rail{position:static;max-height:none}
  .wt-rail-left{order:-1}
  .wt-rail-left[data-collapsed="true"] #signal-rail-body{display:none}
  .stocks-table-wrap{overflow-x:auto;overflow-y:visible}
  .stocks-table thead th{top:0}
  .toolbar{align-items:flex-end}
  .toolbar-filters .control,
  .toolbar-filters .control:has(.control-hint){min-height:0}
  .toolbar-filters .control:not(:has(.control-hint))::after,
  .toolbar-filters .control:has(.btn-group):not(:has(.control-hint))::after,
  .toolbar-filters .control:has(.filter-row):not(:has(.control-hint))::after,
  .toolbar-filters .control:has(.input-group):not(:has(.control-hint))::after,
  .toolbar-filters .control:has(.select-btn):not(:has(.control-hint))::after,
  .toolbar-filters .control:has(.date-btn):not(:has(.control-hint))::after{display:none}
  .toolbar-actions{margin-left:0;align-self:flex-end}
}
@media (min-width:769px) and (max-width:1024px){
  .stream-item{grid-template-columns:84px minmax(0,52ch) minmax(0,1fr)}
}

/* ============== TAB PANES ============== */
.tab-pane{display:none}
.tab-pane.active{display:block}

/* ============== PANE HEAD (slim, no hero chrome) ============== */
.pane-head{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:var(--sp-4);
  flex-wrap:wrap;
  margin-bottom:var(--sp-4);
}
.pane-head h2{font-size:var(--fs-lg);font-weight:700;letter-spacing:-.01em}
.pane-meta{
  display:flex;
  gap:var(--sp-4);
  align-items:baseline;
  font-family:var(--mono);
  font-size:var(--fs-xs);
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.pane-meta b{color:var(--ink-dim);font-weight:600}

/* ============== TOOLBAR — hairline strip, not a card ============== */
.toolbar{
  display:flex;
  flex-wrap:wrap;
  gap:var(--sp-3);
  align-items:flex-end;
  margin-bottom:var(--sp-5);
  padding:0 0 var(--sp-4);
  border-bottom:1px solid var(--border);
}
.toolbar-filters{
  display:flex;
  flex-wrap:wrap;
  align-items:flex-end;
  gap:var(--sp-3);
  flex:1;
}
.toolbar-actions{
  display:inline-flex;
  align-items:flex-end;
  gap:var(--sp-3);
  margin-left:auto;
}
/* toolbar buttons sit on the same 34px instrument rhythm as select/input/segment
   (DESIGN.md module toolbar); 44px stays for the lock CTA and coarse pointers */
.toolbar .btn{min-height:34px}
.toolbar .btn svg{width:14px;height:14px}
/* pane meta rehomed onto the toolbar's action side: sits on the control
 * baseline instead of spending a standalone row above the toolbar */
.toolbar-actions .toolbar-meta{padding-bottom:9px}
@media (max-width:768px){.toolbar-actions .toolbar-meta{display:none}}
.toolbar-filters .control{
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  flex:0 0 auto;
  min-width:0;
  min-height:72px;
}
.toolbar-filters .control:has(.control-hint){min-height:72px}
.toolbar-filters .control:not(:has(.control-hint))::after{
  content:"";
  display:block;
  height:15px;
  margin-top:var(--sp-1);
}
.toolbar-filters .chips,
.watch-chips-row .chips{
  align-self:flex-end;
  margin-top:0;
  margin-bottom:1px;
}
.watch-chips-row{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--sp-3);
  margin-bottom:var(--sp-5);
}
.control{
  display:grid;
  gap:var(--sp-1);
  flex:1 1 auto;
  min-width:150px;
}
.control label{
  font-size:var(--fs-xs);
  font-weight:500;
  color:var(--muted);
}
.control input[type=text],.control input[type=search],.control input[type=date],.control select{
  width:100%;
  min-height:34px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-0);
  padding:0 var(--sp-3);
  color:var(--ink);
  font-size:var(--fs-sm);
  transition:border-color var(--dur-1) var(--ease);
}
.control input:focus,.control select:focus{border-color:var(--focus)}
.control input::placeholder{color:var(--muted)}
.control-hint{display:block;font-family:var(--mono);font-size:var(--fs-2xs);color:var(--muted);margin-top:var(--sp-1);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.control-hint--warn{color:var(--warn)}
.control select option{background:var(--surface);color:var(--ink)}
.control input[type=date]{font-family:var(--mono);font-variant-numeric:tabular-nums slashed-zero lining-nums}
/* the backtrack trade-date select holds pure date values — mono tnum rail */
#backtrack-date{font-family:var(--mono);font-variant-numeric:tabular-nums slashed-zero lining-nums;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
/* toolbar control width modifiers */
.control--xs{width:120px}
.control--sm{width:160px}
.control--md{width:200px}
.control--lg{width:240px}
.control--xl{width:280px}
.control.control--xs,
.control.control--sm,
.control.control--md,
.control.control--lg,
.control.control--xl{flex:0 0 auto;min-width:0}
.chips--end{align-self:flex-end}
.btn--end{margin-left:auto}

/* -- New Swiss controls inside toolbar .control wrappers -- */
.control .btn-group,
.control .filter-row,
.control .input-group,
.control .select-btn,
.control .date-btn{width:100%}
.control .btn-group{justify-content:stretch}
.control .btn-group .btn--segment{flex:1 1 auto;justify-content:center}
.control .input-group .input{width:100%;border:0}
.control .select-btn select{padding:0 30px 0 14px}
.toolbar-filters .control:has(.btn-group):not(:has(.control-hint))::after,
.toolbar-filters .control:has(.filter-row):not(:has(.control-hint))::after,
.toolbar-filters .control:has(.input-group):not(:has(.control-hint))::after,
.toolbar-filters .control:has(.select-btn):not(:has(.control-hint))::after,
.toolbar-filters .control:has(.date-btn):not(:has(.control-hint))::after{
  content:"";
  display:block;
  height:15px;
  margin-top:var(--sp-1);
}

/* ============== BENTO GRID — hairline-zoned, not boxed ============== */
.bento{
  display:grid;
  grid-template-columns:repeat(12,minmax(0,1fr));
  gap:var(--sp-6);
}
/* Ranked importance lives only in the left signal rail; News/Monitor centers
   carry their own distinct content (firehose stream; breaking-event clusters).
   Full-bleed: rows use the whole module width — a left reading block capped to
   --read-measure plus a right-aligned mono data rail — not a narrow column. */
.bento .card-stream{grid-column:span 12}
#app[data-tab="limitup"] .tk-panel--limitup{display:none}

/* ============== MODULES (class kept as .card; the boxed atom) ============== */
/* every module = a hard rectangle with a 1px --border-heavy outline on --surface */
.card{
  background:var(--surface);
  border:1px solid var(--border-heavy);
  border-radius:var(--r-0);
  box-shadow:var(--shadow-card);
}
.card-inner{position:relative}
/* module header row: sits on --surface, 1px --border bottom rule, --sp-3 padding */
.card-header{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--sp-4);
  padding:var(--sp-3) var(--sp-4);
  border-bottom:1px solid var(--border);
}
/* MOD: <ID> code — uppercase-mono functional chrome above the title */
.mod-id{
  display:block;
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--muted);
  margin-bottom:var(--sp-1);
}
/* zone codes never break mid-token (a narrow rail head wraps after "MOD:" instead) */
.mod-id .mod-code{white-space:nowrap}
.card-title{
  font-size:var(--fs-lg);
  font-weight:700;
  letter-spacing:-.01em;
  color:var(--ink);
}
.card-sub{
  margin-top:var(--sp-1);
  font-size:var(--fs-xs);
  color:var(--muted);
}
.count-pill{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-2);
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  background:var(--surface-2);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  color:var(--ink-dim);
  white-space:nowrap;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.count-pill:empty{display:none}
.card-body{padding:var(--sp-4)}
.card-scroll{scrollbar-width:thin}
.card-scroll--sm{max-height:var(--scroll-h-sm);overflow-y:auto;scrollbar-width:thin}
#pane-news .card-stream .card-header,
#pane-monitor .card-stream .card-header{
  position:sticky;
  top:var(--topbar-h,57px);
  z-index:var(--z-module-head);
  background:var(--surface);
}
.stream-item,.sig-row,.event-card,.event-sub-item,.bt-row,.th-btn,.bt-name-btn,.exp-btn{
  scroll-margin-top:calc(var(--topbar-h,57px) + 48px);
}

/* ============== STREAM ITEMS — full-bleed ledger rows ============== */
.stream-item{
  position:relative;
  display:grid;
  grid-template-columns:84px minmax(0,var(--read-measure)) minmax(0,1fr);
  gap:var(--row-gap);
  align-items:start;
  width:100%;
  padding:var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-3);
  transition:background var(--dur-1) var(--ease);
}
.stream-main{min-width:0}
.stream-item + .stream-item{border-top:1px solid var(--border)}
.stream-item:hover{background:var(--accent-soft)}
.card-scroll .stream-item{content-visibility:auto;contain-intrinsic-size:auto 88px}
.card-scroll--sm .watch-hit{content-visibility:auto;contain-intrinsic-size:auto 88px}
/* Spine width via --spine-w: information, not decoration */
/* Spine grammar: one rule + [data-tier] color map.
 * crit=I4-5 / warn=I3+watch / calm=I1-2 / up=multi-board / transparent=no tier */
.spine::before{
  content:"";
  position:absolute;
  left:0;top:var(--spine-inset);bottom:var(--spine-inset);
  width:var(--spine-w);
  border-radius:var(--r-micro);
  background:transparent;
}
[data-tier="crit"]::before{background:var(--crit)}
[data-tier="warn"]::before{background:var(--warn)}
[data-tier="calm"]::before{background:var(--calm)}
[data-tier="up"]::before{background:var(--up)}
.stream-time{
  font-family:var(--mono);
  font-size:var(--fs-xs);
  color:var(--muted);
  display:flex;
  flex-direction:column;
  gap:2px;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.stream-time > span{min-width:5ch}
.stream-time .ago{color:var(--muted)}
.item-meta{
  display:flex;
  flex-wrap:wrap;
  gap:var(--sp-2);
  align-items:center;
  margin-bottom:var(--sp-1);
}
.source-mark{
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  color:var(--ink-dim);
}
.item-title{
  font-size:var(--fs-md);
  font-weight:600;  /* CJK headlines run 600 so they hold against the heavy Latin chrome (DESIGN.md Typography) */
  line-height:var(--lh-body);
  color:var(--ink);
  max-width:var(--read-measure);  /* readable line length; the rest of the row carries the data rail */
}
.item-summary{
  font-size:var(--fs-sm);
  color:var(--muted);
  margin-top:var(--sp-1);
  line-height:var(--lh-body);
  max-width:var(--read-measure);  /* readable prose width, not edge-to-edge */
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
}

/* Right-aligned mono data rail (Swiss: quiet type + whitespace, no panel boxes):
   relocates source · I-badge · affected assets off the reading column to the far
   edge, so the full module width carries structured signal, not empty space. */
.stream-data{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:var(--sp-1);
  text-align:right;
  min-width:18ch;
}
.stream-data .source-mark{color:var(--ink-dim)}
.data-tags{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:var(--sp-1)}
.stream-assets{
  display:flex;
  flex-wrap:wrap;
  justify-content:flex-end;
  gap:var(--sp-2);
  max-width:24ch;
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  color:var(--ink-dim);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.stream-assets .asset{white-space:nowrap}
.stream-assets .more{color:var(--muted)}
.quote-tags{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--sp-1);max-width:32ch}
.quote-badge{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-1);
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  background:var(--crit-soft);
  color:var(--up-strong);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:700;
  line-height:1.45;
  white-space:nowrap;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.quote-badge.down{background:var(--surface-2);color:var(--down)}
.quote-name{max-width:8ch;overflow:hidden;text-overflow:ellipsis}
.quote-price{color:var(--ink-dim)}
.limitup-tags{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--sp-1);max-width:36ch}
.limitup-tag{
  display:inline-flex;
  align-items:center;
  gap:2px;
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  background:var(--surface-2);
  color:var(--ink-dim);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  line-height:1.45;
  white-space:nowrap;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.limitup-tag .lt-label{color:var(--muted);font-weight:500}
.limitup-tag .lt-value{color:var(--ink);font-weight:700}
.limitup-tag .lt-unit{color:var(--muted);font-weight:500}
.stream-more{border-top:1px solid var(--border);padding:var(--sp-3)}
.stream-more-btn{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-3);
  width:100%;
  padding:var(--sp-3);
  border:1px solid var(--border);
  background:var(--surface-2);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  font-weight:700;
  color:var(--ink-dim);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  transition:background var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.stream-more-btn:hover{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}
.stream-more-btn:disabled{cursor:wait;opacity:.72}
.stream-more-meta{font-size:var(--fs-2xs);font-weight:600;color:var(--muted)}

/* ============== BADGES & CHIPS — 4px rects, never capsules ============== */
.badge,.chip,.mkt-tag{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-1);
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  line-height:1.5;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.badge{background:var(--surface-2);color:var(--ink-dim)}
.badge-5,.badge-4{background:var(--crit-soft);color:var(--crit)}
.badge-3{background:var(--warn-soft);color:var(--warn)}
.badge-2,.badge-1{background:var(--surface-2);color:var(--ink-dim)}
.chip{background:var(--surface-2);color:var(--muted)}
.chip-signal{background:var(--accent-soft);color:var(--accent-ink)}
.mkt-tag{background:var(--surface-2);color:var(--ink-dim);font-weight:500}
.chips{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-2)}

/* ============== BOARD — the ledger ============== */
.board-list{display:block;padding:0}
.board-list > * + *{border-top:1px solid var(--border)}
.board-card{
  position:relative;
  display:grid;
  grid-template-columns:56px minmax(0,1fr);
  gap:var(--row-gap);
  width:100%;
  padding:var(--sp-3);
  transition:background var(--dur-1) var(--ease);
}
.board-card:hover{background:var(--accent-soft)}
.board-score-col{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:var(--sp-1);
}
.item-score{
  min-width:2.4ch;
  text-align:right;
  font-family:var(--mono);
  font-size:var(--fs-score);
  font-weight:700;
  letter-spacing:-.02em;
  color:var(--ink);  /* calm scores stay --ink (DESIGN.md board row) — dim numerals read as disabled */
  line-height:1;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.row-meta{
  display:flex;
  gap:var(--sp-2);
  align-items:center;
  flex-wrap:wrap;
  margin-top:var(--sp-2);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}

/* ============== EVENT ROWS (clusters, de-boxed) ============== */
.event-card{position:relative;padding:var(--sp-3);transition:background var(--dur-1) var(--ease)}
.event-card + .event-card{border-top:1px solid var(--border)}
.event-card:hover{background:var(--accent-soft)}
.event-card-ledger{
  display:grid;
  grid-template-columns:56px minmax(0,1fr);
  gap:var(--row-gap);
  align-items:flex-start;
}
.event-rail{align-items:flex-end}
.evt-toggle{
  display:inline-flex;
  padding:2px;
  border:0;
  background:none;
  cursor:pointer;
  border-radius:var(--r-0);
  transition:background var(--dur-1) var(--ease);
}
.evt-toggle:hover{background:var(--surface-2)}
.event-main{min-width:0}
.event-head{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:var(--sp-2);
}
.evt-count{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-1);
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  background:var(--surface-2);
  font-family:var(--mono);
  font-size:var(--fs-sm);
  font-weight:600;
  color:var(--ink-dim);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  min-width:2.4ch;
}
.evt-caret{
  display:inline-flex;
  width:12px;
  height:12px;
  color:var(--ink-dim);
  transition:transform var(--dur-1) var(--ease);
}
.evt-caret svg{width:100%;height:100%}
.evt-toggle[aria-expanded="true"] .evt-caret{transform:rotate(90deg)}
.event-level{
  display:inline-flex;
  align-items:center;
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  padding:2px var(--sp-2);
  border-radius:var(--r-0);
  line-height:1.5;
}
.event-level-critical{background:var(--crit-soft);color:var(--crit)}
.event-level-high{background:var(--accent);color:var(--btn-ink)}
.event-level-normal{background:var(--surface-2);color:var(--muted)}
/* score tiers: make equal-score walls readable at a glance */
.item-score.score-hi{color:var(--crit)}
.item-score.score-mid{color:var(--ink-hero)}
/* daily digest/roundup posts: keep but de-emphasize */
.board-card.is-digest,.stream-item.is-digest{opacity:.62}
.board-card.is-digest:hover,.stream-item.is-digest:hover{opacity:1}
.event-title{
  display:block;
  flex:1;
  min-width:0;
  font-size:var(--fs-md);
  font-weight:600;
  line-height:var(--lh-body);
  margin-top:0;
  max-width:var(--read-measure);
  color:var(--ink);
}
.event-meta{margin-top:var(--sp-2)}
/* child rows: indented to align with event-main content column */
.event-body{display:none;margin:var(--sp-2) var(--sp-3) var(--sp-3) calc(56px + var(--row-gap) + var(--sp-3));border-left:var(--spine-w-sub) solid var(--border);padding-left:var(--sp-3)}
.event-body.open{display:block}
.event-sub-item{
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  gap:var(--sp-2);
  align-items:baseline;
  width:100%;
  padding:var(--sp-2);
  border-top:1px solid var(--border);
  font-size:var(--fs-xs);
  transition:background var(--dur-1) var(--ease);
}
.event-sub-item:first-child{border-top:none}
.event-sub-item:hover{background:var(--accent-soft)}
.sub-badge-spacer{display:block;min-width:28px}
.event-sub-body{display:block;line-height:var(--row-lh)}
.event-sub-title{color:var(--ink)}
.event-sub-item .source-mark{margin-right:var(--sp-1)}

/* ============== LIMIT-UP TABS ============== */
/* Session-summary zones (LMT-VIZ / BTK-DAY): each strip — KPI band, up-days
 * distribution, industry footprint — is a padded, hairline-separated zone with
 * its own sentence-case title + mono system kicker, so the summary reads as
 * three labeled instruments instead of one cramped pile. */
.viz-zone{padding:var(--sp-4) var(--sp-5) var(--sp-5)}
.viz-zone--kpi{padding-top:var(--sp-2);padding-bottom:var(--sp-2)}
.viz-zone + .viz-zone{border-top:1px solid var(--border)}
.viz-zone-head{display:flex;align-items:baseline;gap:var(--sp-3);margin-bottom:var(--sp-3)}
.viz-zone-title{font-size:var(--fs-sm);font-weight:600;color:var(--ink);letter-spacing:0;margin:0}
.viz-zone-kicker{
  font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
}
@media (max-width:768px){
  .viz-zone{padding:var(--sp-3) var(--sp-4) var(--sp-4)}
}
/* KPI band: naked numerals split by vertical rules — no boxes */
.kpi-band{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  padding:var(--sp-4) 0;
}
.kpi-cell{
  padding:0 var(--sp-4);
  border-left:1px solid var(--border-strong);
}
.kpi-cell:first-child{border-left:0;padding-left:0}
.kpi-label{
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--muted);
  margin-top:var(--sp-2);
}
/* zh KPI captions are CJK — never letter-space/uppercase CJK glyphs */
:lang(zh) .kpi-label{letter-spacing:0;text-transform:none}
.kpi-value{
  font-family:var(--mono);
  font-size:var(--fs-data);
  font-weight:800;
  letter-spacing:-.02em;
  color:var(--ink-hero);
  line-height:var(--lh-tight);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
/* 最高连板 is a price-up magnitude → the large price-up red token (never severity --crit) */
.kpi-value.up{color:var(--up-strong)}
.kpi-value .unit{
  margin-left:var(--sp-1);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  color:var(--muted);
  font-weight:500;
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
/* up-days distribution: single-hue stacked bar, real integer counts */
.updays-bar{
  display:flex;
  height:20px;
  border-radius:var(--r-0);
  overflow:hidden;
  gap:var(--sp-1);
  margin:0 0 var(--sp-2);
}
/* segment fill is a solid mix (not element opacity) so the 1px full-strength
 * --up outline stays >=3:1 against --bg for every step */
.updays-seg{min-width:6px;box-shadow:inset 0 0 0 1px var(--up);display:flex;align-items:center;justify-content:center;overflow:hidden}
.updays-segnum{font-family:var(--mono);font-size:var(--fs-2xs);font-weight:600;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;line-height:1;pointer-events:none}
.updays-legend{
  display:flex;
  flex-wrap:wrap;
  gap:var(--sp-2) var(--sp-4);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.updays-legend .sw{
  width:8px;height:8px;
  border-radius:var(--r-0);
  box-shadow:inset 0 0 0 1px var(--up);
  display:inline-block;
  margin-right:var(--sp-1);
  vertical-align:baseline;
}
/* industry footprint: a single-row ledger, not pills */
.industry-row{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  row-gap:var(--sp-2);
  padding:var(--sp-2) 0 0;
}
.industry-item{
  display:flex;
  align-items:baseline;
  gap:var(--sp-2);
  padding:0 var(--sp-4);
  border-left:1px solid var(--border);
}
.industry-item:first-child{border-left:0;padding-left:0}
.industry-name{font-size:var(--fs-sm);color:var(--ink-dim)}
.industry-count{
  font-family:var(--mono);
  font-size:var(--fs-xs);
  font-weight:600;
  color:var(--accent-ink);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.industry-more{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-1);
  margin-left:var(--sp-3);
  padding:var(--sp-1) var(--sp-2);
  border-radius:var(--r-0);
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  color:var(--accent-ink);
  background:var(--accent-soft);
  border:1px solid transparent;
  transition:border-color var(--dur-1) var(--ease);
}
.industry-more:hover{border-color:var(--accent-ink)}
.industry-more:active{background:var(--accent-soft);border-color:var(--accent-ink)}
.industry-more .icon{width:10px;height:10px}
.industry-item.extra{display:none}
.industry-row.expanded .industry-item.extra{display:flex}
.stocks-card{margin-top:var(--sp-6)}
.stocks-card .card-body{padding:0}
/* Safe default: horizontal scroll (narrow layouts; the ≤1024px block above
 * relies on it). ≥1025px flips to clip so no scroll container sits between the
 * page and the sticky thead — there the progressive col-* policy below
 * guarantees the table always fits its wrap. */
.stocks-table-wrap{overflow-x:auto;overflow-y:visible;scrollbar-width:thin;border-bottom:1px solid var(--border);position:relative}
@media (min-width:1025px){
  .stocks-table-wrap{overflow-x:clip}
}
.stocks-table{
  width:100%;
  border-collapse:separate;
  border-spacing:0;
  font-size:var(--fs-sm);
}
.stocks-table thead th{
  position:sticky;
  top:var(--topbar-h,57px);
  z-index:var(--z-table-head);
  background:var(--surface-2);
  padding:0;
  border-bottom:1px solid var(--border-strong);
  white-space:nowrap;
}
.th-btn{
  display:flex;
  align-items:center;
  gap:var(--sp-1);
  width:100%;
  padding:10px;
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  color:var(--muted);
  transition:color var(--dur-1) var(--ease);
}
.stocks-table thead th.num .th-btn{justify-content:flex-end}
/* hover = accent-soft wash */
.th-btn:hover{color:var(--ink);background:var(--accent-soft)}
/* active sort: label → --ink/600, sort triangle carries accent color;
   arrow path is fill:currentColor, so the arrow takes its own color independent of the label. */
.stocks-table thead th.active .th-btn{color:var(--ink);font-weight:600}
.sort-arrow{color:var(--muted);opacity:.75;transition:color var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease)}
.stocks-table thead th.active .sort-arrow{opacity:1;color:var(--accent-ink)}
.th-btn svg.sort-arrow{width:8px;height:5px;flex:none}
.stocks-table thead th.num,.stocks-table tbody td.num{text-align:right;font-family:var(--mono);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;min-width:4.5ch}
.stocks-table tbody tr{transition:background var(--dur-1) var(--ease)}
/* zebra keyed off the DATA-row index (not nth-child) so interleaved 解读 detail rows can't break parity */
.stocks-table tbody tr.bt-row.zebra{background:var(--zebra)}
.stocks-table tbody tr.bt-row:hover{background:var(--accent-soft)}
/* Row hover/press = --accent-soft chrome fill; no brightness lift */
.stocks-table tbody tr.bt-row:active{background:var(--accent-soft)}
.stocks-table tbody td{
  padding:var(--sp-2) 10px;
  vertical-align:middle;
  white-space:nowrap;
}
/* Progressive column policy: the tape must always FIT its wrap (overflow-x is
 * clipped on desktop so a page-sticky thead can work — an overflowing column
 * would be unreachable). Lowest-signal columns yield first; every dropped
 * datum stays reachable elsewhere (解读 expansion row / RAIL-SEAL / drawer).
 * ≤1024px the rails fold, the wrap scrolls horizontally and ALL columns return. */
@media (min-width:1025px) and (max-width:1439px){
  .stocks-table .col-price{display:none}
}
@media (min-width:1025px) and (max-width:1310px){
  .stocks-table .col-industry{display:none}
}
@media (min-width:1025px) and (max-width:1200px){
  .stocks-table .col-firstLuTime{display:none}
}
@media (min-width:1025px) and (max-width:1130px){
  .stocks-table .col-symbol{display:none}
}
/* table grid rule: 1px --border grid lines define every data cell.
 * Borders only — the red .cell-percent/.lb-tag.multi never sit on a --surface-2 inset fill. */
.stocks-table tbody tr.bt-row td{
  border-bottom:1px solid var(--border);
  border-right:1px solid var(--border);
}
.stocks-table tbody tr.bt-row td:last-child{border-right:0}
.cell-symbol{font-family:var(--mono);font-size:var(--fs-xs);color:var(--muted);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.cell-name{font-weight:600;color:var(--ink)}
.cell-price{color:var(--ink-dim);min-width:7ch;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.cell-percent{color:var(--up);font-weight:600;font-size:var(--fs-md);min-width:7ch;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.cell-percent.down{color:var(--down)}
.cell-amount{color:var(--ink-dim);min-width:8ch;font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
/* 连板 = the ledger numeral of this tape; multi-board rows carry the spine */
.lb-tag{
  font-family:var(--mono);font-size:var(--fs-sm);font-weight:600;
  color:var(--ink-dim);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  min-width:3ch;text-align:right;
}
.lb-tag.multi{color:var(--up)}
/* per-row spine segment (gaps keep it a row marker, not a column rule) */
.updays-cell{position:relative;min-width:3ch}
.updays-cell.spine::before{top:var(--sp-2);bottom:var(--sp-2)}
.updays-tag{
  font-family:var(--mono);font-size:var(--fs-xs);
  color:var(--ink-dim);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  min-width:3ch;text-align:right;
}
.cell-time{font-family:var(--mono);color:var(--muted);font-size:var(--fs-xs);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;min-width:8ch}
.cell-industry{color:var(--muted);font-size:var(--fs-xs)}

.empty-state{padding:var(--sp-4) var(--sp-3) var(--sp-4) var(--row-inset);min-height:120px;display:flex;align-items:center;justify-content:flex-start;text-align:left;border-left:var(--spine-w) solid transparent;color:var(--muted);font-size:var(--fs-sm);line-height:1.5}
.empty-illus{width:56px;height:56px;flex:none;object-fit:contain;margin-right:var(--sp-4)}
[data-theme="dark"] .empty-illus{filter:invert(1) hue-rotate(180deg);mix-blend-mode:lighten}
/* rail empty state uses the same internal margin as the signal rows (rail pad + --sp-3) */
.rail-empty{padding-left:var(--sp-3)}

/* ============== ZONE FAILURE (per-zone inline error, no global banner) ============== */
.zone-error{display:flex;align-items:center;gap:var(--sp-3);margin:var(--sp-3) 0;padding:var(--sp-3);box-shadow:inset var(--spine-w) 0 0 var(--crit);background:var(--crit-soft);color:var(--crit);font-size:var(--fs-xs);font-family:var(--mono);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.zone-illus{width:36px;height:36px;flex:none;object-fit:contain}
[data-theme="dark"] .zone-illus{filter:invert(1) hue-rotate(180deg);mix-blend-mode:lighten}
.zone-error .zone-retry{margin-left:auto;padding:var(--sp-1) var(--sp-3);border-radius:var(--r-0);border:1px solid var(--crit);color:var(--crit);font-weight:600;font-size:var(--fs-xs);background:transparent;cursor:pointer}
.zone-error .zone-retry:hover{background:var(--surface)}
.zone-error .zone-retry:active{background:var(--surface-2)}

/* ============== INTERACTION STATE MATRIX (background press, no transform/brightness) ============== */
/* ink-only controls press to the darker panel step (--ink clears 10:1 there) */
.tab-btn:active,.icon-btn:active,.close-btn:active,.th-btn:active,.watch-x:active,.source-link:active{background:var(--surface-3)}
.source-link:active{color:var(--ink)}
/* sort-header press: promote the --muted label to --ink (it would fail on surface-3) */
.th-btn:active{color:var(--ink)}
/* colored rows HOLD --accent-soft on press (AA: red/green values fail on surface-3) */
.stream-item:active,.board-card:active,.evt-toggle:active,.bt-row:active,.sig-row:active,.event-sub-item:active,.exp-btn:active,.stream-more-btn:active{background:var(--accent-soft)}
.bt-row:active td{background:var(--accent-soft)}
.stream-item.is-current,.board-card.is-current,.event-sub-item.is-current,.sig-row.is-current{background:var(--accent-soft)}
/* Selection uses the persistent accent wash; the tier spine already carries severity. */

/* ============== LEGEND ============== */
.legend{
  display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);align-items:center;
  font-family:var(--mono);font-size:var(--fs-2xs);color:var(--muted);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  margin-top:var(--sp-2)
}
.legend .dot{width:var(--sp-2);height:var(--sp-2);border-radius:var(--r-micro);display:inline-block;margin-right:var(--sp-1);vertical-align:middle}
.dot-calm{background:var(--calm)}.dot-warn{background:var(--warn)}.dot-crit{background:var(--crit)}
.legend--inline{margin-top:0;margin-bottom:0}

/* ============== INLINE DETAIL ============== */
.inline-detail{
  width:100%;
  border-top:1px solid var(--border-heavy);
  border-bottom:1px solid var(--border-heavy);
  background:var(--surface-2);
}
.inline-detail-inner{padding:var(--sp-5) var(--sp-5) var(--sp-6)}
.inline-detail-toolbar{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-3);
  padding-bottom:var(--sp-3);
  border-bottom:1px solid var(--border);
}
.inline-detail-origin,.inline-detail-actions{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--sp-2);
}
.inline-detail-origin{
  min-width:0;
  color:var(--muted);
  font-family:var(--mono);
  font-size:var(--fs-xs);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.inline-detail-code{
  color:var(--ink);
  font-size:var(--fs-2xs);
  font-weight:600;
  letter-spacing:.06em;
  text-transform:uppercase;
}
.inline-detail-actions{justify-content:flex-end;flex:none}
.source-link,.inline-detail-collapse{
  display:inline-flex;align-items:center;gap:var(--sp-2);
  min-height:32px;
  padding:var(--sp-1) var(--sp-3);
  border:1px solid var(--border);
  border-radius:var(--r-0);
  background:var(--surface);
  color:var(--ink-dim);
  font-family:var(--font);
  font-size:var(--fs-xs);
  text-decoration:none;
  transition:background var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.source-link:hover,.inline-detail-collapse:hover{border-color:var(--accent);color:var(--accent-ink)}
.inline-detail-collapse:active{background:var(--surface-3);color:var(--ink)}
.detail-lede{
  max-width:72ch;
  padding:var(--sp-5) 0;
  font-size:var(--fs-md);
  line-height:1.7;
  white-space:pre-wrap;
  color:var(--ink-dim);
}
.wt-rail .inline-detail-inner{padding:var(--sp-4) var(--sp-3) var(--sp-5)}
.wt-rail .inline-detail-toolbar{align-items:flex-start;flex-direction:column}
.wt-rail .inline-detail-actions{justify-content:flex-start;width:100%}
.wt-rail .inline-detail-actions>*{flex:1 1 auto;justify-content:center}
.wt-rail .detail-lede{font-size:var(--fs-sm);padding:var(--sp-4) 0}
.wt-rail .inline-detail .detail-signal-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
.wt-rail .inline-detail .score-cell:nth-child(4n+1){border-left:1px solid var(--border);padding-left:var(--sp-3)}
.wt-rail .inline-detail .score-cell:nth-child(2n+1){border-left:0;padding-left:0}
.wt-rail .detail-rationale{grid-template-columns:1fr;gap:var(--sp-2)}
.inline-detail .detail-skeleton .sk{background:var(--surface-3)}
.card-title,.item-title,.lock-card h1{text-wrap:balance}
.item-summary,.card-sub,.event-fact,.event-insight{text-wrap:pretty}
.detail-signal-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:0;
  border-top:1px solid var(--border-heavy);
  border-bottom:1px solid var(--border-heavy);
}
.score-cell{
  display:grid;
  gap:var(--sp-1);
  padding:var(--sp-2) var(--sp-3);
  border-left:1px solid var(--border);
  font-family:var(--mono);
  color:var(--ink);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
}
.score-cell:nth-child(4n+1){border-left:0;padding-left:0}
.score-cell strong{
  font-family:var(--font);
  font-size:var(--fs-2xs);
  color:var(--muted);
  font-weight:600;
}
.score-cell > span{font-size:var(--fs-md)}
.score-cell > span.score-num{font-size:var(--fs-score-sm);font-weight:600;letter-spacing:-.01em;line-height:1.1;min-width:4ch}
.detail-rationale{
  display:grid;
  grid-template-columns:104px minmax(0,1fr);
  gap:var(--sp-4);
  padding:var(--sp-5) 0;
  border-bottom:1px solid var(--border);
  color:var(--ink-dim);
  font-size:var(--fs-sm);
  line-height:var(--lh-body);
}
.detail-exposure{
  display:flex;
  flex-wrap:wrap;
  gap:var(--sp-5);
  padding-top:var(--sp-5);
}
.detail-exposure-group{flex:1 1 240px;min-width:0}
.detail-market-chip{gap:var(--sp-2)}
.detail-market-chip strong{font-family:var(--mono);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.detail-market-chip.is-hot{border-color:var(--accent-ink);color:var(--accent-ink)}
.detail-taxonomy{margin-top:var(--sp-5);padding-top:var(--sp-5);border-top:1px solid var(--border)}
.detail-skeleton{display:flex;flex-direction:column;gap:var(--sp-4);padding-top:var(--sp-2)}
.detail-skeleton .sk{display:block;background:var(--surface-2);border-radius:var(--r-micro);animation:skp var(--dur-3) var(--ease-io) infinite}
.detail-skeleton .sk-title{height:28px;width:75%}
.detail-skeleton .sk-meta{height:12px;width:40%}
.detail-skeleton .scores--skeleton{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2);margin:var(--sp-2) 0;border:0}
.detail-skeleton .sk-score{height:44px}
.detail-skeleton .sk-line{height:12px}
.detail-skeleton .sk-line:nth-of-type(2){width:92%}
.detail-skeleton .sk-line:nth-of-type(3){width:78%}
.score-num.imp-crit{color:var(--crit)}
.score-num.imp-warn{color:var(--warn)}
.score-num.imp-calm{color:var(--ink-hero)}
.score-num.urg-warn{color:var(--warn)}
.score-num.urg-calm{color:var(--ink)}
.detail-section-title{
  font-size:var(--fs-2xs);
  font-family:var(--mono);
  font-weight:600;
  color:var(--muted);
  margin-bottom:var(--sp-2);
}
.raw{margin-top:var(--sp-5)}
.raw summary{cursor:pointer;font-size:var(--fs-xs);color:var(--muted);font-family:var(--mono)}
.raw pre{
  font-size:var(--fs-xs);
  font-family:var(--mono);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  overflow-x:auto;
  margin-top:var(--sp-2);
  padding:var(--sp-4);
  background:var(--surface-2);
  color:var(--ink-dim);
  border-radius:var(--r-0);
  line-height:var(--lh-body);
}
.close-btn{
  position:absolute;
  top:var(--sp-3);right:var(--sp-3);
  width:44px;height:44px;
  border-radius:var(--r-0);
  background:var(--surface-2);
  border:1px solid var(--border);
  color:var(--muted);
  display:inline-flex;align-items:center;justify-content:center;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.close-btn:hover{background:var(--surface);color:var(--ink)}
.close-btn svg{width:15px;height:15px}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ============== SKELETON LOADING (matches the ledger grid) ============== */
.skeleton-row,.skeleton-card{position:relative}
.skeleton-row{display:grid;grid-template-columns:84px minmax(0,1fr);gap:var(--row-gap);padding:var(--sp-3) var(--sp-2) var(--sp-3) var(--sp-3);align-items:start}
.skeleton-row + .skeleton-row{border-top:1px solid var(--border)}
.skeleton-card{display:grid;grid-template-columns:56px minmax(0,1fr);gap:var(--row-gap);padding:var(--sp-3) var(--sp-2) var(--sp-3) var(--sp-3)}
.skeleton-card + .skeleton-card{border-top:1px solid var(--border)}
.skeleton-sig{display:grid;grid-template-columns:34px minmax(0,1fr);gap:var(--sp-2);padding:var(--sp-2) 0 var(--sp-2) var(--sp-3);align-items:start}
.skeleton-sig + .skeleton-sig{border-top:1px solid var(--border)}
.sk{display:block;background:var(--surface-2);border-radius:var(--r-0);height:11px;animation:skp var(--dur-3) var(--ease-io) infinite}
.sk + .sk{margin-top:var(--sp-2)}
.sk.w40{width:40%}.sk.w70{width:70%}.sk.w90{width:90%}
@keyframes skp{0%,100%{opacity:.55}50%{opacity:.85}}

/* ============== RESPONSIVE ============== */
@media (max-width:1024px){
  .bento .card-stream{grid-column:span 12}
  .kpi-band{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:var(--sp-5)}
  .kpi-cell:nth-child(odd){border-left:0;padding-left:0}
}
@media (max-width:768px){
  .topbar-inner{flex-wrap:wrap;gap:var(--sp-2);padding:var(--sp-2) var(--sp-4)}
  .topbar-start{order:1}
  .topbar-center{order:1;justify-content:flex-start;width:auto;flex:1 1 auto}
  .topbar-end{order:2;flex-wrap:wrap;justify-content:space-between;align-items:flex-start;gap:var(--sp-2);width:100%}
  .nav-status{flex:1;flex-wrap:wrap;justify-content:flex-start;gap:var(--sp-2);min-width:0}
  .status-cluster{flex-wrap:wrap;gap:var(--sp-1) var(--sp-2);padding:var(--sp-1) var(--sp-2)}
  .strip-field:has(#lat-ms),
  .strip-field:has(#mkt-state),
  .strip-field:has(#lat-ms) + .nav-vr,
  .vr-mkt{display:none}
  .controls-cluster{padding-left:var(--sp-2);border-left:1px solid var(--border-strong);flex:none}
  .app-main{padding:var(--sp-4) var(--sp-3) 56px}
  .control{flex:1 1 100%;min-width:0}
  .control input[type=text],.control input[type=search],.control input[type=date],.control select{font-size:16px}
  #pane-limitup .toolbar{gap:var(--sp-2);padding-bottom:var(--sp-3)}
  #pane-limitup .toolbar-filters{gap:var(--sp-2)}
  #pane-limitup .toolbar-filters .control{width:auto;flex:1 1 180px}
  #pane-limitup .toolbar-actions{flex:0 0 auto}
  #pane-limitup .control-hint{display:none}
  .stream-item{grid-template-columns:1fr;gap:var(--sp-2)}
  .stream-data{min-width:0;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;text-align:left;gap:var(--sp-2);margin-top:2px}
  .data-tags,.stream-assets,.quote-tags,.limitup-tags{justify-content:flex-start}
  .event-card-ledger{grid-template-columns:1fr}
  .event-rail{flex-direction:row;align-items:center;justify-content:flex-start}
  .event-body{margin-left:var(--sp-3)}
  .skeleton-row{grid-template-columns:1fr}
  .stream-time{flex-direction:row;gap:var(--sp-3)}
  .detail-signal-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .score-cell:nth-child(4n+1){border-left:1px solid var(--border);padding-left:var(--sp-3)}
  .score-cell:nth-child(2n+1){border-left:0;padding-left:0}
  .inline-detail-inner{padding:var(--sp-5) var(--sp-4) calc(var(--sp-6) + var(--sp-2))}
  .inline-detail-toolbar{align-items:flex-start;flex-direction:column}
  .inline-detail-actions{justify-content:flex-start;width:100%}
  .detail-rationale{grid-template-columns:1fr;gap:var(--sp-2)}
}
@media (max-width:480px){
  .kpi-band{grid-template-columns:1fr;row-gap:var(--sp-4)}
  .kpi-cell{border-left:0;padding:0}
  .kpi-value{font-size:var(--fs-score)}
  /* keep the strip to its essentials: state square + clock + updated-at */
  .mkt-cluster,.vr-mkt{display:none}
  /* stack controls above the status cluster so nothing is clipped */
  .topbar-end{flex-direction:column;justify-content:flex-start;align-items:stretch;gap:var(--sp-1)}
  .controls-cluster{order:-1;align-self:flex-end;border-left:0;padding-left:0}
  .nav-status{flex:none;width:100%}
  .status-cluster{justify-content:space-between}
}
@media (pointer:coarse){
  .icon-btn,.close-btn{min-width:44px;min-height:44px}
  .tab-btn{min-height:44px}
  .th-btn,.evt-toggle,.industry-more,.source-link,.inline-detail-collapse,.watch-chip,.exp-btn,.bt-name-btn{min-height:44px}
  .control input,.control select,.btn--filter,.btn--segment,.select-btn select,.input-group,.input-group__clear,.toolbar .btn{min-height:44px}
  .input-group__clear{min-width:44px}
  .watch-chip{min-width:44px;display:inline-flex;align-items:center;justify-content:center}
  .watch-x{width:28px;height:28px}
  .stream-item,.board-card,.event-sub-item,.sig-row{min-height:44px}
  .stocks-table tbody td{padding-top:var(--sp-3);padding-bottom:var(--sp-3)}
}

/* ===== Monitor & Backtrack tabs ===== */
/* "Back to live" is an action out of review mode; while already live it is a
 * no-op and only adds a red pill to the toolbar — hide it until a date is set. */
#monitor-live-btn[aria-pressed="true"]{display:none}
.watch-chip{display:inline-flex;align-items:center;gap:var(--sp-2);max-width:220px}
.watch-chip>span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:1 1 auto}
/* the keyword chip itself is a passive token — only the × inside is interactive,
   so the span never advertises hover/press affordances it cannot honor */
span.watch-chip{cursor:default}
span.watch-chip:hover,span.watch-chip:active{background:transparent;color:var(--ink-dim);border-color:var(--border)}
.watch-chip--undo{color:var(--accent-ink);border-style:dashed}
.watch-x{
  display:inline-flex;align-items:center;justify-content:center;
  flex:none;
  width:20px;height:20px;
  padding:0;
  margin-left:2px;
  background:transparent;
  border:0;
  border-radius:var(--r-micro);
  color:inherit;
  font-size:var(--fs-sm);line-height:1;
  cursor:pointer;
}
/* keyboard focus uses the shared two-tone ring only (no divergent red outline) */
.watch-chip:hover .watch-x,.watch-x:hover,.watch-x:focus-visible{color:var(--crit);background:var(--surface-2)}
.trend-wrap{overflow-x:auto;padding:var(--sp-2) 0 var(--sp-1)}
.bt-num{font-size:var(--fs-2xs);fill:var(--ink-dim)}
.bt-lbl{font-size:var(--fs-2xs);fill:var(--muted)}
.bt-max{font-size:var(--fs-2xs);fill:var(--up)}
.bt-mean{font-size:var(--fs-2xs);fill:var(--muted);font-family:var(--mono);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1}
.bt-bar{cursor:pointer}
.bt-bar.selected .bt-lbl{fill:var(--accent-ink)}
.bt-bar-first{opacity:var(--spark-dim)}
.bt-spark{flex:none;display:block}
.bt-spark .spk-bar.dim{opacity:var(--spark-dim)}
.card-head-right{display:flex;align-items:center;gap:var(--sp-3)}
.bt-row:hover td{background:var(--accent-soft)}
.score-md{font-size:var(--fs-md)}
#pane-monitor .bento{margin-top:var(--sp-5)}
#watch-hits-card{margin:var(--sp-5) 0}
.stream-item.watch-hit{grid-template-columns:84px minmax(0,1fr)} /* 2-child rows: no right gutter (P1-1 fix) */
.stream-item.watch-hit>span{min-width:0} /* bare <span> content col misses .stream-main's min-width:0 — guard long tokens */
#backtrack-trend,#backtrack-stock,#backtrack-day{margin-top:var(--sp-6)}

/* Monitor event message anatomy — mirrors the Telegram breaking format:
 * title, fact prose, impact/watch insight rows, asset tags,
 * named sources, first-seen → sent timeline. */
.event-fact{margin:var(--sp-2) 0 0;font-size:var(--fs-sm);color:var(--ink-dim);line-height:var(--lh-body)}
.evt-facts{margin:var(--sp-2) 0 0;padding-left:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-1);list-style:disc}
.evt-facts li{font-size:var(--fs-sm);color:var(--ink-dim);line-height:var(--lh-body)}
.event-insights{margin-top:var(--sp-2);display:flex;flex-direction:column;gap:var(--sp-1)}
.event-insight{display:flex;gap:var(--sp-2);margin:0;font-size:var(--fs-sm);line-height:var(--lh-body);color:var(--ink-dim);align-items:baseline}
.insight-label{
  flex:none;
  font-family:var(--mono);
  font-size:var(--fs-2xs);
  font-weight:600;
  color:var(--muted);
  padding:var(--sp-1) var(--sp-1);
  border:1px solid var(--border);
  border-radius:var(--r-0);
  line-height:1.4;
  min-width:2.5ch;
  text-align:center;
}
.insight-text{min-width:0}
.evt-assets{display:flex;flex-wrap:wrap;gap:var(--sp-1);margin-top:var(--sp-2)}
mark.kw-mark{background:var(--warn-soft);color:inherit;border-radius:var(--r-0);padding:0 1px}
.live-mark{font-family:var(--mono);font-size:var(--fs-2xs);color:var(--muted);border:1px solid var(--border);border-radius:var(--r-0);padding:1px var(--sp-1);margin-left:var(--sp-1);vertical-align:1px}
.review-note{font-family:var(--mono);font-size:var(--fs-xs);color:var(--accent-ink)}
.evt-sub-time{font-family:var(--mono);font-size:var(--fs-2xs);color:var(--muted);font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;min-width:5ch}

/* Stock 解读 expansion rows (Limit-Up + Backtrack tables) */
.exp-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--r-0);color:var(--ink-dim);cursor:pointer;background:none;border:0}
.exp-btn:hover{background:var(--accent-soft)}
.exp-btn[aria-expanded="true"]{color:var(--accent-ink)}
.exp-btn[aria-expanded="true"] .evt-caret{transform:rotate(90deg)}
tr.stock-detail{display:none}
tr.stock-detail.open{display:table-row}
tr.stock-detail>td{background:var(--surface-2);padding:var(--sp-3) var(--sp-4) var(--sp-3);border-bottom:1px solid var(--border-strong)}
/* Backtrack progression sub-table (renderBacktrackStock, #backtrack-stock): bare <tr> data rows
 * carry no .bt-row, so they miss the tape's cell grid + hover. Scope the match to this container
 * and exclude .stock-detail rows so the expandable detail cells stay un-bordered. */
#backtrack-stock .stocks-table tbody tr:not(.stock-detail) td{border-bottom:1px solid var(--border);border-right:1px solid var(--border)}
#backtrack-stock .stocks-table tbody tr:not(.stock-detail) td:last-child{border-right:0}
#backtrack-stock .stocks-table tbody tr:not(.stock-detail):hover td{background:var(--accent-soft)}
.sd-wrap{display:flex;flex-direction:column;gap:var(--sp-2);max-width:78ch}
.sd-tags{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:center}
.sd-ai{font-size:var(--fs-sm);line-height:1.65;color:var(--ink-dim);white-space:pre-wrap;margin:0}
.cell-action{width:34px;text-align:center}

/* Hover/focus reason popover (Limit-Up + Backtrack tables). No glass/blur. */
/* role="tooltip": --surface + 1px --border hairline seam, square, NO blur/glass/shadow */
#reason-pop{
  position:fixed;
  z-index:var(--z-popover);
  max-width:360px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-0);
  box-shadow:none;
  padding:var(--sp-3);
  font-family:var(--mono);
  font-feature-settings:"tnum" 1,"zero" 1,"lnum" 1;
  color:var(--ink-dim);
  opacity:0;
  transform:translateY(4px);
  transition:opacity var(--dur-2) var(--ease-out),transform var(--dur-2) var(--ease-out);
  pointer-events:none;
}
#reason-pop:not([hidden]){opacity:1;transform:translateY(0)}
#reason-pop .sd-wrap{max-width:none}
#reason-pop .sd-tags{margin-bottom:var(--sp-2)}
#reason-pop .sd-ai{font-size:var(--fs-xs)}

/* Live-feed new-row luminance confirmation flash. */
/* new-row flash: one-shot background + left-border flash that resolves to rest (no brightness) */
@keyframes rowFlash{
  from{background:var(--accent-soft);box-shadow:inset 3px 0 0 var(--accent)}
  to{background:transparent;box-shadow:inset 3px 0 0 transparent}
}
.is-new{animation:rowFlash var(--dur-1) var(--ease-out) 1}

/* Backtrack interactions: clickable name, search box, industry filter */
.bt-name-btn{background:none;border:0;cursor:pointer;color:inherit;font:inherit;padding:0;text-align:left}
.bt-name-btn:hover,.bt-name-btn:active{color:var(--accent-ink)}
.bt-tools{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.bt-tools input{min-height:34px;font-size:var(--fs-sm)}

/* ============== ANIMATION PRIMITIVES ==============
 * Feedback-only motion that respects the Swiss Modernism 2.0 register:
 * - FLIP for live-list insertions/reorders
 * - overlay fade + drawer/dialog transition discipline
 * - poll tick flash on the updated-at cell
 * Everything is neutralized under prefers-reduced-motion. */

/* FLIP: elements carry an inline transform during reconciliation, then we
 * remove the class to let the transition settle to rest. */
.flip-animating{
  transition:transform var(--dur-2) var(--ease-out-quart);
  will-change:transform;
}

/* Table-row FLIP: rows are repositioned inside the existing table. */
tr.flip-animating td{
  transition:transform var(--dur-2) var(--ease-out-quart);
  will-change:transform;
}

/* Native <dialog> enter/exit: fade + slight translate. The native showModal()
 * handles the backdrop; we only animate the content box. Re-assert margin:auto
 * because the global * reset zeros out the default dialog centering. */
dialog{
  margin:auto;
  opacity:0;
  transform:translateY(-8px);
  transition:opacity var(--dur-2) var(--ease-out),transform var(--dur-2) var(--ease-out-quart);
}
dialog[open]{
  opacity:1;
  transform:translateY(0);
}
@starting-style{
  dialog[open]{opacity:0;transform:translateY(-8px)}
}

/* Poll tick: a single, blunt border/background flash on the updated-at cell. */
#status.tick{
  animation:pollTick var(--dur-1) var(--ease-out) 1,
            tickBorder var(--dur-1) var(--ease-out) 1;
}
@keyframes tickBorder{
  0%{border-color:transparent}
  50%{border-color:var(--accent)}
  100%{border-color:transparent}
}

/* Reduced motion: neutralize all feedback animations with named selectors only. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .flip-animating,
  tr.flip-animating td,
  dialog,
  dialog[open],
  #status.tick,
  .sk,
  #reason-pop,
  .sig-row,
  .is-new{
    animation:none;
    transition:none;
    transform:none;
    opacity:1;
  }
}
