/* ════════════════════════════════════════════════════════════════════════════
   SURFACE LANGUAGE  —  design v3.
   ────────────────────────────────────────────────────────────────────────────
   app.css carries the TOKENS; this carries the SHAPE they are arranged into.
   Splitting them is deliberate: the palette answers "what colour", this answers
   "what is a card, how far apart do cards sit, and what does a label look like",
   and the two change for different reasons.

   The design's architecture, in one paragraph: the page is a tinted GROUND, and
   everything on it is a white or near-white CARD with a hairline border, a soft
   long-throw shadow and generous padding. Sections do not touch. Every label is
   uppercase at .16em tracking in the quietest text tier, so the type does the ranking
   rather than size or weight alone. Numbers are tabular so columns align — an OpenType
   feature of the one family rather than a second, monospaced one. Nothing is full-bleed.

   That last point is the whole difference from what this replaces. The previous
   design was an unbroken hairline-divided sheet; this one is a stack of discrete
   objects. Applying the palette without applying this leaves the right colours
   in the wrong architecture, which is exactly what a token-only swap produced.

   Loaded AFTER app.css and reveal.css, BEFORE the page stylesheets, so a page
   can still override a shared rule.

   Every shared base selector below is wrapped in :where(), which carries ZERO
   specificity. That is load-bearing, not decoration: this file loads after
   app.css, so at equal specificity it would silently win every collision. The
   first draft did exactly that — a generic `.chip` stripped the bias chips of
   their bull and bear fills, because `.chip` and `.b-bullish` are both one
   class and the later one takes it. With :where(), anything that already had an
   opinion keeps it, and these rules only fill the gaps.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── The ground ────────────────────────────────────────────────────────────── */

html, body { background: var(--app-bg); }

/* The shell is no longer a bordered sheet holding the whole app; it is the
   ground the cards sit on. Padding is the design's own 48px, easing down on
   narrow viewports because 48px of gutter on a phone is most of the screen. */
/* 1600px of content inside 48px gutters is the design's own page: its frame is
   drawn at exactly 1600 and its outer padding at exactly 48. The 1560 this
   replaces was a guess made before the design source was in hand, and it is 40px
   short — enough that the dashboard's ten-currency rail could not fit ten
   currencies without overlapping itself. */
#app {
  max-width: 1696px;
  margin: 0 auto;
  padding: 0 clamp(14px, 3.4vw, 48px) 120px;
  background: transparent;
  border: 0;
  box-shadow: none;
  min-height: 100vh;
}

/* ── The header ────────────────────────────────────────────────────────────── */

/* A floating card rather than a rule across the page: it detaches from the
   ground on the same terms as everything else. The pinstripe overlay that used
   to sit behind it belongs to the sheet metaphor and is dropped. */
.topbar {
  position: sticky;
  top: clamp(8px, 1.4vw, 16px);
  z-index: 20;
  display: flex; align-items: center; gap: 18px;
  height: 56px;
  margin: clamp(8px, 1.4vw, 16px) 0 0;
  padding: 0 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-2);
}
.topbar::before { display: none; }          /* the sheet's pinstripe, retired */

.brand {
  font: 600 15px/1 var(--font-display);
  letter-spacing: .12em;
  color: var(--text);
}

/* ── The editorial masthead ───────────────────────────────────────────────────
   ONE place that lists every block carrying the dark band, because the first
   attempt did not have one: the rule was written per page, in four files, and two
   mastheads were simply missed — the per-currency detail head and the pair
   primer's own head, both of which look identical to a banded one on their
   siblings and so read as a half-applied theme.

   Editorial is the only palette that inverts the top of a page. In both modes the
   band is ink navy with a white headline, which is what makes the style read as a
   printed front page rather than a recoloured terminal. The other three palettes
   never match these selectors, so they are untouched.

   WHAT COUNTS AS A MASTHEAD. The block that opens a page or a page-level tab and
   carries its headline. Deliberately NOT the page-top intro CARDS — .wr-hero,
   .ftl-hero, .fj-head, .pb-hero, .drv-hero, .consensus-hero — which are bordered
   panels sitting on the ground with their own background. Those are cards, and a
   card painted navy reads as a stray dark box rather than a masthead. They follow
   the palette through the ordinary surface tokens like every other card.

   THE REBINDING is the mechanism. Painting the band alone would leave dark labels
   on a dark ground, so the band re-points the tokens its subtree reads at the hero
   variants; every descendant then inverts by inheritance instead of needing a rule
   of its own. This is also why the hero tokens have no :root defaults — a default
   of `--hero-text: var(--text)` becomes a reference cycle the moment this rule
   says `--text: var(--hero-text)`, and a cycle makes BOTH properties invalid
   rather than falling back to either. Palette-scoping is what removes the need
   for defaults at all.
   ──────────────────────────────────────────────────────────────────────────── */
:root[data-palette="editorial"] .cd-hero,
:root[data-palette="editorial"] .cd-dhead,
:root[data-palette="editorial"] .pd-hero,
:root[data-palette="editorial"] .pd-prhero,
:root[data-palette="editorial"] .pd-f2fhero,
:root[data-palette="editorial"] .md-masthead,
:root[data-palette="editorial"] .mb-masthead {
  background: var(--hero-bg);
  padding: var(--hero-pad);
  color: var(--hero-text);
  --text: var(--hero-text);
  --text-2: var(--hero-text-2);
  --text-muted: var(--hero-text-2);
  --text-faint: var(--hero-text-3);
  --colhead: var(--hero-text-3);
  /* EVERY surface and line token, not a chosen few. Two rounds of this went out with
     a subset: --surface-sunken was left behind, so the primer's "what the money earns"
     panel painted its near-white recessed colour straight onto the ink band, and
     --hairline-rgb was left behind, so every border drawn the generic way
     (rgba(var(--hairline-rgb), a)) kept its paper value and vanished on navy, taking
     the outline of the crowd-stands card with it. A band inverts a REGION; a token
     that describes a surface or a line and is not listed here is a hole in it. */
  --surface: var(--hero-panel);
  --surface-raised: var(--hero-panel);
  --surface-sunken: var(--hero-panel-2);
  --surface-row-active: var(--hero-panel-2);
  --surface-kpi: var(--hero-panel-2);
  --hairline-rgb: 30,41,59;
  --frame-border: var(--hero-line);
  --seg-empty: rgba(30,41,59,.55);
  --accent: var(--hero-accent);
  --bull-text: var(--hero-bull);
  --bear-text: var(--hero-bear);
}

/* The two desks run their band to the page edges; the Dashboard and the Brief do
   not, because the design draws those two as inset blocks with no bleed and no
   radius. Horizontal only — see below for why the vertical half is separate. */
:root[data-palette="editorial"] .cd-hero,
:root[data-palette="editorial"] .cd-dhead,
:root[data-palette="editorial"] .pd-hero,
:root[data-palette="editorial"] .pd-prhero,
:root[data-palette="editorial"] .pd-f2fhero {
  margin-left: var(--hero-bleed-x);
  margin-right: var(--hero-bleed-x);
}

/* The VERTICAL bleed belongs only to the block that actually starts the page, and
   this is the half the first attempt got wrong. A masthead pulls up through the
   page's own top padding so the band reaches the top edge — correct when it is
   the first thing on the page, and a 36px overlap onto whatever sits above it
   when it is not. Both desks put things above it: the board has a jump bar
   (present only when a pair is open, so the bug was intermittent), and every
   detail tab has a breadcrumb and a tab strip. :first-child answers exactly that
   question, including the conditional case, without the renderers having to say
   which arrangement they built. */
:root[data-palette="editorial"] .cd-page > .cd-hero:first-child,
:root[data-palette="editorial"] .cd-page > .cd-dhead:first-child,
:root[data-palette="editorial"] .pd-page > .pd-hero:first-child,
:root[data-palette="editorial"] .pd-page > .pd-prhero:first-child,
:root[data-palette="editorial"] .pd-page > .pd-f2fhero:first-child {
  margin-top: var(--hero-bleed-y);
}

/* ── The card ──────────────────────────────────────────────────────────────── */

/* One class, used everywhere a group of related things sits together. Page
   stylesheets opt in by adding it to their own section wrappers rather than by
   restating these five declarations. */
:where(.card, .view > .panel, .view > section) {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}

/* Views stack their own top-level blocks as separated cards. `gap` rather than
   margins on the children, so a page that hides a block does not leave its
   margin behind. */
.view {
  display: flex;
  flex-direction: column;
  gap: var(--gap-stack);
  padding-top: var(--gap-stack);
}

/* A card that holds a table clips its own corners, so the header row's fill
   follows the radius instead of squaring it off. */
:where(.card--table, .tablecard) {
  overflow: hidden;
  padding: 0;
}

.card--pad { padding: clamp(13px, 1.2vw, 18px); }

/* Nested surfaces step DOWN a rung, as the radius scale requires. */
:where(.card .card, .card .subcard) {
  border-radius: var(--r-md);
  box-shadow: none;
  background: var(--surface-sunken);
}

/* ── Labels ────────────────────────────────────────────────────────────────── */

/* The design's signature: uppercase mono at wide tracking in the quietest tier.
   It is what lets a section be introduced without a heading big enough to
   compete with the content under it. */
:where(.eyebrow, .card-label, .sec-label) {
  font: 500 10.5px/1.4 var(--font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--colhead);
}

/* A label followed by a plain-language gloss on the same line — the design uses
   this constantly, and the gloss is what keeps the tracked caps from reading as
   jargon. */
.sec-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px;
  padding: 14px 16px 0;
}
.sec-head .sec-note {
  font: 400 12px/1.5 var(--font-sans);
  color: var(--text-muted);
}

/* Headlines are the serif, and only headlines. */
:where(h1, h2, .headline) {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -.015em;
  text-wrap: balance;
}

/* ── Numbers ───────────────────────────────────────────────────────────────── */

/* Every figure is mono and tabular so columns line up under each other, which
   is most of what makes a dense table readable at a glance. */
:where(.num, .mono, td.num, .val, .figure) {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* ── Tables ────────────────────────────────────────────────────────────────── */

/* Cells stay square — only the card around them rounds. The header row is the
   sunken tier so it reads as chrome rather than as data. */
.view table { border-collapse: collapse; width: 100%; }

:where(.view thead th) {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--colhead);
  text-align: left;
  padding: 11px 14px;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  white-space: nowrap;
}

:where(.view tbody td) {
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
}
.view tbody tr:last-child td { border-bottom: 0; }

.view tbody tr {
  transition: background-color var(--dur-micro) var(--ease-out);
}
.view tbody tr:hover { background: var(--surface-row-active); }

/* ── Chips and pills ───────────────────────────────────────────────────────── */

:where(.chip, .tag, .pill) {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 10.5px/1 var(--font-sans);
  letter-spacing: .06em;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-2);
  white-space: nowrap;
}
.chip--on, .tag--on, .pill--on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.chip--bull { color: var(--bull-text); border-color: var(--bull-edge); background: var(--bull-tint); }
.chip--bear { color: var(--bear-text); border-color: var(--bear-edge); background: var(--bear-tint); }
.chip--warn { color: var(--warn-text); border-color: var(--warn-edge); background: var(--warn-tint); }

/* ── Buttons ───────────────────────────────────────────────────────────────── */

:where(.btn, .ghost) {
  font: 500 11.5px/1 var(--font-sans);
  letter-spacing: .06em;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out),
              color var(--dur-micro) var(--ease-out);
}
:where(.btn, .ghost):hover { background: var(--surface-sunken); border-color: var(--accent-edge); }
:where(.btn, .ghost):active { transform: scale(.985); }
.btn--on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ── KPI tiles ─────────────────────────────────────────────────────────────── */

/* The design's stat tile: a tracked label, a large mono figure, and a line of
   plain language under it explaining what the figure means. The gloss is the
   point — a number with no sentence beside it is a number a reader has to
   interpret for themselves. */
.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}
.kpi {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 15px;
  background: var(--surface-kpi);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.kpi-l {
  font: 500 9.5px/1.3 var(--font-mono);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead);
}
.kpi-v {
  font: 500 26px/1.05 var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--text);
}
.kpi-v .kpi-d { font-size: 13px; color: var(--text-muted); margin-left: 6px; }
.kpi-n { font: 400 11.5px/1.45 var(--font-sans); color: var(--text-muted); }

/* ── Meters ────────────────────────────────────────────────────────────────── */

/* A diverging bar: the track is the sunken tier, the fill runs from the centre
   in the up or down colour. Used by the currency board and the committee grid. */
.meter { position: relative; height: 6px; background: var(--surface-sunken);
         border-radius: var(--r-xs); overflow: hidden; }
.meter-f { position: absolute; top: 0; bottom: 0; border-radius: var(--r-xs); }
.meter-f--up { background: var(--bull-dot); }
.meter-f--dn { background: var(--bear-dot); }

/* ── The model bar ─────────────────────────────────────────────────────────── */

/* The Claude | Gemini | Grok segmented switch. Named md-* for historical reasons
   -- it was written for the Master Dashboard -- but it is NOT that page's: app.js
   builds it for Drivers and Standing, and market-expectations.js for Market
   Expectations. It lives here because a rule three pages depend on cannot sit in
   a fourth page's stylesheet, where the next rewrite of that page deletes it and
   silently unstyles the other three. The class names are kept exactly as they
   are: renaming them would mean editing every call site for no visible gain.

   Pill segments: transparent inactive, hairline border, accent-fill active. */
/* Claude|Gemini|Grok model switch — mirrors the shared .aibar-seg control
   (app.css) used on Currencies/Pairs: pill segments, transparent inactive,
   hairline border, accent-fill active. Kept as .md-* classes so the module
   stays a self-contained IIFE, but visually identical to the app-wide bar. */
.md-modelbar {
  display: flex; align-items: center; gap: 7px;
  padding: 14px 0 4px; margin: 0 0 10px;   /* same top breathing room as .aibar (app.css) — was flush against the tab strip */
  flex-wrap: wrap;
}
.md-modelseg {
  font: 500 11.5px/1 var(--font-sans); color: var(--text-muted);
  background: transparent; border: 1px solid var(--line2);
  border-radius: var(--r-pill); padding: 5px 13px; cursor: pointer;
  /* named properties, never `all` — this button also carries padding + a radius, and a
     blanket transition drags those through every palette/theme swap. */
  transition: background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.md-modelseg:hover { color: var(--text); }
.md-modelseg--on {
  color: var(--on-accent); background: var(--accent);
  border-color: var(--accent);
}
.md-modelbar-note {
  font: 400 11.5px/1 var(--font-mono); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

/* ── Reduced motion ────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  :where(.btn, .ghost):active { transform: none; }
}

/* ── Narrow viewports ──────────────────────────────────────────────────────── */

@media (max-width: 720px) {
  .topbar { height: auto; padding: 10px 12px; flex-wrap: wrap; }
  .kpis { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}
