/* ==========================================================================
   Investment Analyzer — application stylesheet (R2, 2026-10-22)
   --------------------------------------------------------------------------
   BODY: the owner-approved mockup stylesheet VERBATIM
   (Redesign Plan - Stock Analysis Software/mockups/assets/app.css — designkit
   clean, proven on all 23 mockup pages). TAIL: the R2 legacy bridge (kept
   markup still speaking the old token vocabulary until R3-R8 port the views,
   gone by R9) + permanent shell glue. TOKENS: /static/tokens.css
   (design/tokens.css, installed by R1). Nothing here invents a colour.
   ========================================================================== */

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.45;
  background: var(--color-bg);
  color: var(--color-text);
}
/* HEADER → BODY SPACING — standing design rule (owner, 2026-10-22).
   Every heading carries the SAME gap to its body — var(--sp-4) — everywhere
   in the app: the body always starts sp-4 below a heading, and a heading
   that follows content sits sp-4 below it. :first-child / :last-child keep
   container edges clean. No page may set its own heading margins inline.
   Components with a deliberately tighter rhythm (.card-head, .card-note,
   .report-panel-head) own their gap and override this — those are the
   documented exceptions, not per-page drift. See DESIGN.md §4. */
h1, h2, h3, h4 { margin: var(--sp-4) 0; font-weight: 600; line-height: 1.3; }
h1:first-child, h2:first-child, h3:first-child, h4:first-child { margin-top: 0; }
h1:last-child, h2:last-child, h3:last-child, h4:last-child { margin-bottom: 0; }
h1 { font-size: var(--fs-title); }
h2 { font-size: var(--fs-section); }
h3 { font-size: var(--fs-base); }
h4 { font-size: var(--fs-small); }
p { margin: 0 0 var(--sp-2); }
p:last-child { margin-bottom: 0; }
a { color: var(--color-primary); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font-family: inherit; }
input, select { font-family: inherit; }
:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; border-radius: var(--r-sm); }
.muted { color: var(--color-text-muted); }
.num, td.numeric, th.numeric { font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
/* overflow guardrails (AGENTS.md frontend rule 3) */
.card, .grid > * { min-width: 0; }
.card { overflow-x: auto; }

/* scrollbars — thin, themed */
* { scrollbar-width: thin; scrollbar-color: var(--color-border) transparent; }
*::-webkit-scrollbar { height: 10px; width: 10px; }
*::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 999px; }
*::-webkit-scrollbar-track { background: transparent; }

/* icons — Lucide-style inline SVG, never emoji (designkit noEmoji rule) */
.icon { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2;
        stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; flex: none; }
.icon-lg { width: 20px; height: 20px; }
.icon-sm { width: 13px; height: 13px; }

/* ---------- layout: fixed shell ---------- */
.shell { display: grid; grid-template-columns: var(--nav-w) minmax(0, 1fr); min-height: 100vh; }

/* left navigation */
.nav {
  position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column;
  background: var(--color-surface); border-inline-end: 1px solid var(--color-border);
}
.nav-brand { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-3);
             border-bottom: 1px solid var(--color-border); height: var(--topbar-h); }
.brand-mark { display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--r-md);
              background: var(--color-primary); color: var(--color-on-primary); font-weight: 700; font-size: var(--fs-small); }
.brand-name { font-weight: 600; font-size: var(--fs-small); letter-spacing: .02em; white-space: nowrap; }
.nav-collapse { margin-inline-start: auto; display: grid; place-items: center; width: 26px; height: 26px;
                background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
                color: var(--color-text-muted); cursor: pointer; }
.nav-collapse:hover { color: var(--color-text); background: var(--color-surface-raised); }
.nav-menu { flex: 1; overflow-y: auto; padding: var(--sp-3) var(--sp-2); display: flex; flex-direction: column; gap: 2px; }
.nav-group { font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
             color: var(--color-text-muted); padding: var(--sp-3) var(--sp-2) var(--sp-1); }
.nav-group:first-child { padding-top: 0; }
.nav-item { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-2);
            border-radius: var(--r-md); color: var(--color-text-muted); font-size: var(--fs-base);
            white-space: nowrap; cursor: pointer; }
.nav-item:hover { background: var(--color-surface-raised); color: var(--color-text); text-decoration: none; }
.nav-item.active { background: var(--color-surface-raised); color: var(--color-primary); font-weight: 600; }
.nav-item .nav-tag { margin-inline-start: auto; font-size: var(--fs-tiny); font-weight: 600;
                     color: var(--color-text-muted); border: 1px solid var(--color-border);
                     border-radius: 999px; padding: 0 var(--sp-1); }
.nav-item .nav-dot { margin-inline-start: auto; width: 7px; height: 7px; border-radius: 999px; background: var(--color-warning); }
.nav-foot { border-top: 1px solid var(--color-border); padding: var(--sp-2); }
.nav-user { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2);
            border-radius: var(--r-md); color: var(--color-text-muted); font-size: var(--fs-small); }

/* top bar */
.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: var(--sp-3);
  height: var(--topbar-h); padding: 0 var(--sp-4);
  background: var(--color-surface); border-bottom: 1px solid var(--color-border);
}
.topbar-right { margin-inline-start: auto; display: flex; align-items: center; gap: var(--sp-1); }
/* The search field yields width before the controls do: the top bar must fit
   the 1280px minimum with the full control set (regime, alerts, theme, conv,
   mode, style, avatar + their hints). 32vw overflowed by 33px once the theme
   seg and the two control hints shipped — measured, see REDESIGN-PLAN.md §8.5.
   The 420px cap is unchanged; only the fluid fraction narrows. */
.omni { display: flex; align-items: center; gap: var(--sp-2); width: min(420px, 29vw);
        background: var(--color-surface-raised); border: 1px solid var(--color-border);
        border-radius: var(--r-md); padding: 0 var(--sp-2); height: 30px; color: var(--color-text-muted); }
.omni input { flex: 1; min-width: 0; background: none; border: none; color: var(--color-text);
              font-size: var(--fs-small); height: 28px; }
.omni input:focus { outline: none; }
.omni input::placeholder { color: var(--color-text-muted); }
kbd { font-family: var(--font); font-size: var(--fs-tiny); color: var(--color-text-muted);
      border: 1px solid var(--color-border); border-radius: var(--r-sm); padding: 1px var(--sp-1); }
.icon-btn { position: relative; display: grid; place-items: center; width: 30px; height: 30px;
            background: transparent; border: 1px solid transparent; border-radius: var(--r-md);
            color: var(--color-text-muted); cursor: pointer; }
.icon-btn:hover { background: var(--color-surface-raised); color: var(--color-text); }
/* NOTE (Delta 3): --color-positive/--color-negative carry MARKET direction
   (up/down) and follow the chosen colour convention. Attention, error and
   "failed" states never use them — they use --color-warning, which means the
   same thing in both themes and both conventions. See REDESIGN-PLAN.md §3.1. */
.icon-btn .dot { position: absolute; top: 5px; right: 5px; width: 7px; height: 7px;
                 border-radius: 999px; background: var(--color-warning); }
.avatar { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px;
          background: var(--color-surface-raised); border: 1px solid var(--color-border);
          font-size: var(--fs-tiny); font-weight: 600; color: var(--color-text-muted); }

/* content area */
.content { flex: 1; width: 100%; max-width: 1600px; margin: 0 auto; padding: var(--sp-5); }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-3);
             flex-wrap: wrap; margin-bottom: var(--sp-4); }
/* same guard as .card-head: the head's own margin does the spacing */
.page-head > h1, .page-head > h2 { margin-bottom: 0; }
.page-title { font-size: var(--fs-title); }
.page-sub { font-size: var(--fs-small); color: var(--color-text-muted); margin-top: var(--sp-1); }
.page-actions { display: flex; gap: var(--sp-2); }

/* ---------- components ---------- */
/* card */
.card { background: var(--color-surface); border: 1px solid var(--color-border);
        border-radius: var(--r-md); padding: var(--sp-4); margin-bottom: var(--sp-4); }
.card:last-child { margin-bottom: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
             flex-wrap: wrap; margin-bottom: var(--sp-4); }
/* a heading INSIDE a card-head is the head itself — the head's own margin
   does the spacing, so the heading's uniform margin must not double it */
.card-head > h1, .card-head > h2, .card-head > h3, .card-head > h4 { margin-bottom: 0; }
.card-title { font-size: var(--fs-section); font-weight: 600; }
.card-note { font-size: var(--fs-small); color: var(--color-text-muted); margin-top: calc(-1 * var(--sp-2));
             margin-bottom: var(--sp-4); }
.card-raised { background: var(--color-surface-raised); }

/* buttons */
.btn { display: inline-flex; align-items: center; gap: var(--sp-2); height: 30px; padding: 0 var(--sp-3);
       background: var(--color-surface-raised); color: var(--color-text); font-size: var(--fs-small);
       font-weight: 500; border: 1px solid var(--color-border); border-radius: var(--r-md); cursor: pointer; }
.btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
.btn:disabled { opacity: .5; cursor: wait; }
.btn-primary { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary); font-weight: 600; }
.btn-primary:hover { filter: brightness(1.12); color: var(--color-on-primary); }
.btn-danger:hover { border-color: var(--color-warning); color: var(--color-warning); }
.btn-block { width: 100%; justify-content: center; height: 34px; }

/* chips & badges */
.chip { display: inline-flex; align-items: center; gap: var(--sp-1); padding: 2px var(--sp-2);
        border: 1px solid var(--color-border); border-radius: 999px; background: var(--color-surface-raised);
        font-size: var(--fs-tiny); font-weight: 600; white-space: nowrap; }
.chip-up { color: var(--color-positive); border-color: var(--color-positive); }
.chip-down { color: var(--color-negative); border-color: var(--color-negative); }
.chip-neutral { color: var(--color-text-muted); }
.chip-warn { color: var(--color-warning); border-color: var(--color-warning); }
.chip-info { color: var(--color-primary); border-color: var(--color-primary); }
.chip-btn { cursor: pointer; background: transparent; font-weight: 500; }
.chip-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
.badge { display: inline-flex; align-items: center; gap: var(--sp-1); padding: 2px var(--sp-2);
         border: 1px solid var(--color-border); border-radius: var(--r-sm);
         background: var(--color-surface-raised); font-size: var(--fs-tiny); color: var(--color-text-muted); }
.badge b { color: var(--color-text); font-weight: 600; }

/* hint mark ("!") — mandatory on every metric/label (AGENTS.md rule 2).
   PLACEMENT — standing design rule (owner, 2026-10-22): the mark always sits
   INSIDE its word's own element (never as a sibling after a block, which
   drops it onto its own line), at the fixed distance of 3px, on the same
   line as the word. flex: none keeps it from shrinking inside flex rows. */
.hint { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px;
        border-radius: 999px; border: 1px solid var(--color-primary); color: var(--color-primary);
        font-size: var(--fs-tiny); font-weight: 700; line-height: 1; cursor: help; vertical-align: 1px;
        margin-inline-start: 3px; user-select: none; opacity: .8; flex: none; }
.hint:hover, .hint.open { opacity: 1; background: var(--color-surface-raised); }

/* tables — dense, sticky headers, tabular numbers */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
th, td { text-align: start; padding: 0 var(--sp-3); border-bottom: 1px solid var(--color-border); }
thead th { position: sticky; top: 0; z-index: 1; height: var(--row-h); background: var(--color-surface-raised);
           color: var(--color-text-muted); font-weight: 600; font-size: var(--fs-small); white-space: nowrap; }
tbody td { height: var(--row-h); }
tbody tr:last-child td { border-bottom: none; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover td { background: var(--color-surface-raised); }
td.numeric, th.numeric { text-align: end; font-variant-numeric: tabular-nums; }
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--color-text); }
td .sub { display: block; font-size: var(--fs-tiny); color: var(--color-text-muted); }
.ticker { font-weight: 700; }
.table-foot { font-size: var(--fs-small); color: var(--color-text-muted); margin-top: var(--sp-3); }
/* Owner table rules (2026-10-23, REDESIGN-PLAN.md §8.6):
   1. every table carries a header row — a header cell is never left blank; an
      actions or badge column gets a real label ("Actions", "New") and its hint.
   2. a hint always lies IN a header cell: the column header for data tables,
      the row header (th scope="row") for term→value tables — never on a body
      cell, a value or a button. tbody th therefore renders like a term cell.
   3. a column's width is set by the table's own <colgroup> (fixed layout), so
      no column's content can reflow another — mandatory where cells change at
      runtime (label swaps, async badges). A control whose label changes gets
      .btn-fixed so its own width never moves its siblings. */
tbody th { font-weight: 400; white-space: normal; }
.table-fixed { table-layout: fixed; }
.btn-fixed { min-width: 6rem; text-align: center; }

/* tabs */
.tabs { display: flex; gap: var(--sp-1); flex-wrap: wrap; margin-bottom: var(--sp-3); }
.tabs button { background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text-muted);
               border-radius: var(--r-md); padding: var(--sp-2) var(--sp-3); font-size: var(--fs-small); cursor: pointer; }
.tabs button:hover { color: var(--color-text); }
.tabs button.active { border-bottom: 2px solid var(--color-primary); color: var(--color-primary); font-weight: 600; }

/* forms */
.input, .select { height: 30px; background: var(--color-surface-raised); color: var(--color-text);
                  border: 1px solid var(--color-border); border-radius: var(--r-md);
                  padding: 0 var(--sp-3); font-size: var(--fs-base); }
.input:focus, .select:focus { outline: none; border-color: var(--color-primary); }
.input::placeholder { color: var(--color-text-muted); }
.field { display: flex; flex-direction: column; gap: var(--sp-1); }
.field label { font-size: var(--fs-small); color: var(--color-text-muted); }
.searchrow { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.searchrow .input { flex: 1; min-width: 12rem; height: 34px; font-size: var(--fs-section); }
.quick-chips { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-3);
               font-size: var(--fs-small); }

/* segmented control (mode toggle, chart range) */
.seg { display: inline-flex; border: 1px solid var(--color-border); border-radius: var(--r-md);
       overflow: hidden; background: var(--color-surface-raised); }
.seg button { background: transparent; border: none; color: var(--color-text-muted); cursor: pointer;
              padding: var(--sp-1) var(--sp-3); font-size: var(--fs-small); }
.seg button.active { background: var(--color-primary); color: var(--color-on-primary); font-weight: 600; }
.seg-theme button { padding: var(--sp-1); display: inline-flex; align-items: center; }
/* D2 — gain/loss convention switch. Each button shows the up/down arrow pair
   in THAT convention's colours, so the control demonstrates its own setting. */
.seg-conv button { padding: var(--sp-1); display: inline-flex; align-items: center; gap: 2px; }
.seg-conv .ic-up { color: var(--up-cn); }
.seg-conv .ic-down { color: var(--down-cn); }
.seg-conv [data-conv-btn="intl"] .ic-up { color: var(--up-intl); }
.seg-conv [data-conv-btn="intl"] .ic-down { color: var(--down-intl); }
/* numeric emphasis (replaces inline styles — audit finding A2). The number,
   its sign or its column header is always the non-colour carrier (principle B). */
.num-pos { color: var(--color-positive); }
.num-neg { color: var(--color-negative); }
.style-select { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-small); color: var(--color-text-muted); }
.style-select .select { height: 26px; font-size: var(--fs-small); padding: 0 var(--sp-2); }

/* progress */
.progress { height: 6px; background: var(--color-surface-raised); border: 1px solid var(--color-border);
            border-radius: 999px; overflow: hidden; }
.progress > div { height: 100%; background: var(--color-primary); }

/* score bar (0–100 inline bar) */
.scorebar { display: flex; align-items: center; gap: var(--sp-2); }
.scorebar .track { flex: 1; min-width: 48px; height: 5px; background: var(--color-surface-raised);
                   border-radius: 999px; overflow: hidden; }
.scorebar .fill { height: 100%; background: var(--color-primary); border-radius: 999px; }
.scorebar .val { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 34px; text-align: end; }

/* probability stacked bar (bull / neutral / bear) */
.probbar { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: var(--color-surface-raised); }
.probbar span { display: block; height: 100%; }
.probbar .b-bull { background: var(--color-positive); }
.probbar .b-neu { background: var(--color-text-muted); }
.probbar .b-bear { background: var(--color-negative); }
.probrow { display: grid; grid-template-columns: 64px 1fr 128px; gap: var(--sp-3); align-items: center;
           padding: var(--sp-2) 0; border-bottom: 1px solid var(--color-border); }
.probrow:last-child { border-bottom: none; }
.probrow .when { font-weight: 600; font-size: var(--fs-small); }
.probrow .vals { display: flex; gap: var(--sp-3); font-size: var(--fs-small); font-variant-numeric: tabular-nums; }
.probrow .vals b { font-weight: 600; }

/* delta with arrow — readable WITHOUT colour (DESIGN.md §4) */
.delta { display: inline-flex; align-items: center; gap: 2px; font-variant-numeric: tabular-nums; font-weight: 600; }
.delta.up { color: var(--color-positive); }
.delta.down { color: var(--color-negative); }
.delta.flat { color: var(--color-text-muted); }

/* warning banner (honesty labels — AGENTS.md rule 7) */
.banner { display: flex; gap: var(--sp-2); align-items: flex-start; padding: var(--sp-3);
          border: 1px solid var(--color-warning); border-radius: var(--r-md);
          background: var(--color-surface-raised); color: var(--color-warning);
          font-size: var(--fs-small); margin-bottom: var(--sp-4); }
.banner .icon { margin-top: 2px; }
.banner.info { border-color: var(--color-primary); color: var(--color-primary); }

/* empty / loading / error states (DESIGN.md §4) */
.state { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
         padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--color-text-muted); }
.state .icon { width: 22px; height: 22px; }
.state .state-title { font-weight: 600; color: var(--color-text); font-size: var(--fs-base); }
.state .state-body { font-size: var(--fs-small); max-width: 46ch; }
.state.error { color: var(--color-warning); }
.state.error .state-title { color: var(--color-warning); }
.skeleton { height: 12px; border-radius: var(--r-sm); background: var(--color-surface-raised); margin-bottom: var(--sp-2); }

/* key-value grid */
.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4); font-size: var(--fs-base); }
.kv dt { color: var(--color-text-muted); }
.kv dd { margin: 0; font-variant-numeric: tabular-nums; font-weight: 600; text-align: end; }

/* score gauge (ring) */
.gauge { position: relative; width: 84px; height: 84px; }
.gauge svg { transform: rotate(-90deg); }
.gauge .gauge-val { position: absolute; inset: 0; display: grid; place-items: center;
                    font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- views ---------- */
/* dashboard */
.dash-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); }
.dash-grid .card { margin-bottom: 0; }
.regime-hero { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }
.regime-hero .regime-word { font-size: var(--fs-title); font-weight: 700; letter-spacing: .04em; }
.regime-hero .regime-word.up { color: var(--color-positive); }
.regime-hero .regime-word.down { color: var(--color-negative); }
.regime-hero .regime-word.flat { color: var(--color-warning); }
.regime-metrics { display: flex; gap: var(--sp-5); flex-wrap: wrap; }
.regime-metric { display: flex; flex-direction: column; gap: 2px; }
.regime-metric .k { font-size: var(--fs-tiny); color: var(--color-text-muted); }
.regime-metric .v { font-size: var(--fs-section); font-weight: 600; font-variant-numeric: tabular-nums; }
.search-hero { background: linear-gradient(180deg, var(--color-surface-raised), var(--color-surface)); }
.search-hero .card-title { margin-bottom: var(--sp-4); }

/* analyze — stock header */
.stock-head-grid { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-5); align-items: start; }
.stock-id h1 { font-size: var(--fs-title); }
.stock-id .company { font-size: var(--fs-section); font-weight: 400; }
.opp-chip { display: inline-flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2);
            padding: var(--sp-1) var(--sp-3); border-radius: var(--r-md); font-size: var(--fs-small);
            font-weight: 700; letter-spacing: .06em; border: 1px solid; }
.opp-chip.up { color: var(--color-positive); border-color: var(--color-positive); background: var(--color-surface-raised); }
.opp-chip.down { color: var(--color-negative); border-color: var(--color-negative); background: var(--color-surface-raised); }
.opp-chip.flat { color: var(--color-warning); border-color: var(--color-warning); background: var(--color-surface-raised); }
.price-row { display: flex; align-items: baseline; gap: var(--sp-3); margin-top: var(--sp-3); }
.price-row .price { font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; }
.badge-row { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-3); }
.stock-actions { display: flex; flex-direction: column; gap: var(--sp-2); }
.stock-meta { display: flex; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-2); font-size: var(--fs-small); color: var(--color-text-muted); }

/* price chart */
.chart-scroll { overflow-x: auto; }
.pricechart { display: block; width: 100%; min-width: 640px; height: auto; }
.pricechart .grid { stroke: var(--color-border); stroke-width: .5; opacity: .6; }
.pricechart .axis { fill: var(--color-text-muted); font-size: var(--fs-tiny); font-family: ui-monospace, monospace; }
.pricechart .candle line { stroke-width: 1; }
.pricechart .candle.up line, .pricechart .candle.up rect { stroke: var(--candle-up); }
.pricechart .candle.up rect { fill: var(--candle-up); }
.pricechart .candle.down line, .pricechart .candle.down rect { stroke: var(--candle-down); }
.pricechart .candle.down rect { fill: var(--candle-down); }
.pricechart .vol { opacity: .25; }
.pricechart .vol.up { fill: var(--candle-up); }
.pricechart .vol.down { fill: var(--candle-down); }
.pricechart .lvl { stroke: var(--color-text-muted); stroke-width: 1; opacity: .8; }
.pricechart .lvl.support { stroke-dasharray: 5 3; }
.pricechart .lvl.resistance { stroke-dasharray: 2 3; }
.pricechart .lvl-label { fill: var(--color-text-muted); font-size: var(--fs-tiny); font-family: ui-monospace, monospace; }
.chart-legend { display: flex; gap: var(--sp-4); flex-wrap: wrap; margin-top: var(--sp-2);
                font-size: var(--fs-tiny); color: var(--color-text-muted); }

/* two/three column content grids */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4); }
.grid-2 .card { margin-bottom: 0; }
.grid-2 + .grid-2, .grid-2 + .card { margin-top: var(--sp-4); }

/* factor columns — the h4 keeps the uniform header→body gap (design rule) */
.factor-col h4 { display: flex; align-items: center; gap: var(--sp-2); }
.factor-col h4.up { color: var(--color-positive); }
.factor-col h4.down { color: var(--color-negative); }
.factor-list { margin: 0; padding: 0; list-style: none; }
.factor-list li { padding: var(--sp-2) 0; border-bottom: 1px solid var(--color-border); font-size: var(--fs-base); }
.factor-list li:last-child { border-bottom: none; }

/* beginner mode */
body[data-mode="beginner"] .advanced-only { display: none !important; }
body[data-mode="advanced"] .beginner-only { display: none !important; }
.b-lead { font-size: var(--fs-section); line-height: 1.55; max-width: 68ch; }
.b-intro { color: var(--color-text-muted); font-size: var(--fs-base); max-width: 64ch; }
.b-verdict { font-size: var(--fs-section); font-weight: 700; }
.b-price-row { display: flex; gap: var(--sp-5); flex-wrap: wrap; margin: var(--sp-3) 0; }
.b-price-row .b-num { display: block; font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; }
.b-price-row .b-cap { display: block; font-size: var(--fs-tiny); color: var(--color-text-muted); margin-bottom: 2px; }
.b-step { counter-increment: bstep; }
.b-steps { counter-reset: bstep; }
.b-step h3::before { content: counter(bstep) ". "; color: var(--color-primary); }
.b-step { margin-top: var(--sp-5); }
.b-horizon { display: grid; grid-template-columns: 96px 1fr; gap: var(--sp-4); align-items: start;
             padding: var(--sp-3) 0; border-top: 1px solid var(--color-border); }
.b-horizon:first-of-type { border-top: none; }
.b-horizon .b-when { font-weight: 700; }
.b-scen { line-height: 1.5; margin-bottom: var(--sp-1); }
.b-scen .b-tag { font-weight: 700; }
.b-scen .b-tag.up { color: var(--color-positive); }
.b-scen .b-tag.down { color: var(--color-negative); }
.b-scen .b-tag.flat { color: var(--color-text-muted); }

/* guide */
.guide-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
.guide-sidebar { position: sticky; top: calc(var(--topbar-h) + var(--sp-4)); display: flex; flex-direction: column; gap: 2px; }
.guide-cat-btn { padding: var(--sp-2); border-radius: var(--r-md); font-size: var(--fs-base); font-weight: 500;
                 color: var(--color-text-muted); cursor: pointer; border: 1px solid transparent; }
.guide-cat-btn:hover { background: var(--color-surface-raised); color: var(--color-text); }
.guide-cat-btn.active { background: var(--color-surface-raised); color: var(--color-primary); font-weight: 600; }
.guide-topic-card { margin-bottom: var(--sp-4); }
.guide-topic-card h3 { color: var(--color-primary); }
.guide-headline { font-size: var(--fs-section); font-weight: 600; margin: var(--sp-4) 0; }
.guide-formula { font-family: ui-monospace, monospace; background: var(--color-surface-raised);
                 padding: var(--sp-3); border-radius: var(--r-sm); display: block; margin: var(--sp-2) 0;
                 font-size: var(--fs-small); overflow-x: auto; }
.guide-bench { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3); margin-top: var(--sp-3); }
.guide-bench-card { background: var(--color-surface-raised); padding: var(--sp-3); border-radius: var(--r-sm); }
.guide-bench-card h5 { margin: 0 0 var(--sp-1); font-size: var(--fs-small); }
.guide-bench-card h5.up { color: var(--color-positive); }
.guide-bench-card h5.flat { color: var(--color-text-muted); }
.guide-bench-card h5.down { color: var(--color-negative); }

/* login */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: var(--sp-4); }
.auth-card { width: min(400px, 100%); }
.auth-card .brand-mark { width: 34px; height: 34px; font-size: var(--fs-base); margin-bottom: var(--sp-3); }
.auth-error { display: flex; gap: var(--sp-2); align-items: center; margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3);
              border: 1px solid var(--color-warning); border-radius: var(--r-md); color: var(--color-warning);
              font-size: var(--fs-small); }

/* mockup-only chrome (not part of the app) */
.mock-banner { position: sticky; top: 0; z-index: 50; text-align: center; font-size: var(--fs-tiny);
               font-weight: 600; letter-spacing: .04em; color: var(--color-warning);
               background: var(--color-surface-raised); border-bottom: 1px solid var(--color-warning); padding: 3px; }
.mock-note { font-size: var(--fs-tiny); color: var(--color-text-muted); text-align: center; padding: var(--sp-4); }

/* gallery */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--sp-4); }
.gallery a { color: inherit; }
.gallery a:hover { text-decoration: none; }
.gallery .card { margin-bottom: 0; height: 100%; }
.gallery .card:hover { border-color: var(--color-primary); }
.gallery .g-num { font-size: var(--fs-tiny); color: var(--color-text-muted); }
.gallery .g-title { font-size: var(--fs-section); font-weight: 600; margin: var(--sp-1) 0; }
.gallery .g-desc { font-size: var(--fs-small); color: var(--color-text-muted); }

/* ---------- responsive ---------- */
/* DESIGN.md §5: minimum supported width 1280px (desktop-first). Below that the
   shell stays usable but dense tables scroll inside their cards. */
@media (max-width: 1279px) {
  .dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
  .grid-2 + .grid-2 { margin-top: var(--sp-4); }
  .guide-layout { grid-template-columns: minmax(0, 1fr); }
  .guide-sidebar { position: static; flex-direction: row; flex-wrap: wrap; }
}
@media (max-width: 900px) {
  .shell { grid-template-columns: 56px minmax(0, 1fr); }
  .nav-brand .brand-name, .nav-item span, .nav-group, .nav-user span, .nav-collapse { display: none; }
  .nav-brand, .nav-item { justify-content: center; }
  .dash-grid { grid-template-columns: minmax(0, 1fr); }
  .stock-head-grid { grid-template-columns: minmax(0, 1fr); }
  .omni { width: auto; flex: 1; }
  /* B-0014 (F-016): the control cluster (.topbar-right — theme, convention,
     mode, style, avatar ≈ 601px at full width) cannot fit one 48px row on a
     phone (measured at 375px: the document scrolled sideways to 908px). The
     bar wraps to a second row instead; sticky positioning keeps working and
     the desktop 1280px layout is untouched (media-scoped). */
  .topbar { flex-wrap: wrap; height: auto; min-height: var(--topbar-h); row-gap: var(--sp-1); padding-block: var(--sp-1); }
  .topbar-right { flex-wrap: wrap; row-gap: var(--sp-1); }
}

/* ==========================================================================
   LEGACY BRIDGE — R2 (2026-10-22), audited and trimmed at R9 (2026-10-25).
   --------------------------------------------------------------------------
   The shell speaks the new token vocabulary (design/tokens.css) and all nine
   views now render the approved mockup composition. What remains here is NOT
   leftover view markup: it is the chrome the mockups never covered, plus the
   old token names app.js still writes in inline styles.

   R9 audit (evidence: REDESIGN-PLAN §8.11) — every row below is still emitted
   by live code. Two provably dead rows were deleted at R9:
     · `.grid` (the old dashboard layout grid — only `<line class="grid">`
       chart gridlines remain, and app.css styles those via `.pricechart .grid`);
     · `.b-bar` + `.b-bar span` + `.b-bar .b-*` (the beginner bar was replaced
       by `.probbar` in R5; app.css owns `.probbar .b-*`).
   Still live, and why they cannot be deleted yet:
     · old token aliases — app.js writes var(--card2)/var(--accent) inline;
     · report overlay, hint bubble, auth form controls, footer, alert badge;
     · severity chips, evidence list, quickview placeholder, search dropdowns;
     · button.primary / .btn-small (auth card, replay buttons, sign-out);
     · the two AGENTS.md rule-3 guardrails (th nowrap / td break-word).
   Removing the rest needs app.js inline styles migrated to tokens — a
   follow-up, deliberately NOT part of the R9 regression. Nothing here is new
   design: every value points at an approved token; the only literal colours
   are the two overlay scrims (no token can express "black at 62%").
   ========================================================================== */

/* ---- old token names → new tokens (aliases, not new colours) ---- */
:root {
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card2: var(--color-surface-raised);
  --text: var(--color-text);
  --muted: var(--color-text-muted);
  --accent: var(--color-primary);
  --pos: var(--color-positive);   /* market direction — follows data-conv (D2) */
  --neg: var(--color-negative);  /* market direction — follows data-conv (D2) */
  --neu: var(--color-warning);   /* neutral/caution — NOT a market direction */
  --border: var(--color-border);
}

th { white-space: nowrap; }
td { overflow-wrap: break-word; }
/* The two guardrails above are asserted by EXACT selector (check_frontend.py):
   nothing — not even a comment — may sit between the previous rule's closing
   brace and `th`/`td`, because the checker's CSS regex folds a preceding
   comment into the selector string and `s == "th"` then never matches. */

/* ---- analyze kept markup ---- */
.score-big { font-size: var(--fs-title); font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.opp { font-size: var(--fs-section); font-weight: 700; letter-spacing: .04em; }
.pos { color: var(--color-positive); }
.neg { color: var(--color-negative); }
.neu { color: var(--color-warning); }
.quickview-top { display: flex; gap: var(--sp-5); align-items: center; flex-wrap: wrap; }

/* ---- search results (bindSearch output — dashboard, analyze, omnibox) ---- */
.search-results { margin-top: var(--sp-2); }
.search-results .item, .omni-results .item {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm); cursor: pointer;
  font-size: var(--fs-small);
}
.search-results .item:hover, .omni-results .item:hover { background: var(--color-surface-raised); }
.search-results .sym, .omni-results .sym { font-weight: 700; color: var(--color-primary); white-space: nowrap; }
/* the top-bar omnibox dropdown (new shell glue, R2) */
.omni-wrap { position: relative; }
.omni-results { position: absolute; top: calc(100% + var(--sp-1)); inset-inline-start: 0; width: min(420px, 60vw);
                z-index: 30; background: var(--color-surface); border: 1px solid var(--color-border);
                border-radius: var(--r-md); padding: var(--sp-1); box-shadow: 0 12px 32px rgba(0, 0, 0, .45); }

/* ---- findings review-queue severity chips (app.js render) ---- */
.sev { display: inline-block; padding: 0 var(--sp-2); border-radius: 999px;
       font-size: var(--fs-tiny); border: 1px solid var(--color-border); }
.sev-high { color: var(--color-negative); border-color: var(--color-negative); }
.sev-medium { color: var(--color-warning); border-color: var(--color-warning); }
.sev-low { color: var(--color-text-muted); }

/* ---- evidence list (analyze deep tabs) ---- */
.evidence-list { list-style: none; padding: 0; margin: 0; }
.evidence-list li { padding: var(--sp-2) 0; border-bottom: 1px solid var(--color-border); }
.evidence-list li:last-child { border-bottom: none; }
.evidence-list .claim { font-weight: 600; }
.evidence-list .ev { color: var(--color-text-muted); font-size: var(--fs-small); }

/* ---- honesty banner (AGENTS.md rule 7) — warning, never market tokens ---- */
.warning { background: var(--color-surface-raised); border: 1px solid var(--color-warning);
           border-radius: var(--r-md); color: var(--color-warning);
           padding: var(--sp-3); font-size: var(--fs-small); margin: var(--sp-3) 0; }

/* ---- small buttons (kept views: Refresh / Mark all read / Run evaluation…) ---- */
.btn-small { display: inline-flex; align-items: center; gap: var(--sp-1); height: 26px; padding: 0 var(--sp-3);
             background: var(--color-surface-raised); color: var(--color-text); font-size: var(--fs-small);
             border: 1px solid var(--color-border); border-radius: var(--r-sm); cursor: pointer; }
.btn-small:hover { border-color: var(--color-primary); color: var(--color-primary); }
.btn-small.danger { color: var(--color-warning); border-color: var(--color-warning); }

/* ---- report overlay (opened on demand, never inline) ---- */
.report-overlay { position: fixed; inset: 0; z-index: 90; background: rgba(0, 0, 0, .62);
                  display: flex; align-items: flex-start; justify-content: center;
                  padding: var(--sp-6) var(--sp-4); overflow-y: auto; }
.report-panel { background: var(--color-surface); border: 1px solid var(--color-border);
                border-radius: var(--r-md); width: 100%; max-width: 1040px; min-width: 0;
                box-shadow: 0 18px 60px rgba(0, 0, 0, .6); }
.report-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
                     padding: var(--sp-4); border-bottom: 1px solid var(--color-border);
                     position: sticky; top: 0; background: var(--color-surface); z-index: 1; }
.report-panel-head h3 { margin: 0; font-size: var(--fs-section); }
.report-close { display: grid; place-items: center; width: 30px; height: 30px; flex-shrink: 0;
                background: var(--color-surface-raised); color: var(--color-text);
                border: 1px solid var(--color-border); border-radius: var(--r-sm); cursor: pointer; }
.report-close:hover { color: var(--color-warning); border-color: var(--color-warning); }
.report-panel-body { padding: var(--sp-4); min-width: 0; overflow-x: auto; overflow-wrap: break-word; }
.report-panel-body > .card { background: var(--color-surface-raised); }
.report-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-4);
                  padding-top: var(--sp-3); border-top: 1px solid var(--color-border); }
.report-btn { display: inline-flex; align-items: center; gap: var(--sp-2); height: 30px; padding: 0 var(--sp-3);
              background: var(--color-primary); color: var(--color-on-primary); border: none;
              border-radius: var(--r-md); font-size: var(--fs-small); font-weight: 600; cursor: pointer; }
.report-btn:hover { filter: brightness(1.12); }
.report-btn.secondary { background: var(--color-surface-raised); color: var(--color-text);
                        border: 1px solid var(--color-border); }
.report-btn.secondary:hover { border-color: var(--color-primary); color: var(--color-primary); }

/* ---- hint bubble (created by hints.js — needs its styles from us) ---- */
#hintBubble { display: none; position: fixed; z-index: 100; max-width: 320px;
              background: var(--color-surface); border: 1px solid var(--color-primary);
              border-radius: var(--r-md); padding: var(--sp-2) var(--sp-3);
              font-size: var(--fs-small); line-height: 1.45;
              box-shadow: 0 8px 28px rgba(0, 0, 0, .55); }
#hintBubble .hint-title { font-weight: 700; color: var(--color-primary); margin-bottom: var(--sp-1); }
#hintBubble .hint-body { color: var(--color-text); }

/* ---- auth overlay (login / forced password change) ---- */
.auth-overlay { position: fixed; inset: 0; z-index: 100; background: rgba(10, 13, 20, .82);
                display: flex; align-items: center; justify-content: center; }

/* ---- guide content column + app footer (kept markup) ---- */
.guide-content { min-width: 0; }
.app-foot { text-align: center; color: var(--color-text-muted); font-size: var(--fs-small);
            padding: var(--sp-5) 0 var(--sp-2); }

/* ---- alert badge inside the top-bar bell (R2 shell glue) ---- */
.icon-btn .badge { position: absolute; top: -5px; right: -5px; padding: 0 5px; height: 15px;
                   background: var(--color-warning); border-color: var(--color-warning);
                   color: var(--color-bg); font-weight: 700; }

/* ---- kept markup whose styling app.css expresses only through classes the
   old HTML never carried (ported views drop these rows in R3-R8) ---- */
/* the Analyze buttons (dashboard + analyze views) and the auth submit buttons */
button.primary { display: inline-flex; align-items: center; gap: var(--sp-2); height: 34px;
                 padding: 0 var(--sp-4); background: var(--color-primary); color: var(--color-on-primary);
                 border: none; border-radius: var(--r-md); font-size: var(--fs-section);
                 font-weight: 600; cursor: pointer; }
button.primary:hover { filter: brightness(1.12); }
button.primary:disabled { opacity: .5; cursor: wait; }
/* the kept search inputs now carry class="input" (owner note 4, 2026-10-22 —
   one search-bar design project-wide), so app.css `.searchrow .input` skins
   them; this bridge row is deleted. The bare `.searchrow input` skin it
   replaces lived here until then. */
/* auth overlay form controls (auth.js renders bare label/input) */
.auth-card label { display: block; color: var(--color-text-muted); font-size: var(--fs-small);
                   margin: var(--sp-3) 0 var(--sp-1); }
.auth-card input { width: 100%; height: 32px; padding: 0 var(--sp-3); font-size: var(--fs-base);
                   background: var(--color-surface-raised); color: var(--color-text);
                   border: 1px solid var(--color-border); border-radius: var(--r-md); }
.auth-card input:focus { outline: none; border-color: var(--color-primary); }

/* ---- beginner-mode prose block (app.js renders .b-mode-intro; the mockup
   pages do not carry it). The old .b-bar/.b-* bar was deleted at R9 — the
   beginner bar is `.probbar` since R5 and app.css owns it. ---- */
.b-mode-intro { color: var(--color-text-muted); font-size: var(--fs-base); max-width: 64ch;
                margin: 0 0 var(--sp-2); }

/* ---- SHELL GLUE — permanent (the shell is not ported view-by-view) ----
   The mockups render nav items as anchors; the SPA needs buttons, and a
   button keeps its native background/border unless reset. */
button.nav-item { background: transparent; border: none; width: 100%; }
.nav-user .btn-small { margin-inline-start: auto; flex: none; }
/* NOTE for R3-R8: .btn-small above lives in the kept-views section but the
   shell's sign-out button uses it too — move it here when the last view ports. */
