/* Brown Bear Research — one stylesheet, light and dark.
   Deliberately restrained: this is a reference publication, not a trading
   terminal. Score bands use a neutral warm ramp rather than red/green, because
   green-means-buy is exactly the inference the site should not invite. */

/* ---------------- Newsreader (headings) ----------------
   Self-hosted, NOT loaded from Google's CDN. Two reasons, both structural:
   the site makes no third-party requests from a visitor's browser (system UI
   font, inline SVG charts, locally-served logos, no analytics), and a webfont
   request would hand every page view to a third party along with the reader's
   IP. Serving the file ourselves keeps that property intact.

   Variable font, weight 200-800 in one file, latin subset. Licensed under the
   SIL Open Font License 1.1 (Production Type) — free to self-host and modify,
   attribution retained in this comment.

   `font-display: swap` means headings paint immediately in the fallback serif
   and reflow when the file lands. On a page whose first paint is a masthead and
   a card of numbers, a flash of fallback text is much cheaper than a blank
   heading — `optional` would drop the font entirely on a slow connection, and
   `block` would leave the headings invisible for up to 3 seconds. */
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/static/newsreader-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 200 800;
  font-display: swap;
  src: url("/static/newsreader-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg:        #fbfaf8;
  --surface:   #ffffff;
  --ink:       #1a1714;
  --ink-soft:  #5c554d;
  --ink-faint: #8a8178;
  --line:      #e6e1da;
  --accent:    #7a4f24;
  --accent-sf: #f0e6da;
  --shadow:    0 1px 2px rgba(26,23,20,.05), 0 4px 12px rgba(26,23,20,.04);
  --radius:    0;

  /* Chart series. Two hues of equal weight, both legible on the warm paper. */
  --series-a:  #7a4f24;
  --series-b:  #46707d;

  /* Newspaper pairing: a transitional serif for headings and a humanist sans
     for running text, data and controls — the arrangement the FT uses.
     Both stacks are system fonts: no webfont request, so no third-party
     dependency and nothing to block the first paint. */
  /* Newsreader (2026-08-12), replacing the system-serif stack for headings.
     SELF-HOSTED from web/static/ — see the @font-face block below. Publico was
     tried first and rejected: it is a commercial Commercial Type face with no
     free version, so it could only ever have rendered for readers who already
     owned it. The system fallbacks stay behind it for the moment before the
     font file arrives, and for anything that fails to load it. */
  --font-display: Newsreader, "Iowan Old Style", Charter, "Source Serif 4",
                  "Source Serif Pro", Cambria, Georgia, "Times New Roman", serif;
  --font-ui: "Segoe UI Variable Text", "Segoe UI", ui-sans-serif, -apple-system,
             Roboto, Helvetica, Arial, sans-serif;
}

:root {
  --band-high-bg: #efe3d2;
  --band-mid-bg:  #f3ece2;
  --band-low-bg:  #f6f4f0;
  --band-vlow-bg: #f9f8f6;
}

/* Dark palette, reachable two ways: the operating system's preference, or the
   reader's explicit choice via the header toggle. The values are duplicated
   because CSS cannot share one declaration block between a media query and a
   plain selector — keep the two lists in step. `[data-theme="light"]` wins over
   the OS preference so the toggle can force light on a dark machine. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:        #14120f;
    --surface:   #1c1916;
    --ink:       #f0ece6;
    --ink-soft:  #b3aaa0;
    --ink-faint: #857c72;
    --line:      #2e2924;
    --accent:    #d8a366;
    --accent-sf: #2a2219;
    --series-a:  #c98f4f;
    --series-b:  #6fa8ba;
    --shadow:    0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.25);
    --band-high-bg: #3a2c18;
    --band-mid-bg:  #2c251b;
    --band-low-bg:  #232019;
    --band-vlow-bg: #1e1b17;
  }
}

:root[data-theme="dark"] {
    --bg:        #14120f;
    --surface:   #1c1916;
    --ink:       #f0ece6;
    --ink-soft:  #b3aaa0;
    --ink-faint: #857c72;
    --line:      #2e2924;
    --accent:    #d8a366;
    --accent-sf: #2a2219;
    --series-a:  #c98f4f;
    --series-b:  #6fa8ba;
    --shadow:    0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.25);
    --band-high-bg: #3a2c18;
    --band-mid-bg:  #2c251b;
    --band-low-bg:  #232019;
    --band-vlow-bg: #1e1b17;
}

* { box-sizing: border-box; }

/* Anchor jumps glide rather than teleport, so the reader keeps their place on a
   long page. Suppressed for anyone who has asked for less motion. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.6 var(--font-ui);
  -webkit-font-smoothing: antialiased;
}

/* Headings carry the serif. Data keeps the sans: lining tabular figures line up
   in a column, old-style serif figures do not. */
h1, h2, h3, .hero h1, .tk-head h1 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.012em;
}
.hero h1, .tk-head h1 { font-weight: 700; letter-spacing: -.022em; line-height: 1.15; }
/* Section labels read as a masthead rubric rather than a UI heading. */
.screen-head h2, .panel > h2, .panel-head h2 {
  font-family: var(--font-display);
}
.col-key, .tile-label, .sub {
  font-family: var(--font-ui);
}

.wrap { max-width: 1120px; margin: 0 auto; padding: 0 20px; }
/* The hero block used to open the page with 44px of padding; it was removed on
   2026-08-11 and took the gap under the sticky masthead with it, leaving the
   first cards butted against the header. */
main.wrap { padding-top: 26px; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* -- masthead -- */

.masthead {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky; top: 0; z-index: 20;
}
.masthead-inner {
  display: flex; align-items: center; gap: 20px;
  padding-top: 14px; padding-bottom: 14px;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; color: var(--ink); }
.brand:hover { text-decoration: none; }
/* Width follows from the intrinsic 1018x224 ratio, so the img keeps its aspect
   and the browser reserves the right box before the file arrives. */
.brand-logo { display: block; height: 34px; width: auto; }
/* Two logo files, one per theme — both JPEGs, so neither has transparency and
   the light one would sit in a white slab on a dark page. Only one is ever
   displayed; the other still downloads, which at 52KB is the acceptable cost of
   having the correct one present the instant the theme flips. */
.brand-logo.for-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo.for-light { display: none; }
  :root:not([data-theme="light"]) .brand-logo.for-dark { display: block; }
}
:root[data-theme="dark"] .brand-logo.for-light { display: none; }
:root[data-theme="dark"] .brand-logo.for-dark { display: block; }
:root[data-theme="light"] .brand-logo.for-light { display: block; }
:root[data-theme="light"] .brand-logo.for-dark { display: none; }

/* Theme toggle */
.theme-toggle {
  margin-left: 4px; width: 34px; height: 34px; flex: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: transparent; color: var(--ink-soft);
  font-size: .95rem; line-height: 1;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle .icon-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-light { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .icon-dark { display: inline; }
}
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-dark { display: inline; }
:root[data-theme="light"] .theme-toggle .icon-light { display: inline; }
:root[data-theme="light"] .theme-toggle .icon-dark { display: none; }

.search { position: relative; display: flex; gap: 8px; flex: 1 1 300px; max-width: 460px; }
.search input {
  flex: 1; padding: 9px 12px; font-size: .95rem;
  border: 1px solid var(--line); border-radius: 0;
  background: var(--bg); color: var(--ink);
}
.search input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.search button {
  padding: 9px 16px; border: 0; border-radius: 0; cursor: pointer;
  background: var(--accent); color: #fff; font-size: .9rem; font-weight: 500;
}
.suggestions {
  position: absolute; top: 105%; left: 0; right: 0; z-index: 30;
  margin: 0; padding: 4px; list-style: none;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 0; box-shadow: var(--shadow); max-height: 320px; overflow-y: auto;
}
.suggestions li a {
  display: block; padding: 8px 10px; border-radius: 0;
  color: var(--ink); font-size: .9rem;
}
.suggestions li a:hover { background: var(--accent-sf); text-decoration: none; }

.nav { font-size: .9rem; }

/* -- hero -- */

.hero { padding: 44px 0 28px; border-bottom: 1px solid var(--line); }
.hero h1 { margin: 0 0 12px; font-size: 2rem; letter-spacing: -.02em; }
.lede { margin: 0 0 14px; max-width: 62ch; color: var(--ink-soft); font-size: 1.05rem; }
.meta { margin: 0; font-size: .875rem; color: var(--ink-faint); }

/* -- screens -- */

.screens {
  display: grid; gap: 22px; padding: 28px 0;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}
.screen {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 0; box-shadow: var(--shadow); overflow: hidden;
}
.screen-head { padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
.screen-head h2 { margin: 0; font-size: 1.05rem; letter-spacing: -.01em; }
/* foldNotes appends an info dot INSIDE the heading, so by default it sits hard
   against the last word — on a narrow panel that reads as punctuation. Flexing
   the heading and pushing the dot right puts it in the same place on every
   panel, which is also where the spotlight's refresh control already sits. */
.screen-head h2 { display: flex; align-items: center; gap: 8px; }
.screen-head h2 .info-dot { margin-left: auto; flex: none; }
.panel-note {
  margin: 8px 0 0; font-size: .8rem; line-height: 1.5; color: var(--ink-faint);
}
/* Column key: the metric number is not a price, and without a label a reader
   will assume it is one. Names the right-hand column at the top of every list. */
.col-key {
  display: flex; justify-content: space-between; gap: 10px; margin: 10px 0 0;
  font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint);
}
.col-key-metric { font-weight: 600; }

.rows { margin: 0; padding: 6px; list-style: none; }
.row {
  display: grid; align-items: baseline; gap: 10px;
  grid-template-columns: 26px 62px 1fr auto;
  padding: 7px 12px; border-radius: 0; font-size: .9rem;
}
.row:hover { background: var(--bg); }
.rank { color: var(--ink-faint); font-size: .8rem; font-variant-numeric: tabular-nums; }
.tk { font-weight: 600; }
.co { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.metric { font-variant-numeric: tabular-nums; font-weight: 600; }
.regime {
  grid-column: 2 / -1; font-size: .75rem; color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.screen-more { margin: 2px 12px 12px; }
.screen-foot {
  margin: 0; padding: 10px 18px; border-top: 1px solid var(--line);
  font-size: .78rem; color: var(--ink-faint); background: var(--bg);
}

.pending { padding: 0 0 36px; color: var(--ink-soft); font-size: .9rem; }
.pending ul { padding-left: 18px; }
.empty { padding: 40px 0; }
.empty pre {
  display: inline-block; padding: 10px 14px; border-radius: 0;
  background: var(--surface); border: 1px solid var(--line);
}

/* -- ticker page -- */

.ticker { padding: 32px 0 48px; }
/* Logo, symbol, identity box, price — one row, vertically centred. */
.tk-head {
  display: flex; align-items: center;
  gap: 16px; flex-wrap: wrap; padding-bottom: 18px;
}
.tk-head h1 { margin: 0; font-size: 2.2rem; letter-spacing: -.02em; }

/* Matches .spot-tk on the front page, by owner request: the symbol should look
   the same wherever it appears. That means the UI sans at 700, NOT the serif
   display face — which is why this has to override the
   `h1, h2, h3, .tk-head h1` family rule near the top of this file. */
.tk-symbol {
  font-family: var(--font-ui) !important;
  font-size: 2.86rem; font-weight: 700; letter-spacing: -.03em; line-height: 1;
}
.tk-idbox {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 18px; border-radius: 12px;
  border: 1px solid var(--line); background: var(--surface);
  font-size: 1.02rem; color: var(--ink-soft);
}
.tk-idbox .co-name { margin: 0; color: var(--ink); font-weight: 600; }
.tk-idbox .sep { color: var(--ink-faint); }
/* NO BOX. The owner asked for the identity in a rounded box "and then the
   price" — the price is a bare number beside it, and boxing it made the header
   read as two competing panels. */
.tk-pricebox { padding: 0; }
.tk-pricebox {
  display: inline-flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
}
.tk-pricebox .px-inline {
  font-size: 1.76rem; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* When the number is from, in small type under it. A live price and a
   day-old close look identical without this. */
.px-asof {
  flex-basis: 100%; margin-top: 1px;
  font-size: .68rem; color: var(--ink-faint); letter-spacing: .02em;
}
/* Direction only, sized well below the price: it is an annotation on the
   number, not a second number. Colour comes from the signed band, so up is the
   same green a positive return is everywhere else on the site. */
.px-arrow { font-size: .8rem; line-height: 1; cursor: default; }
@media (max-width: 640px) {
  .tk-symbol { font-size: 2.3rem; }
  .tk-idbox { padding: 8px 14px; font-size: .94rem; }
  .tk-pricebox .px-inline { font-size: 1.5rem; }
}
.co-name { margin: 4px 0 0; color: var(--ink-soft); }
.tk-price { text-align: right; }
.px { font-size: 1.9rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.px-meta { font-size: .8rem; color: var(--ink-faint); }
.provenance {
  margin: 0 0 20px; padding: 9px 13px; border-radius: 0;
  background: var(--accent-sf); color: var(--ink-soft); font-size: .85rem;
}
.warnbox {
  margin: 0 0 20px; padding: 12px 16px; border-radius: 0;
  border: 1px solid var(--line); background: var(--surface); font-size: .85rem;
}
.warnbox ul { margin: 6px 0 0; padding-left: 20px; color: var(--ink-soft); }

.tiles {
  display: grid; gap: 14px; margin-bottom: 24px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.tile {
  /* Deliberate exception to the square-corner rule: the four score boxes and
     the narrative bubbles are the page's soft, human-facing elements. */
  /* Trimmed vertically on 2026-08-12 so the four of them stack shorter and the
     chart beside can come back down with them. Horizontal padding is unchanged
     — the labels wrap at 18px and would start breaking words below it. */
  padding: 11px 18px; border-radius: 10px;
  border: 1px solid var(--line); box-shadow: var(--shadow); background: var(--surface);
}
.tile.band-high { background: var(--band-high-bg); }
.tile.band-mid  { background: var(--band-mid-bg); }
.tile.band-low  { background: var(--band-low-bg); }
.tile.band-vlow { background: var(--band-vlow-bg); }
.tile-value { font-size: 1.8rem; line-height: 1.15; font-weight: 650; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.tile-label { margin-top: 2px; font-size: .9rem; font-weight: 500; }
.tile-note { margin-top: 7px; font-size: .74rem; line-height: 1.45; color: var(--ink-faint); }

/* SIX columns, so a panel can be a third, a half or two thirds of the row.
   auto-fit with a min width could only ever produce EQUAL columns, which is why
   every panel was the same size and Price vs Earnings growth ran full width to
   hold two numbers. Default is a half; `span-third` and `span-twothirds` are
   the exceptions, declared per panel at the call site. */
.grid {
  display: grid; gap: 18px; margin-bottom: 18px;
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
.grid > .panel { grid-column: span 3; }
.grid > .panel.span-third { grid-column: span 2; }
.grid > .panel.span-twothirds { grid-column: span 4; }
.grid > .panel.span-full { grid-column: span 6; }

/* A third of the row is too narrow for a table below ~900px, so the grid drops
   to halves, and to a single column below 620px. */
@media (max-width: 900px) {
  .grid > .panel,
  .grid > .panel.span-third,
  .grid > .panel.span-twothirds { grid-column: span 3; }
}
@media (max-width: 620px) {
  .grid > .panel,
  .grid > .panel.span-third,
  .grid > .panel.span-twothirds { grid-column: span 6; }
}
.panel {
  padding: 18px 20px; border-radius: 0;
  border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow);
  margin-bottom: 18px;
}
.grid .panel { margin-bottom: 0; }
.panel h2 { margin: 0 0 12px; font-size: 1rem; letter-spacing: -.01em; }
.panel h3 { margin: 0 0 4px; font-size: .85rem; color: var(--ink-soft); }

.reasoning { margin: 0 0 12px; font-size: 1.02rem; line-height: 1.65; }
.statelines { margin: 0 0 10px; display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  padding: 3px 11px; border-radius: 0; font-size: .78rem;
  background: var(--accent-sf); color: var(--accent); font-weight: 500;
}

.kv { width: 100%; border-collapse: collapse; font-size: .9rem; }
.kv th {
  text-align: left; font-weight: 400; color: var(--ink-soft);
  padding: 6px 0; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.kv td {
  text-align: right; padding: 6px 0; border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums; font-weight: 500;
}
.kv.wide td, .kv.wide th { text-align: left; padding-right: 16px; }
.kv tr:last-child th, .kv tr:last-child td { border-bottom: 0; }

.audit { display: flex; gap: 28px; flex-wrap: wrap; margin-bottom: 10px; }
.audit-col p { margin: 0; font-variant-numeric: tabular-nums; }
.pos { color: var(--accent); }
.neg { color: var(--ink-faint); }
details summary { cursor: pointer; font-size: .85rem; color: var(--ink-soft); }
.reasons { margin: 10px 0 0; padding-left: 20px; font-size: .84rem; color: var(--ink-soft); }
.reasons li { margin-bottom: 5px; }

/* -- prose / about -- */

.prose { max-width: 70ch; padding: 36px 0 48px; }
.prose h1 { font-size: 2rem; letter-spacing: -.02em; margin: 0 0 14px; }
.prose h2 { font-size: 1.15rem; margin: 32px 0 10px; }
.prose ul { padding-left: 20px; color: var(--ink-soft); }
.prose li { margin-bottom: 7px; }
.notes dt { font-weight: 600; margin-top: 14px; font-size: .95rem; }
.notes dd { margin: 4px 0 0; color: var(--ink-soft); font-size: .9rem; }
.disclaimer-block {
  padding: 14px 16px; border-radius: 0; border: 1px solid var(--line);
  background: var(--surface); font-size: .88rem; color: var(--ink-soft);
}

/* -- error -- */

.errorpage { padding: 80px 0; text-align: center; }
.errorpage .code { margin: 0; font-size: 3.6rem; font-weight: 700; color: var(--ink-faint); }
.errorpage h1 { margin: 0 0 10px; font-size: 1.5rem; }
.errorpage .message { color: var(--ink-soft); max-width: 52ch; margin: 0 auto 22px; }
.btn {
  display: inline-block; padding: 10px 20px; border-radius: 0;
  background: var(--accent); color: #fff; font-size: .9rem;
}
.btn:hover { text-decoration: none; opacity: .92; }

/* -- footer -- */

.footer {
  border-top: 1px solid var(--line); background: var(--surface);
  padding: 26px 0 34px; margin-top: 30px;
}
.disclaimer {
  margin: 0 0 12px; font-size: .82rem; line-height: 1.6;
  color: var(--ink-soft); max-width: 88ch;
}
.colophon { margin: 0; font-size: .8rem; color: var(--ink-faint); }

@media (max-width: 620px) {
  .hero h1 { font-size: 1.6rem; }
  .tk-head h1 { font-size: 1.8rem; }
  .masthead-inner { gap: 12px; }
  .row { grid-template-columns: 24px 56px 1fr; }
  .row .metric { grid-column: 3; text-align: right; }
}

.muted { color: var(--ink-faint); font-weight: 400; font-size: .82rem; }

/* -- score caveats: flooring and inapplicable structural inputs -- */

.caveatbox {
  margin: 0 0 18px; padding: 14px 18px; border-radius: 0;
  border: 1px solid var(--accent); background: var(--accent-sf);
}
.caveatbox h3 { margin: 0 0 6px; font-size: .95rem; color: var(--ink); }
.caveatbox p { margin: 0 0 8px; font-size: .87rem; line-height: 1.6; color: var(--ink-soft); }
.caveatbox ul { margin: 0; padding-left: 20px; font-size: .85rem; color: var(--ink-soft); }
.caveatbox li { margin-bottom: 4px; }

.tile-caveat { border-style: dashed; }
.floor-tag {
  display: inline-block; vertical-align: middle; margin-left: 7px;
  padding: 2px 8px; border-radius: 0;
  background: var(--accent); color: #fff;
  font-size: .62rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
}
.tile-raw {
  margin-top: 6px; font-size: .74rem; line-height: 1.4;
  color: var(--ink-soft); font-variant-numeric: tabular-nums;
}

/* ================= ticker page v2 (WEBSITE_DESIGN.md) ================= */

.tk-meta { margin: 6px 0 0; color: var(--ink-soft); font-size: .95rem; }
.tk-meta .sep { margin: 0 8px; color: var(--ink-faint); }
.tk-meta .co-name { color: var(--ink); font-weight: 500; }
.tk-meta .px-inline { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }

/* scores + chart side by side */
.score-row {
  display: grid; gap: 18px; margin-bottom: 0;
  grid-template-columns: minmax(300px, 1.05fr) minmax(280px, 1fr);
  align-items: start;
}
.score-col { display: flex; flex-direction: column; gap: 14px; }
.score-row .tiles {
  display: grid; gap: 12px; margin: 0;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* The bubbles finish the left column, so the chart opposite can run the full
   height of both. */
.score-col .bubbles { margin: 0; }
/* ⚠️ DO NOT make the chart body flex-grow. The SVG carries a viewBox and its
   own aspect ratio, so stretching the CONTAINER does not stretch the chart —
   it just opens a gap between the plot and the caption underneath, which is
   exactly what the first attempt at "a bit taller" produced. Height comes from
   the SVG itself (chart.HEIGHT); the box sizes to its content. */
.score-row .chartbox { display: flex; flex-direction: column; }
.pct { font-size: 1.1rem; font-weight: 500; margin-left: 1px; }

.chartbox {
  padding: 14px 16px; border-radius: 0;
  border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow);
}
.spark { width: 100%; height: auto; display: block; color: var(--accent); }
.spark-line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
.spark-area { fill: currentColor; opacity: .10; stroke: none; }
.spark-dot { fill: currentColor; }
.chart-cap { margin: 8px 0 0; font-size: .78rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.chart-empty { padding: 60px 0; text-align: center; color: var(--ink-faint); font-size: .85rem; }

.trendnote { margin: 0 0 18px; font-size: .8rem; color: var(--ink-faint); }

/* narrative bubbles: coloured by STATE TYPE, never by good/bad */
.bubbles { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 6px; }
.bubble {
  padding: 6px 14px; border-radius: 999px; cursor: pointer;
  font-size: .84rem; font-weight: 500; font-family: inherit;
  border: 1px solid transparent; transition: transform .08s ease;
}
.bubble:hover, .bubble:focus { transform: translateY(-1px); outline: none; }
/* `is-active` is set by the shared info-panel handler in base.html and removed
   the moment another trigger opens, so only ever ONE bubble is outlined —
   whether it was reached by pointer or by click. */
.bubble.is-active { box-shadow: 0 0 0 2px var(--accent); }

.bub-structure     { background: #e7e2d8; color: #4a4034; }
.bub-trend         { background: #dbe4e8; color: #2f4550; }
.bub-extension     { background: #efe0d2; color: #6b4a28; }
.bub-repair        { background: #dfe6dc; color: #3a4a36; }
.bub-participation { background: #e4dfe9; color: #453c52; }
.bub-volatility    { background: #eae2d4; color: #57492f; }
.bub-relative      { background: #dee5e2; color: #33473f; }

/* Same two-way pairing as the bands above — see the warning there. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  .bub-structure     { background: #302a22; color: #ddd2c2; }
  .bub-trend         { background: #22303a; color: #c4d8e2; }
  .bub-extension     { background: #3a2c1c; color: #e8c9a4; }
  .bub-repair        { background: #26301f; color: #cbdcc2; }
  .bub-participation { background: #2e2735; color: #d6cae2; }
  .bub-volatility    { background: #332b1e; color: #e2d3b4; }
  .bub-relative      { background: #223029; color: #c2dbcd; }
  }
}

:root[data-theme="dark"] {
  .bub-structure     { background: #302a22; color: #ddd2c2; }
  .bub-trend         { background: #22303a; color: #c4d8e2; }
  .bub-extension     { background: #3a2c1c; color: #e8c9a4; }
  .bub-repair        { background: #26301f; color: #cbdcc2; }
  .bub-participation { background: #2e2735; color: #d6cae2; }
  .bub-volatility    { background: #332b1e; color: #e2d3b4; }
  .bub-relative      { background: #223029; color: #c2dbcd; }
}

.bubble-detail {
  margin: 4px 0 22px; padding: 12px 16px; border-radius: 0;
  border: 1px solid var(--line); background: var(--surface);
  font-size: .88rem; line-height: 1.6; color: var(--ink-soft);
}

/* pathway */
.triggers { margin: 0; padding: 0; list-style: none; }
.triggers li {
  display: grid; gap: 4px 14px; padding: 10px 0;
  border-bottom: 1px solid var(--line);
  grid-template-columns: 120px 1fr auto;
}
.triggers li:last-child { border-bottom: 0; }
.trigger-name { font-size: .76rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-faint); }
.trigger-what { font-weight: 500; }
.trigger-gap { font-variant-numeric: tabular-nums; font-weight: 600; }
.trigger-why { grid-column: 2 / -1; font-size: .82rem; color: var(--ink-soft); }

/* detailed scoring */
.signals { display: grid; gap: 22px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.signal-col h3 { margin: 0 0 8px; font-size: .85rem; color: var(--ink-soft); }

.pending-section { opacity: .72; border-style: dashed; }

/* paid-tier ready: each gateable section can be blurred independently */
.gateable .panel-body { position: relative; }
.gated .panel-body { filter: blur(5px); pointer-events: none; user-select: none; }

@media (max-width: 860px) {
  .score-row { grid-template-columns: 1fr; }
  .triggers li { grid-template-columns: 1fr auto; }
  .trigger-name { grid-column: 1 / -1; }
}

/* ============ DIRECTIONAL COLOUR SYSTEM (owner override 2026-08-02) ============
   Five bands, red -> amber -> green, depth by strength.
   Polarity is set per metric in presentation.py: chase risk and drawdown are
   INVERTED, so a high chase risk resolves to c-neg2 (red), not green. */

:root {
  --pos2-bg: #d9ead0; --pos2-fg: #24521f; --pos2-line: #4e9440;
  --pos1-bg: #e9f1e0; --pos1-fg: #3d6b33; --pos1-line: #79ad63;
  --mid-bg:  #f6efdd; --mid-fg:  #6d5a2a; --mid-line:  #c8a24a;
  --neg1-bg: #f7e6dd; --neg1-fg: #8a4a2a; --neg1-line: #cc7d52;
  --neg2-bg: #f5dad5; --neg2-fg: #8c2f26; --neg2-line: #c1483c;
}

/* ⚠️ THE DARK BANDS MUST BE REACHABLE BOTH WAYS. This block was media-query
   ONLY until 2026-08-11, so a reader on a light machine who pressed the theme
   toggle got the dark page with the LIGHT bands still applied: pale green
   bubbles carrying dark green text on a near-black card, and score tiles to
   match. Every other themed declaration in this file already pairs the query
   with a `[data-theme="dark"]` selector — this one was missed, and the bug is
   invisible to anyone whose OS is already dark. Keep the two lists in step.

   Dark values are deliberately DEEPER in the background and BRIGHTER in the
   foreground than a straight inversion of the light set: on a dark surface the
   tint has to sit further from the text to read as a filled bubble at all. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --pos2-bg: #162c19; --pos2-fg: #a9e09c; --pos2-line: #56a047;
    --pos1-bg: #16241a; --pos1-fg: #96c78a; --pos1-line: #6f9c5f;
    --mid-bg:  #2b2415; --mid-fg:  #e2c682; --mid-line:  #c8a24a;
    --neg1-bg: #2f2017; --neg1-fg: #e2a884; --neg1-line: #b8713f;
    --neg2-bg: #351a17; --neg2-fg: #eda398; --neg2-line: #c1483c;
  }
}

:root[data-theme="dark"] {
    --pos2-bg: #162c19; --pos2-fg: #a9e09c; --pos2-line: #56a047;
    --pos1-bg: #16241a; --pos1-fg: #96c78a; --pos1-line: #6f9c5f;
    --mid-bg:  #2b2415; --mid-fg:  #e2c682; --mid-line:  #c8a24a;
    --neg1-bg: #2f2017; --neg1-fg: #e2a884; --neg1-line: #b8713f;
    --neg2-bg: #351a17; --neg2-fg: #eda398; --neg2-line: #c1483c;
}

.c-pos2 { color: var(--pos2-fg); }
.c-pos1 { color: var(--pos1-fg); }
.c-mid  { color: var(--mid-fg); }
.c-neg1 { color: var(--neg1-fg); }
.c-neg2 { color: var(--neg2-fg); }
td.c-pos2, td.c-pos1, td.c-mid, td.c-neg1, td.c-neg2 { font-weight: 650; }

/* score tiles take the band as a background + left rule */
.tile.c-pos2 { background: var(--pos2-bg); border-left: 4px solid var(--pos2-line); }
.tile.c-pos1 { background: var(--pos1-bg); border-left: 4px solid var(--pos1-line); }
.tile.c-mid  { background: var(--mid-bg);  border-left: 4px solid var(--mid-line); }
.tile.c-neg1 { background: var(--neg1-bg); border-left: 4px solid var(--neg1-line); }
.tile.c-neg2 { background: var(--neg2-bg); border-left: 4px solid var(--neg2-line); }
.tile.c-pos2 .tile-value { color: var(--pos2-fg); }
.tile.c-pos1 .tile-value { color: var(--pos1-fg); }
.tile.c-mid  .tile-value { color: var(--mid-fg); }
.tile.c-neg1 .tile-value { color: var(--neg1-fg); }
.tile.c-neg2 .tile-value { color: var(--neg2-fg); }

/* bubbles: directional */
.bub-pos { background: var(--pos2-bg); color: var(--pos2-fg); }
.bub-neg { background: var(--neg2-bg); color: var(--neg2-fg); }
.bub-mid { background: var(--mid-bg);  color: var(--mid-fg); }

/* info circle */
.tile-label { display: flex; align-items: center; gap: 6px; }
.info-dot {
  width: 16px; height: 16px; flex: 0 0 16px; padding: 0;
  border-radius: 50%; border: 1px solid currentColor;
  background: transparent; color: inherit; opacity: .55;
  font: 600 10px/14px ui-sans-serif, sans-serif; cursor: pointer;
}
.info-dot:hover, .info-dot:focus { opacity: 1; outline: none; }
.info-panel {
  position: absolute; z-index: 60; max-width: 320px;
  padding: 12px 14px; border-radius: 0;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow); font-size: .84rem; line-height: 1.55;
}
.info-panel strong { display: block; margin-bottom: 4px; color: var(--ink); }
.info-panel span { color: var(--ink-soft); }

/* chart controls */
.chart-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px; flex-wrap: wrap;
}
.chart-interval {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-faint);
}
.chart-ranges { display: flex; gap: 4px; }
.range-btn {
  padding: 3px 9px; border-radius: 0; cursor: pointer;
  border: 1px solid var(--line); background: transparent;
  color: var(--ink-soft); font: 500 .74rem inherit;
}
.range-btn:hover { border-color: var(--accent); }
.range-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; }

.spark.dir-up   { color: var(--pos2-line); }
.spark.dir-down { color: var(--neg2-line); }

/* chart hover readout + crosshair */
.chartbox { position: relative; }
.spark-cross { stroke: currentColor; stroke-width: 1; opacity: .35; }
.spark-hover { fill: currentColor; }
.chart-readout {
  position: absolute; top: 44px; right: 18px; z-index: 5;
  padding: 6px 10px; border-radius: 0;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow); font-variant-numeric: tabular-nums;
  display: flex; flex-direction: column; align-items: flex-end; gap: 1px;
  pointer-events: none;
}
.chart-readout b { font-size: 1rem; color: var(--ink); }
.chart-readout span { font-size: .7rem; color: var(--ink-faint); }

/* price vs earnings detail */
.exp-headline { margin: 0 0 4px; font-size: 1.05rem; font-weight: 600; line-height: 1.5; }
.exp-conf { margin: 0 0 14px; font-size: .84rem; color: var(--ink-faint); }
.exp-conf span { font-weight: 600; }
.kvrow {
  display: grid; grid-template-columns: 96px 1fr; gap: 12px;
  padding: 8px 0; border-top: 1px solid var(--line); font-size: .88rem;
}
.kvrow-label { color: var(--ink-faint); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
.kvrow-vals { display: flex; flex-wrap: wrap; gap: 4px 18px; }
.kvpair { color: var(--ink-soft); }
.kvpair b { color: var(--ink); font-variant-numeric: tabular-nums; }
.takeaway {
  margin: 14px 0 0; padding: 11px 14px; border-radius: 0;
  background: var(--bg); border: 1px solid var(--line);
  font-size: .88rem; line-height: 1.6; color: var(--ink-soft);
}
.takeaway-label {
  display: inline-block; margin-right: 6px; font-size: .72rem;
  text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint);
}
.ichi td { text-align: left; }
.panel h2 .info-dot { vertical-align: middle; margin-left: 6px; }

/* battery-style strength gauge */
/* Rounded by owner request (2026-08-12). The site is square everywhere else
   (--radius: 0); these and the spotlight chips are the deliberate exceptions. */
.battery {
  display: inline-flex; gap: 2px; margin-left: 8px;
  vertical-align: middle; padding: 2px;
  border: 1px solid currentColor; border-radius: 5px; opacity: .85;
}
.battery .cell {
  width: 6px; height: 11px; border-radius: 2px;
  background: currentColor; opacity: .18;
}
.battery .cell.on { opacity: 1; }
.kv td .battery { float: right; margin-left: 10px; }
.warn-note { color: var(--neg1-fg); }

/* relative rotation graph */
.rrg-wrap { display: grid; gap: 20px; grid-template-columns: minmax(260px, 380px) 1fr; align-items: start; }
.rrg { width: 100%; height: auto; display: block; }
.rrg rect { opacity: .16; }
.q-leading   { fill: var(--pos2-line); }
.q-improving { fill: var(--pos1-line); }
.q-weakening { fill: var(--neg1-line); }
.q-lagging   { fill: var(--neg2-line); }
.rrg-axis { stroke: var(--ink-faint); stroke-width: 1; opacity: .5; }
.rrg-quad { font-size: 11px; fill: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; }
.rrg-axis-label { font-size: 10px; fill: var(--ink-faint); }
.rrg-label { font-size: 11px; font-weight: 600; }
.rrg-tail { stroke-width: 2; opacity: .55; fill: none; }
.rrg-dot.leg-a, .rrg-tail.leg-a, .rrg-label.leg-a { stroke: var(--accent); fill: var(--accent); }
.rrg-dot.leg-b, .rrg-tail.leg-b, .rrg-label.leg-b { stroke: var(--pos2-line); fill: var(--pos2-line); }
.rrg-dot.leg-c, .rrg-tail.leg-c, .rrg-label.leg-c { stroke: var(--ink-faint); fill: var(--ink-faint); }
.rrg-tail.leg-a, .rrg-tail.leg-b, .rrg-tail.leg-c { fill: none; }
.rrg-phase { margin: 0 0 6px; font-size: 1.05rem; font-weight: 650; }
.rrg-summary { margin: 0 0 14px; font-size: .88rem; color: var(--ink-soft); }
.rrg-legs th { font-size: .74rem; text-transform: uppercase; letter-spacing: .04em; }
.rrg-legs td { text-align: left; font-variant-numeric: tabular-nums; }
.kvpair .battery { margin-left: 5px; }
@media (max-width: 800px) { .rrg-wrap { grid-template-columns: 1fr; } }

/* price-vs-earnings sub-tables and options */
h3.sub {
  margin: 18px 0 6px; font-size: .74rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-faint); font-weight: 600;
}
h3.sub:first-of-type { margin-top: 10px; }
.revisions { margin: 0; font-size: .9rem; color: var(--ink-soft); }
.opt-flag { margin: 0 0 6px; font-size: 1.02rem; font-weight: 650; }
.opt-summary { margin: 0 0 14px; font-size: .88rem; color: var(--ink-soft); }

/* news headlines */
.news-list { margin: 0; padding: 0; list-style: none; }
.news-item {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.news-item:last-child { border-bottom: 0; }
.news-title { font-size: .95rem; line-height: 1.45; color: var(--ink); font-weight: 500; }
.news-title:hover { color: var(--accent); }
.news-meta { font-size: .76rem; color: var(--ink-faint); }
.news-loading, .news-empty {
  padding: 14px 0; color: var(--ink-faint); font-size: .88rem; list-style: none;
}

.news-more {
  margin-top: 12px; padding: 7px 14px; border-radius: 0; cursor: pointer;
  border: 1px solid var(--line); background: transparent;
  color: var(--accent); font: 500 .84rem inherit;
}
.news-more:hover { border-color: var(--accent); background: var(--accent-sf); }

/* `hidden` must beat any author display rule.
   .news-item sets display:flex, and an author display declaration overrides the
   UA stylesheet's [hidden]{display:none} — so items carrying the hidden
   attribute stayed on screen. Applies to every hideable element, not just news. */
[hidden] { display: none !important; }

/* ---------------- front page: spotlight, movers, macro ---------------- */

/* Two columns, not the old auto-fit track: the spotlight is the one panel with
   a chart, four figures and its highlight chips to place, and in an equal
   three-up row it had to stack all of that into 290px. It takes the wide column
   and the full height; movers and macro share the narrow one. Below 860px
   everything falls back to a single column in source order. */
/* Two columns on the top row — spotlight wide, Macro Health narrow — and the
   Position Health pair spanning the FULL width beneath them.
   Macro spanning both rows was the first attempt and it simply moved the dead
   space: the macro card is ~370px against the spotlight's ~373, so a two-row
   span left the same emptiness under it that the old layout left under the
   spotlight. Row heights now match and nothing is stretched to hide a gap.
   Below 860px it is one column in source order: spotlight, pair, macro. */
.front-grid {
  display: grid; gap: 18px; margin: 0 0 28px;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  align-items: start;
}
.front-grid .spotlight   { grid-column: 1; grid-row: 1; }
.front-grid .macro       { grid-column: 2; grid-row: 1; }
.front-grid .front-band  { grid-column: 1 / -1; grid-row: 2; }

/* The promoted band: top scorers plus the two Position Health panels, side by
   side across the full width. auto-fit rather than a fixed three-column track,
   so the band still reads correctly if a panel has no rows and is omitted. */
.front-band {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.front-band .screen { margin: 0; }

@media (max-width: 860px) {
  .front-grid { grid-template-columns: minmax(0, 1fr); }
  .front-grid .spotlight,
  .front-grid .front-band,
  .front-grid .macro { grid-column: auto; grid-row: auto; }
}

/* Promoted screens read as cards rather than as list sections: they sit beside
   the spotlight and the macro panel, and an unbordered list next to two bordered
   cards looks like a rendering failure. */
.screen-prominent {
  padding: 18px 20px;
  border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow);
}
.screen-prominent h2 { font-size: 1rem; }

/* Big movers is a screens-grid cell, so it needs the padding the .screen-head /
   .rows structure gives every other panel — its body is a bespoke two-column
   list rather than the standard row list. */
.movers .movers-cols { padding: 14px 18px 4px; }
.movers .panel-note { padding: 0 18px 14px; margin: 0; }
.card {
  padding: 18px 20px; border-radius: 0;
  border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow);
}
.card h2 { margin: 0 0 12px; font-size: 1rem; letter-spacing: -.01em; }

/* Refresh sits at the top right of the card, so the heading has to make room. */
.card h2 { display: flex; align-items: center; gap: 8px; }
.spot-refresh {
  margin-left: auto; width: 26px; height: 26px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: transparent; cursor: pointer;
  color: var(--ink-soft); font-size: 1rem; line-height: 1;
}
.spot-refresh:hover { border-color: var(--accent); color: var(--accent); }
.spot-refresh:disabled { opacity: .4; cursor: default; }
.spotlight.is-loading { opacity: .55; transition: opacity .1s ease; }

/* Identity beside the chart while there is room for both. minmax(0,…) on the
   chart track matters: an SVG in a grid cell refuses to shrink below its
   intrinsic width otherwise, and the card overflows instead of the chart
   scaling. */
.spot-main { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 22px; align-items: start; }
@media (max-width: 620px) { .spot-main { grid-template-columns: minmax(0, 1fr); gap: 10px; } }

.spot-chart { margin: 4px 0 2px; color: var(--ink-soft); }
.spot-chart svg { display: block; width: 100%; height: auto; }
.spot-cap {
  margin: 2px 0 0; font-size: .72rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.spot-tk-row { display: flex; align-items: center; gap: 10px; }
.spot-tk { font-size: 2.1rem; font-weight: 700; letter-spacing: -.02em; }
/* Logos arrive as square PNGs on a white field, which reads as a bright patch
   on the dark theme — the subtle surface tint and radius stop it looking like a
   hole punched in the card. `contain` because the source images are not all the
   same aspect. */
.spot-logo, .tk-logo {
  flex: none; border-radius: 6px; object-fit: contain;
  background: #fff; padding: 2px;
}
.spot-logo { width: 34px; height: 34px; }
.tk-logo { width: 52px; height: 52px; }
/* Inside .tk-ident, NOT a direct child of .tk-head: that header is
   `justify-content: space-between` with the price block on the right, and a
   third child would have been spaced out into the middle of the row. */
.tk-tk-row { display: flex; align-items: center; gap: 12px; }
.spot-co { margin: 2px 0 8px; color: var(--ink-soft); font-size: .88rem; }
.spot-sector {
  display: block; font-size: .76rem; color: var(--ink-faint); margin-top: 2px;
}
/* Sized up to hold the left of the card now that all three bubbles sit right.
   The change keeps a smaller size than the ticker itself: the symbol is the
   card's subject and must stay the largest thing on it. */
.spot-nums { display: flex; align-items: baseline; gap: 14px; margin-top: 4px; }
.spot-nums .px-asof { flex-basis: auto; margin: 0; }
.spot-px { font-size: 1.85rem; font-weight: 650; font-variant-numeric: tabular-nums;
           letter-spacing: -.015em; }
.spot-nums > span:not(.spot-px) { font-size: 1.15rem; font-weight: 600;
           font-variant-numeric: tabular-nums; }
/* The state bubble carries no evidence line, so it centres its single label
   against the two-line chips beside it and keeps the row's baseline even.
   Colour comes from the state's own .bub-* polarity class, NOT from this rule —
   a state is not green just because the card is. See the note in serve.py. */
.spot-chip.is-state { justify-content: center; cursor: default; }
.spot-chip.is-state .chip-label { font-weight: 650; }

/* Highlight chips: label on top, the figure that fired the rule underneath, so
   the chip is checkable rather than an assertion. Colours are the shared
   .bub-* palette, which is how the ticker page's state bubbles already read. */
/* All three bubbles on one left-aligned row spanning the card. See the note in
   _spotlight.html for why this replaced two right-aligned arrangements. */
.spot-states {
  display: flex; flex-wrap: wrap; align-items: stretch;
  gap: 8px; margin: 18px 0 2px;
}
/* Pill-shaped, unlike every other surface on the site — the owner asked for
   rounded corners on these three specifically, so the radius is set here rather
   than by touching --radius, which would round the whole publication. */
.spot-chip {
  display: flex; flex-direction: column; gap: 1px; text-align: left;
  padding: 8px 16px; border: 0; border-radius: 14px; cursor: pointer;
  font: inherit; line-height: 1.25;
}
.spot-chip .chip-label { font-size: .84rem; font-weight: 600; letter-spacing: -.01em; }
.spot-chip .chip-evidence { font-size: .72rem; opacity: .78; font-variant-numeric: tabular-nums; }
.spot-chip:hover, .spot-chip:focus { outline: none; box-shadow: 0 0 0 2px var(--accent); }

/* Four figures across the wide card, instead of the old two-column table that
   left half the panel empty. */
.spot-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 12px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}
.spot-stat { display: flex; flex-direction: column; gap: 2px; }
.spot-stat .stat-value {
  font-size: 1.25rem; font-weight: 650; font-variant-numeric: tabular-nums;
}
.spot-stat .stat-label { font-size: .74rem; color: var(--ink-faint); }

.movers-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.mover-list { margin: 0; padding: 0; list-style: none; }
.mover-list li {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 5px 0; font-size: .88rem; font-variant-numeric: tabular-nums;
}
.mover-list a { font-weight: 600; }

.macro-phase { margin: 0 0 10px; font-size: 1.3rem; font-weight: 650; letter-spacing: -.02em; }
.macro-gauge { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.battery.big { padding: 3px; }
.battery.big .cell { width: 12px; height: 18px; border-radius: 3px; }
.battery.big { border-radius: 7px; }
.macro-word { font-weight: 600; font-size: .9rem; }
.macro-desc { margin: 0 0 12px; font-size: .88rem; color: var(--ink-soft); line-height: 1.55; }
.macro-warn { border-left: 3px solid var(--accent); padding-left: 10px; }
.btn-sm {
  display: inline-block; margin-top: 12px; padding: 7px 14px; border-radius: 0;
  background: var(--accent); color: #fff; font-size: .84rem; font-weight: 500;
}
.btn-sm:hover { text-decoration: none; opacity: .92; }

/* macro detail page */
.macro-page { padding: 32px 0 48px; }
.v2-score { font-size: .82rem; font-weight: 400; color: var(--ink-faint); margin-left: 8px; }
.v2-table td { text-align: left; vertical-align: top; }
.v2-table th { text-align: left; }
tr.v2-note td { padding-top: 0; padding-bottom: 10px; border-bottom: 1px solid var(--line); font-size: .8rem; line-height: 1.5; }
tr.v2-note em { font-style: normal; color: var(--ink); }
.macro-page .macro-phase { margin: 0 0 12px; }

/* macro phase history */
.hist-head { margin: 0 0 12px; font-size: 1.2rem; font-weight: 650; }
.hist-wrap { overflow-x: auto; margin-bottom: 10px; }
.macro-hist { width: 100%; min-width: 480px; height: auto; display: block; }
.hist-bull { fill: var(--pos2-line); opacity: .55; }
.hist-mid  { fill: var(--mid-line);  opacity: .45; }
.hist-bear { fill: var(--neg2-line); opacity: .6; }
.hist-zero { stroke: var(--ink-faint); stroke-width: 1; opacity: .4; stroke-dasharray: 3 3; }
.hist-line { fill: none; stroke: var(--ink); stroke-width: 1.4; opacity: .75; }
.hist-legend {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: center;
  font-size: .78rem; color: var(--ink-soft); margin-bottom: 14px;
}
.hist-legend .swatch {
  display: inline-block; width: 11px; height: 11px; border-radius: 0;
  margin-right: 5px; vertical-align: -1px;
}
.swatch.hist-bull { background: var(--pos2-line); }
.swatch.hist-mid  { background: var(--mid-line); }
.swatch.hist-bear { background: var(--neg2-line); }

/* ---------------- evidence citations ---------------- */
/* The marker is a link, not a tooltip: the finding it points at is often a
   REJECTION, which is too important to hide behind a hover. */
.cite {
  margin-left: 6px; font-size: .72rem; font-weight: 600; vertical-align: super;
  color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cite:hover { text-decoration: underline; }
.score-cite {
  grid-column: 1 / -1; margin: 2px 0 0;
  font-size: .78rem; color: var(--ink-faint);
}

.evidence { margin-top: 8px; }
.evidence-list { margin: 0; padding: 0; list-style: none; counter-reset: none; }
.evidence-item {
  display: grid; grid-template-columns: 26px 1fr; gap: 10px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.evidence-item:last-child { border-bottom: 0; }
.evidence-item:target { background: var(--accent-sf); }
.ev-num {
  font-size: .78rem; font-weight: 700; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.ev-claim { margin: 0; font-size: .9rem; font-weight: 550; line-height: 1.45; }
.ev-finding { margin: 5px 0 0; font-size: .85rem; line-height: 1.55; color: var(--ink-soft); }
.ev-source { margin: 5px 0 0; font-size: .74rem; color: var(--ink-faint); }
.ev-verdict {
  display: inline-block; margin-right: 7px; padding: 1px 7px;
  font-size: .68rem; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; border: 1px solid currentColor;
}
.ev-supported   { color: var(--pos1-fg); }
.ev-rejected    { color: var(--neg2-fg); }
.ev-descriptive { color: var(--mid-fg); }
.ev-untested    { color: var(--ink-faint); }

/* ---------------- browse page ---------------- */
.browse-hero { padding-bottom: 20px; }
.nav a + a { margin-left: 16px; }

.browse-controls {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px;
  padding: 18px; margin: 20px 0 12px;
  background: var(--surface); border: 1px solid var(--line);
}
.ctrl { display: flex; flex-direction: column; gap: 5px; }
.ctrl label {
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint);
}
.ctrl input[type="text"], .ctrl select {
  padding: 7px 10px; font: inherit; font-size: .9rem;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
}
.ctrl input[type="range"] { width: 150px; accent-color: var(--accent); }
.ctrl output {
  font-size: .78rem; color: var(--ink-soft); font-variant-numeric: tabular-nums;
}
.btn-sm.ghost {
  background: transparent; border: 1px solid var(--line); color: var(--ink-soft);
  padding: 7px 14px; font-size: .84rem; cursor: pointer;
}
.btn-sm.ghost:hover { border-color: var(--accent); color: var(--accent); }
.browse-count { margin: 0 0 10px; font-size: .82rem; color: var(--ink-faint); }

/* Wide tables scroll inside their own box; the page body never scrolls sideways. */
.table-scroll { overflow-x: auto; border: 1px solid var(--line); background: var(--surface); }
.browse-table { border-collapse: collapse; width: 100%; font-size: .87rem; }
.browse-table th, .browse-table td { padding: 7px 12px; text-align: left; white-space: nowrap; }
.browse-table thead th {
  position: sticky; top: 0; z-index: 5;
  background: var(--bg); border-bottom: 1px solid var(--line);
  font-size: .72rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; cursor: pointer; user-select: none;
}
.browse-table thead th:hover { color: var(--accent); }
.browse-table thead th.sorted-asc span::after  { content: " \2191"; }
.browse-table thead th.sorted-desc span::after { content: " \2193"; }
.browse-table tbody tr { border-bottom: 1px solid var(--line); }
.browse-table tbody tr:last-child { border-bottom: 0; }
.browse-table tbody tr:hover { background: var(--bg); }
.browse-table td.num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
/* Header must adopt the alignment of the column it names, or every numeric
   heading floats left of a right-aligned column. */
.browse-table th.num { text-align: right; }
.browse-table td.c-tk a { font-weight: 700; }
.browse-table td.c-name, .browse-table td.c-regime {
  max-width: 230px; overflow: hidden; text-overflow: ellipsis;
  color: var(--ink-soft); font-weight: 400;
}
.browse-table td.c-regime { font-size: .78rem; color: var(--ink-faint); }
.browse-foot { margin: 14px 0 40px; max-width: 78ch; }

@media (max-width: 700px) {
  .browse-table td.c-name, .browse-table th:nth-child(2) { display: none; }
}

/* State read-out under a states-only panel: prose the engine wrote, with its
   scalar read-out stripped (see presentation._clean_interpretation). */
.state-read {
  margin: 10px 0 0; padding: 9px 12px;
  background: var(--bg); border-left: 3px solid var(--line);
  font-size: .85rem; line-height: 1.5; color: var(--ink-soft);
}

/* ---------------- earnings panel ---------------- */
.earnings-panel { grid-column: 1 / -1; }
.next-earnings {
  margin: 0 0 12px; padding: 9px 12px; background: var(--accent-sf);
  font-size: .9rem; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.ne-label {
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-soft);
}
.earnings-chart { margin: 4px 0 0; }
.earnings-chart svg { display: block; width: 100%; }
/* Revenue and net income share the money scale; EPS is a line on its own.
   Filed quarters solid, derived fourth quarters lighter — the difference in
   provenance has to be visible in the chart, not only in the caption. */
/* Two SERIES, not a strong one and a weak one: they are separated by HUE at
   equal weight. Opacity is reserved for the within-series distinction (a
   derived Q4), so the two meanings never compete for the same visual channel. */
.bar-rev { fill: var(--series-a); opacity: .9; }
.bar-inc { fill: var(--series-b); opacity: .9; }
/* EPS became a bar on 2026-08-12, so it takes a fill like the other two. Ink
   rather than a third hue: it is on a DIFFERENT scale from the money bars, and
   giving it an equal-weight colour would invite comparing its height with
   theirs. */
.bar-eps { fill: var(--ink); opacity: .55; }
.bar-rev.bar-derived, .bar-inc.bar-derived, .bar-eps.bar-derived { opacity: .3; }
.axis-zero { stroke: var(--line); stroke-width: 1; }
.bar-label { fill: var(--ink-faint); font-size: 8.5px; font-family: inherit; }

.earnings-key {
  display: flex; flex-wrap: wrap; gap: 14px; margin: 6px 0 0;
  font-size: .74rem; color: var(--ink-soft);
}
.earnings-key .k { display: inline-flex; align-items: center; gap: 5px; }
.sw { display: inline-block; width: 9px; height: 9px; }
.sw-rev { background: var(--series-a); opacity: .9; }
.sw-inc { background: var(--series-b); opacity: .9; }
.sw-derived { background: var(--series-a); opacity: .42; }
.sw-eps { background: var(--ink); opacity: .55; }
.earnings-table { font-size: .85rem; }
.earnings-table td.muted, .earnings-table .muted { color: var(--ink-faint); font-weight: 400; }

/* ---------------- share count + sector earnings ---------------- */
.share-chart { margin: 0 0 12px; }
.share-chart svg { display: block; width: 100%; }
.share-path { fill: none; stroke: var(--series-b); stroke-width: 1.6; }
.share-dot { fill: var(--series-b); }
/* Return overlay: its own band and zero line under the share line, so the two
   never share a vertical scale. Stems for the same reason as the earnings
   panel — these are readings at discrete filings, not a continuous path. */
.sc-stem { stroke: var(--ink-faint); stroke-width: 1.1; opacity: .5; }
.sc-up { fill: var(--pos1-fg); }
.sc-down { fill: var(--neg1-fg); }
.sw-shares { width: 12px; height: 2px; background: var(--series-b); }
.sw-ret-up { width: 9px; height: 9px; border-radius: 50%; background: var(--pos1-fg); }
.sw-ret-down { width: 9px; height: 9px; border-radius: 50%; background: var(--neg1-fg); }

.sector-head { margin-bottom: 14px; }
.sector-table td.c-tk { font-weight: 650; }
.spark-cell { padding-right: 14px; }
.sector-spark { display: block; }
.spark-path { fill: none; stroke: var(--accent); stroke-width: 1.4; }
.spark-zero { stroke: var(--line); stroke-width: 1; }
.lowbase {
  display: inline-block; margin-left: 4px; padding: 0 5px;
  border: 1px solid currentColor; font-size: .62rem; letter-spacing: .04em;
  text-transform: uppercase; vertical-align: middle;
}

/* ---------------- earnings response ---------------- */
.er-chart { margin: 12px 0 6px; }
.er-chart svg { display: block; width: 100%; }
.er-up { fill: var(--pos1-fg); opacity: .85; }
.er-down { fill: var(--neg1-fg); opacity: .85; }
.er-table { font-size: .85rem; }

/* Earnings response: full width, revenue bars + price line on separate scales. */
.er-panel { grid-column: 1 / -1; }
.er-rev-up { fill: var(--series-a); opacity: .55; }
.er-rev-down { fill: var(--series-a); opacity: .22; }
/* Stems, not a line: the events are discrete and irregularly spaced, so a
   connecting segment would describe a path the price never took. */
.er-stem { stroke: var(--series-b); stroke-width: 1.4; opacity: .55; }
.er-dot { fill: var(--series-b); }
.sw-rev-up { background: var(--series-a); opacity: .55; }
.sw-rev-down { background: var(--series-a); opacity: .22; }
.sw-move { width: 9px; height: 9px; border-radius: 50%; background: var(--series-b); }

/* ---------------- chart tools + enlarge ---------------- */
.chart-figure { margin: 0 0 12px; }
.chart-tools {
  display: flex; align-items: center; gap: 7px; margin: 0 0 4px;
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint);
}
.chart-tools-label { margin-right: auto; }
.chart-expand {
  width: 22px; height: 22px; flex: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: transparent;
  color: var(--ink-soft); font-size: .8rem; line-height: 1;
}
.chart-expand:hover { border-color: var(--accent); color: var(--accent); }

.chart-modal {
  position: fixed; inset: 0; z-index: 60; padding: 4vh 4vw;
  background: rgba(20, 18, 15, .62);
  display: flex; align-items: center; justify-content: center;
}
.chart-modal-inner {
  width: min(1100px, 100%); max-height: 92vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow); padding: 18px 20px;
}
.chart-modal-head {
  display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
}
.chart-modal-head strong {
  margin-right: auto; font-family: var(--font-display); font-size: 1.05rem;
}
.chart-modal-close {
  width: 30px; height: 30px; flex: none; cursor: pointer;
  border: 1px solid var(--line); background: transparent;
  color: var(--ink-soft); font-size: 1.2rem; line-height: 1;
}
.chart-modal-close:hover { border-color: var(--accent); color: var(--accent); }
/* The enlarged copy gets real height; the inline one is deliberately compact. */
.chart-modal-body svg { display: block; width: 100%; height: 46vh; }
.chart-modal-key { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 14px;
  font-size: .78rem; color: var(--ink-soft); }
.chart-modal-key .k { display: inline-flex; align-items: center; gap: 5px; }
/* The price chart's expand control lives inside the existing range row. */
.chart-ranges .chart-expand { margin-left: 6px; }
.er-more { margin: 10px 0 0; }


/* Insider filings table: a compact ledger under the totals. */
.insider-filings { margin-top: 14px; font-size: .84rem; }
.insider-filings th { font-weight: 600; color: var(--ink-faint); font-size: .74rem;
  text-transform: uppercase; letter-spacing: .04em; }
.insider-filings .num { text-align: right; font-variant-numeric: tabular-nums; }
.filing-role { display: block; font-size: .72rem; color: var(--ink-faint); }


/* ---------------- score history chart ---------------- */
.score-history { width: 100%; height: auto; display: block; overflow: visible; }
.sh-grid { stroke: var(--line); stroke-width: 1; }
.sh-axis { fill: var(--ink-faint); font-size: 10px; font-family: var(--font-ui); }

/* ⚠️ THE SERIES CLASSES SET STROKE ONLY. They used to set `fill` as well, for
   the benefit of the dots — and because `.sh-bbs` is declared after `.sh-line`
   at equal specificity, that fill won on the POLYLINES too and painted each
   series as a filled shape. Three translucent slabs, which is what "the cloud"
   was. Lines get their fill killed here; dots get theirs from a two-class
   selector that outranks it. */
.sh-line {
  fill: none !important;
  stroke-width: 2; stroke-linejoin: round; stroke-linecap: round;
}
.sh-dot { stroke: none; }
.sh-line.sh-backfill { stroke-dasharray: 5 4; opacity: .85; }

/* The price strip. Ink-coloured and thin, deliberately not one of the series
   colours: it is a different quantity on a different scale, and colouring it
   like a score would invite reading it as one. */
.sh-price { fill: none; stroke: var(--ink); stroke-width: 1.2; stroke-linejoin: round; }
.sh-price-label { font-size: 9px; fill: var(--ink-faint); }

/* Owner's palette (2026-08-12): Brown Bear Score orange, Position Health
   green, Business Conviction blue. Deliberately not the score bands, which
   encode good/bad — a series colour must not imply a verdict on its metric. */
:root {
  --sh-bbs: #c2701c;
  --sh-phs: #4e8f4a;
  --sh-bcs: #3d7ea6;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --sh-bbs: #e2984a;
    --sh-phs: #7bbf74;
    --sh-bcs: #6cabd1;
  }
}
:root[data-theme="dark"] {
  --sh-bbs: #e2984a;
  --sh-phs: #7bbf74;
  --sh-bcs: #6cabd1;
}

.sh-bbs { stroke: var(--sh-bbs); }
.sh-phs { stroke: var(--sh-phs); }
.sh-bcs { stroke: var(--sh-bcs); }
.sh-dot.sh-bbs { fill: var(--sh-bbs); }
.sh-dot.sh-phs { fill: var(--sh-phs); }
.sh-dot.sh-bcs { fill: var(--sh-bcs); }

.chart-legend { display: flex; flex-wrap: wrap; gap: 18px; margin: 12px 0 0;
  font-size: .82rem; color: var(--ink-soft); }
.legend-item { display: inline-flex; align-items: center; gap: 8px; }
.legend-swatch { width: 26px; height: 5px; border-radius: 3px; display: inline-block; }
.legend-swatch.sh-bbs { background: var(--sh-bbs); }
.legend-swatch.sh-phs { background: var(--sh-phs); }
.legend-swatch.sh-bcs { background: var(--sh-bcs); }
.legend-swatch.sw-price { background: var(--ink); height: 2px; }



/* ---------------- ticker page: section grouping ---------------- */
/* A ticker page is ~12 screens with 18 panels. Before this the only way to
   reach the bottom half was to keep scrolling, and the panels interleaved
   subjects on the way. Four labelled groups, and a nav that stays put. */
/* Full-width sticky bar under the ticker header. `top` clears the masthead,
   which is itself sticky — the two stack rather than overlap. */
.ticker-nav {
  /* 66px is the masthead's measured height, so the two sticky bars stack
     exactly. At 64 the nav sat 2px under the masthead's edge. */
  position: sticky; top: 66px; z-index: 10;
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
  margin: 12px 0 4px; padding: 8px 0;
  background: var(--bg);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.ticker-nav a {
  padding: 6px 16px; font-size: .98rem; color: var(--ink-soft);
  white-space: nowrap;
  border: 1px solid transparent; border-radius: 999px;
}
.ticker-nav a:hover {
  text-decoration: none; color: var(--accent);
  border-color: var(--line); background: var(--surface);
}

.group-head {
  margin: 18px 0 14px; padding-bottom: 8px;
  border-bottom: 2px solid var(--ink); font-size: 1.35rem; letter-spacing: -.02em;
  /* Clears the sticky masthead (66px) AND the sticky section nav beneath it
     (57px), plus a little air. Measured: at 122px the heading landed at y=122
     with the nav ending at y=123 — one pixel under it. */
  scroll-margin-top: 132px;
}
.group-sub {
  display: block; margin-top: 3px;
  font-family: var(--font-ui); font-size: .82rem; font-weight: 400;
  letter-spacing: 0; color: var(--ink-faint);
}

/* The pointer that replaced the in-page evidence list. */
.method-pointer {
  margin: 28px 0 0; padding: 14px 16px;
  border: 1px solid var(--line); background: var(--surface);
  font-size: .88rem; color: var(--ink-soft);
}

/* Evidence register, now on /about. */
.register-group { margin: 22px 0 0; }
.register-group h3 {
  margin: 0 0 8px; font-size: 1rem; padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.register-item { margin: 0 0 14px; }
.register-item .ev-claim { margin: 0 0 4px; font-weight: 600; }
.register-item .ev-finding { margin: 0 0 4px; color: var(--ink-soft); font-size: .9rem; }
.register-item .ev-source { margin: 0; color: var(--ink-faint); font-size: .78rem; }

@media (max-width: 700px) {
  /* ⚠️ NOT sticky on narrow screens. The masthead wraps to 181px there and is
     itself sticky; a second bar under it would hold a quarter of a 812px
     viewport permanently. The nav still opens the page, it just scrolls away. */
  .ticker-nav { position: static; gap: 2px; padding: 6px 0; }
  .ticker-nav a { padding: 5px 10px; font-size: .84rem; }
  .group-head { scroll-margin-top: 190px; }
}


/* Back to the top, at the right of a group heading. Only on groups below the
   first — a link back to the top from the top is noise. */
.group-head { display: flex; align-items: baseline; flex-wrap: wrap; }
.group-head .group-sub { flex: 1 1 100%; order: 3; }
.to-top {
  margin-left: auto; padding: 3px 10px;
  font-family: var(--font-ui); font-size: .72rem; font-weight: 500;
  letter-spacing: .02em; color: var(--ink-faint);
  border: 1px solid var(--line); border-radius: 999px;
}
.to-top:hover { text-decoration: none; color: var(--accent); border-color: var(--accent); }
