/* Observatory app styles. Colours come exclusively from tokens.css. */

* { margin: 0; padding: 0; box-sizing: border-box; }

html { font-size: 16px; }

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Hiragino Sans", "Yu Gothic", sans-serif;
  background: var(--obs-surface);
  color: var(--obs-text);
  line-height: 1.5;
}

.num, .tabular { font-variant-numeric: tabular-nums; }

/* present to screen readers, absent on screen */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

a { color: var(--obs-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--obs-focus);
  border-radius: 2px;
}

/* An in-page anchor must land below the sticky header, not under it. The bar
   is 53px until the nav wraps (below ~500px), where it grows to three rows. */
html { scroll-padding-top: 66px; }
@media (max-width: 499px) { html { scroll-padding-top: 150px; } }

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--obs-header-bg);
  /* Header and section bands share one navy, so a band scrolling under the
     sticky header would merge into a single slab. This rule is invisible
     against the white page and only shows as a seam where the two navies meet. */
  border-bottom: 1px solid var(--obs-header-border);
  color: var(--obs-header-text);
}

/* the bar is dark in both themes, so the default focus ring is invisible on it */
.site-header :focus-visible { box-shadow: 0 0 0 2px var(--obs-header-focus); }

.site-header .inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 20px;
  height: 52px;
  display: flex;
  align-items: center;
  gap: 24px;
}

.brand { font-weight: 700; color: var(--obs-header-ink); font-size: 15px; letter-spacing: 0.01em; }
.brand .ds { font-weight: 400; color: var(--obs-header-muted); }

.site-nav { display: flex; gap: 16px; font-size: 13.5px; }
.site-nav a { color: var(--obs-header-text); padding: 4px 2px; }
.site-nav a:hover { text-decoration: none; color: var(--obs-header-ink); }
.site-nav a[aria-current="page"] {
  color: var(--obs-header-ink);
  font-weight: 600;
  border-bottom: 2px solid var(--obs-header-accent);
  margin-bottom: -2px;
}

.header-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.header-asof { font-size: 12px; color: var(--obs-header-muted); white-space: nowrap; }

.theme-toggle {
  font: inherit; font-size: 12px;
  color: var(--obs-header-text);
  background: none;
  border: 1px solid var(--obs-header-border);
  border-radius: 3px;
  padding: 3px 10px;
  cursor: pointer;
}
.theme-toggle:hover { border-color: var(--obs-header-ink); color: var(--obs-header-ink); }

/* ---------- layout ---------- */

.container { max-width: 1240px; margin: 0 auto; padding: 20px 20px 56px; }

/* The Item Explorer's table is eleven columns wide by design; at the standard
   measure it would clip its last column at 1440. The header and footer widen
   with it so the page still reads as one column of content. */
body.page-wide .container,
body.page-wide .site-header .inner,
body.page-wide .site-footer .inner { max-width: 1360px; }

.page-head { margin: 12px 0 8px; }
h1 { font-size: 22px; color: var(--obs-ink); font-weight: 700; }
.page-sub { font-size: 13px; color: var(--obs-text-muted); margin-top: 4px; }
.page-sub .sep { margin: 0 6px; }

section { margin-top: 32px; }

/* Section headers are a filled blue band, not underlined text — it is the one
   place a filled colour block is house style. Panels opt out (.detail-head h2).
   The band owns its own spacing on both sides: pages are not required to wrap
   sections in <section> or .prose for a band to clear the content above it.
   (Adjacent/parent margins collapse, so wrapped pages don't double up.) */
h2 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--obs-band-ink);
  background: var(--obs-band-bg);
  border-radius: 3px;
  padding: 10px 16px;
  margin-top: 32px;
  margin-bottom: 14px;
}
.h2-note {
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--obs-band-muted);
}
.section-sub {
  font-size: 13px;
  color: var(--obs-text-muted);
  max-width: 74ch;
  margin: 0 0 12px;
}
h3 { font-size: 13.5px; color: var(--obs-ink); font-weight: 600; margin: 16px 0 6px; }

/* ---------- banners ---------- */

.banner {
  border: 1px solid var(--obs-trust-stale);
  color: var(--obs-trust-stale);
  border-radius: 3px;
  padding: 8px 12px;
  font-size: 13px;
  margin: 12px 0;
}

/* A neutral sibling of .banner, for a disclosure that is not a fault: a
   methodology break the reader must know about before reading a growth rate.
   The stale colour would read as "something is broken" and this is not. */
.banner-note {
  border-color: var(--obs-border);
  color: var(--obs-text-muted);
}

/* ---------- badges (outline-only) ---------- */

.badge {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  padding: 0 6px;
  border: 1px solid;
  border-radius: 3px;
  white-space: nowrap;
  vertical-align: middle;
}
.badge-official { color: var(--obs-trust-official); border-color: var(--obs-trust-official); }
.badge-model    { color: var(--obs-trust-model);    border-color: var(--obs-trust-model); }
.badge-stale    { color: var(--obs-trust-stale);    border-color: var(--obs-trust-stale); }

/* ---------- headline metric card ---------- */

.metric-card {
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  padding: 22px 24px 18px;
  margin-top: 12px;
}
/* Title and ingest stamp share the top line; the sub-line is forced onto its
   own row below both by the 100% basis. */
.metric-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0 24px;
}
.metric-card-head h1 { font-size: 22px; font-weight: 700; letter-spacing: -0.2px; color: var(--obs-ink); }
.metric-asof {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 12px;
  color: var(--obs-text-muted);
  white-space: nowrap;
}
.metric-sub { flex: 1 0 100%; margin-top: 6px; font-size: 13px; color: var(--obs-text-muted); }

/* One framed strip rather than five separate cards: the readings are one
   family of measures on one reference month, and the shared frame says so.
   The frame clips the trailing column and row rules (the grid is pulled 1px
   past it), so cell dividers stay hairlines at any column count and a partly
   filled last row leaves no orphaned rule. */
.strip {
  margin-top: 20px;
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  overflow: hidden;
}
.strip-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin: 0 -1px -1px 0;
}
.strip-cell {
  padding: 14px 16px 16px;
  min-width: 0;
  border-right: 1px solid var(--obs-border);
  border-bottom: 1px solid var(--obs-border);
}
/* Never wraps: a two-line label in one cell would drop that cell's value off
   the baseline its neighbours share. The full label is on the title tooltip. */
.strip-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--obs-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.strip-value {
  margin-top: 8px;
  font-size: 34px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -1px;
  color: var(--obs-ink);
}
.strip-value .unit {
  font-size: 16px;
  font-weight: 600;
  color: var(--obs-text-muted);
  margin-left: 2px;
  letter-spacing: normal;
}
.strip-delta { margin-top: 8px; font-size: 13px; font-weight: 600; }
.strip-delta.up { color: var(--obs-trust-model); }
.strip-delta.down { color: var(--obs-trust-official); }
.strip-delta.flat { color: var(--obs-text-muted); }
.strip-meter {
  margin-top: 8px;
  height: 4px;
  background: var(--obs-grid);
  border-radius: 2px;
  overflow: hidden;
}
.strip-meter i { display: block; height: 100%; background: var(--obs-primary); border-radius: 2px; }
/* A cell with no meter still reserves the lane, so every foot in the strip
   sits on one line. Hidden rather than absent: an empty track under a value
   that is not a share of anything would imply a scale that does not exist. */
.strip-meter.is-empty { visibility: hidden; }
.strip-foot { margin-top: 10px; font-size: 12px; color: var(--obs-text-faint); }
/* The company strip carries three readings where the sector strip carries
   five. It sets its own column count and repeats it at each breakpoint, since
   the wider selector alone would lose to this one inside a media query. The
   orphan-slack rules above already fit three cells at two columns. */
.strip-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
/* The BOJ strip carries four readings; it splits 2×2 rather than 3+1 so no
   orphan-slack rule is ever needed for it. */
.strip-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* ---------- controls ---------- */

.controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.controls label { font-size: 12px; color: var(--obs-text-muted); }

select, input[type="search"], input[type="text"] {
  font: inherit;
  font-size: 13px;
  color: var(--obs-ink);
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 5px 8px;
}
select:focus, input:focus {
  outline: none;
  border-color: var(--obs-primary);
  box-shadow: 0 0 0 2px var(--obs-focus-soft);
}
input[type="search"] { width: 300px; max-width: 100%; }

.seg { display: inline-flex; border: 1px solid var(--obs-border); border-radius: 3px; overflow: hidden; }
.seg button {
  font: inherit; font-size: 12.5px;
  padding: 4px 11px;
  background: var(--obs-surface);
  color: var(--obs-text);
  border: none;
  border-right: 1px solid var(--obs-border);
  cursor: pointer;
}
.seg button:last-child { border-right: none; }
.seg button:hover { background: var(--obs-surface-subtle); }
.seg button[aria-pressed="true"] {
  background: var(--obs-surface-subtle);
  color: var(--obs-primary);
  font-weight: 600;
}

.btn {
  font: inherit; font-size: 12.5px;
  color: var(--obs-primary);
  background: var(--obs-surface);
  border: 1px solid var(--obs-primary);
  border-radius: 3px;
  padding: 4px 12px;
  cursor: pointer;
}
.btn:hover { background: var(--obs-surface-subtle); }

.controls .spacer { flex: 1; }

/* ---------- ask (floating assistant) ---------- */

.btn-primary {
  background: var(--obs-primary);
  border-color: var(--obs-primary);
  color: var(--obs-surface);
  font-weight: 600;
  padding: 5px 16px;
}
.btn-primary:hover { background: var(--obs-primary-dark); border-color: var(--obs-primary-dark); }
.btn-primary:disabled { opacity: 0.55; cursor: default; }
.btn-primary:disabled:hover { background: var(--obs-primary); border-color: var(--obs-primary); }

/* The launcher is the one filled action on the page it floats over, so it can
   carry brand fill without competing with the data. */
.ask-launcher {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 900;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--obs-surface);
  background: var(--obs-primary);
  border: 1px solid var(--obs-primary-dark);
  border-radius: 3px;
  padding: 9px 16px;
  cursor: pointer;
}
.ask-launcher:hover { background: var(--obs-primary-dark); }

/* No shadow anywhere in this system, so the panel needs the scrim to read as
   floating rather than as part of the page. */
.ask-scrim {
  position: fixed;
  inset: 0;
  z-index: 940;
  background: rgba(15, 23, 42, 0.18);
}

/* An author `display` beats the UA stylesheet's [hidden] { display: none },
   so the attribute has to be re-asserted here or the panel never hides —
   it would sit over the page permanently and Close would appear dead. */
.ask-panel[hidden],
.ask-scrim[hidden] { display: none; }

.ask-panel {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 950;
  width: 420px;
  max-width: calc(100vw - 40px);
  height: 560px;
  max-height: calc(100vh - 40px);
  display: flex;
  flex-direction: column;
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  margin: 0;
}

.ask-panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--obs-border);
  flex: none;
}
.ask-panel-head h2 {
  /* opt out of the filled section band — this is a panel title */
  display: block;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--obs-ink);
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  margin: 0;
}
.ask-close {
  margin-left: auto;
  font: inherit;
  font-size: 12px;
  color: var(--obs-text-muted);
  background: none;
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 3px 10px;
  cursor: pointer;
}
.ask-close:hover { color: var(--obs-ink); border-color: var(--obs-text-muted); }

.ask-thread {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.ask-empty { font-size: 12.5px; color: var(--obs-text-muted); }
.ask-suggestions { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.ask-suggest {
  font: inherit;
  font-size: 12.5px;
  color: var(--obs-primary);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
}
.ask-suggest:hover { text-decoration: underline; }

/* The reader's own turn is set apart by alignment and a tint, not a bubble
   with a large radius — this stays a document, not a messaging app. */
.ask-msg-user {
  align-self: flex-end;
  max-width: 85%;
  font-size: 13.5px;
  color: var(--obs-ink);
  background: var(--obs-surface-subtle);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 7px 10px;
}
.ask-msg-agent { align-self: stretch; }

.ask-compose {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--obs-border);
}
.ask-compose input[type="text"] { flex: 1; font-size: 13.5px; padding: 7px 10px; }

.ask-body {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--obs-text);
  font-variant-numeric: tabular-nums;
}
.ask-body p { margin: 0 0 10px; }
.ask-body p:last-child { margin-bottom: 0; }
.ask-body ul { margin: 8px 0 10px 20px; }
.ask-body li { margin: 3px 0; }
/* the model emphasises the figure it was asked for; keep it a weight change
   only, so a bolded number still sits on the same baseline as the prose */
.ask-body strong { font-weight: 600; color: var(--obs-ink); }
.ask-body code {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 13px;
  color: var(--obs-ink);
}
.ask-foot { font-size: 11px; color: var(--obs-text-muted); margin-top: 10px; }
.ask-msg-agent details.calc { margin-top: 4px; }

/* one grid for every row, so the detail column starts at the same x
   whatever the lookup is called */
.ask-lookups {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 3px 14px;
  font-size: 12.5px;
}
.ask-lookup-what { color: var(--obs-ink); }
.ask-lookup-detail { color: var(--obs-text-muted); overflow-wrap: anywhere; }
.ask-sources {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--obs-border);
}
.ask-trust { margin-top: 10px; }
.ask-working { font-size: 13px; color: var(--obs-text-muted); padding: 2px 0 8px; }
/* the shared state style is sized for an empty panel; here it sits inline */
.ask-msg .state-error { padding: 0; font-size: 13px; }

/* ---------- charts ---------- */

/* A chart travels with its controls and source line in one bordered panel —
   the same edge the tables and stat strips already carry. Chart containers
   that already sit inside a bordered panel (.ov-panel, .detail) stay bare:
   no box inside a box. */
.chart-panel,
.chart-block {
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  background: var(--obs-surface);
  padding: 12px 14px;
  margin: 12px 0 4px;
}
.chart { width: 100%; height: 380px; }
.chart-bars { width: 100%; height: 400px; }
.source-line { font-size: 11px; color: var(--obs-text-muted); margin-top: 6px; }

/* ---------- show calculation ---------- */

details.calc { margin-top: 8px; font-size: 12.5px; }
details.calc summary {
  cursor: pointer;
  color: var(--obs-primary);
  font-size: 12px;
  list-style: none;
  display: inline-block;
}
details.calc summary::before { content: "▸ "; }
details.calc[open] summary::before { content: "▾ "; }
details.calc .calc-body {
  margin-top: 6px;
  padding: 8px 12px;
  border-left: 2px solid var(--obs-border);
  color: var(--obs-text);
  font-size: 12.5px;
}
details.calc code {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 12px;
}

/* ---------- tables ---------- */

.table-meta {
  font-size: 12.5px;
  color: var(--obs-text-muted);
  margin-bottom: 8px;
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

/* ---------- table tools: filter + row count ----------
   Sits above a data table, outside its scroll wrapper so a re-render of the
   table cannot destroy it. Every data table gets this by default. */

.table-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.table-tools .table-filter {
  font: inherit;
  font-size: 12.5px;
  padding: 4px 8px;
  min-width: 200px;
  max-width: 320px;
  flex: 1 1 200px;
  color: var(--obs-ink);
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
}
.table-tools .table-filter:focus {
  outline: 2px solid var(--obs-primary);
  outline-offset: -1px;
}
.table-count {
  font-size: 11.5px;
  color: var(--obs-text-muted);
  white-space: nowrap;
}
.table-empty {
  font-size: 12.5px;
  color: var(--obs-text-muted);
  margin: 8px 0 0;
}
@media (max-width: 560px) {
  .table-tools .table-filter { max-width: none; }
}

.table-wrap { overflow-x: auto; border: 1px solid var(--obs-border); border-radius: 3px; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
table.data th {
  position: sticky;
  top: 0;
  background: var(--obs-surface-subtle);
  color: var(--obs-text-muted);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--obs-border);
  white-space: nowrap;
  z-index: 2;
}
table.data th.num { text-align: right; }
table.data th.sortable { cursor: pointer; user-select: none; }
table.data th.sortable:hover { color: var(--obs-ink); }
table.data th .arrow { font-size: 9px; margin-left: 3px; }
table.data td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--obs-border);
  vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: none; }
table.data td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--obs-ink);
}
table.data td.muted, table.data .muted { color: var(--obs-text-muted); }
/* Statement-style tables indent a sub-line INSIDE the cell inset, never in
   place of it: an inline padding-left of 0 for a top-level line put the text
   on the table border. Levels add to the 10px every cell has. */
table.data td.indent-1 { padding-left: 28px; }
table.data td.indent-2 { padding-left: 46px; }
table.data td.indent-3 { padding-left: 64px; }
table.data tbody tr:hover { background: var(--obs-surface-subtle); }
table.data tbody tr.clickable { cursor: pointer; }

.cell-item .en { color: var(--obs-ink); font-weight: 500; }
.cell-item .ja { color: var(--obs-text-muted); font-size: 12px; }
.cell-item { max-width: 320px; overflow: hidden; text-overflow: ellipsis; }

/* A platform classification sitting beside a filed name. Outline only, so it
   never reads as part of the disclosure it annotates. */
.tag-note {
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--obs-text-muted);
  border: 1px solid var(--obs-border);
  border-radius: 2px;
  padding: 0 4px;
  white-space: nowrap;
}

/* A table whose last column carries a sentence-length list rather than a
   value. Squeezed below its floor width the browser crushes that column to a
   few characters and every row grows to a dozen lines of ragged text, so the
   table keeps a minimum width and the wrapper scrolls instead. */
.tbl-roomy { min-width: 900px; }
.tbl-roomy td:last-child { min-width: 340px; }

/* ---------- footnote flags ---------- */

/* The lane is reserved on every row, flagged or not, so a marker never pushes a
   column of digits out of alignment. .has-lane pads the header by the same
   amount to keep the label flush with the numbers below it. */
/* px, not em: the header is 11px and the cells 13px, so an em-based lane would
   reserve two different widths and pull the header off the digits below it. */
.note-lane {
  display: inline-block;
  width: 15px;
  padding-left: 4px;
  text-align: left;
}
table.data th.has-lane { padding-right: 29px; } /* 10px cell padding + 19px lane */

.note-mark {
  font-size: 10px;
  line-height: 1;
  color: var(--obs-text-muted);
  cursor: help;
}
table.data tbody tr:hover .note-mark { color: var(--obs-ink); }

.table-notes {
  margin-top: 10px;
  max-width: 92ch;
  font-size: 12px;
  color: var(--obs-text-muted);
}
.table-notes:empty { margin-top: 0; }
.table-notes p { margin: 4px 0; }
.table-notes b { color: var(--obs-text); font-weight: 600; }
.table-notes .note-mark { cursor: default; margin-right: 2px; }
.table-notes .note-calc { margin-top: 8px; }

.detail-note { font-size: 12.5px; color: var(--obs-text); margin: 0 0 8px; max-width: 92ch; }
.detail-note b { font-weight: 600; }
.detail-note .note-mark { cursor: default; margin-right: 2px; }

.spark { display: block; }
.spark polyline { fill: none; stroke: var(--obs-series-1); stroke-width: 1.5; }

/* ---------- item explorer: search rail ---------- */

/* Scope switch, query box and scope hints are one control, not three: the two
   tabs change what the same query searches, so they share one frame. */
.explorer-controls { display: flex; align-items: stretch; gap: 16px; margin-bottom: 14px; }

.search-rail {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: stretch;
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  overflow: hidden;
}
/* the ring lives on the frame, so the borderless input still shows focus */
.search-rail:focus-within { border-color: var(--obs-primary); box-shadow: 0 0 0 2px var(--obs-focus-soft); }
.search-rail :focus-visible { box-shadow: none; }

.seg-flush {
  flex: 0 0 auto;
  border: 0;
  border-right: 1px solid var(--obs-border);
  border-radius: 0;
  background: var(--obs-surface-subtle);
}
.seg-flush button {
  padding: 0 18px;
  font-size: 14px;
  font-weight: 500;
  color: var(--obs-text-muted);
  background: transparent;
  border-right: 0;
  border-bottom: 3px solid transparent;
}
.seg-flush button:hover { background: transparent; color: var(--obs-ink); }
.seg-flush button[aria-pressed="true"] {
  background: var(--obs-surface);
  color: var(--obs-primary);
  font-weight: 600;
  border-bottom-color: var(--obs-primary);
}

.search-field {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  min-height: 44px;
}
.search-icon { flex: 0 0 auto; stroke: var(--obs-primary); stroke-width: 1.8; fill: none; }
.search-field input[type="search"] {
  flex: 1;
  width: auto;
  min-width: 60px;
  font-size: 15px;
  color: var(--obs-ink);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
}
.search-field input[type="search"]:focus { border: 0; box-shadow: none; }

.search-scope {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--obs-text-muted);
  cursor: help;
}
.search-scope i { display: block; width: 1px; height: 11px; background: var(--obs-border); }
.search-scope .mono { font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace; }

.btn-tall { min-height: 44px; padding: 0 16px; white-space: nowrap; }

.meta-rule { width: 1px; height: 12px; background: var(--obs-border); }
.table-meta b { color: var(--obs-ink); font-weight: 600; }

/* ---------- item explorer: column bands ---------- */

.band-toggles {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 10px 12px;
  margin-bottom: 14px;
  background: var(--obs-surface-subtle);
  border: 1px solid var(--obs-border);
  border-radius: 4px;
}
.band-toggles-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--obs-text-muted);
}
.band-toggles label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--obs-text);
  cursor: pointer;
}
.band-toggles input { width: 14px; height: 14px; margin: 0; accent-color: var(--obs-primary); cursor: pointer; }
/* A picker with a ceiling greys the options it cannot take, rather than
   accepting the click and silently dropping it. */
.band-toggles label.is-disabled { color: var(--obs-text-faint); cursor: default; }
.band-toggles label.is-disabled input { cursor: default; }
/* Trails the options, and wraps with them rather than pushing them. */
.band-toggles-note { margin-left: auto; font-size: 12px; color: var(--obs-text-faint); }

/* Two header rows: the upper one names what a group of columns means, the lower
   one names the columns. Both stay put while the body scrolls, so the second
   row's offset is pinned to the first row's exact height (15 + 7 + 7). */
/* The fixed columns come to 1,034px; the rest is the item name's designed
   minimum. Past that the wrap scrolls — eleven columns of a dense table is
   wider than the page, and squeezing the names instead makes every long one
   wrap to three lines. */
.tbl-bands { min-width: 1260px; }
/* BOJ series tables: enough width that the name column stays readable and the
   trend/as-of columns survive; below it the wrap scrolls, never the page. */
.tbl-series { min-width: 720px; }
.tbl-series td:first-child { max-width: 300px; }
.tbl-bands th, .tbl-bands td { padding: 12px 14px; }

.tbl-bands thead .band-row th {
  top: 0;
  padding: 7px 14px;
  line-height: 15px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--obs-primary);
  background: var(--obs-surface-subtle);
  white-space: nowrap;
}
.tbl-bands thead .band-row th.band-accent { background: var(--obs-grid); }

.tbl-bands thead .col-row th {
  top: 29px;
  padding: 9px 14px;
  font-size: 11px;
  letter-spacing: 0.05em;
  background: var(--obs-surface);
  border-bottom: 1px solid var(--obs-border);
}
.tbl-bands thead .col-row th.has-lane { padding-right: 33px; } /* 14px cell padding + 19px lane */

/* A band's first column carries the rule that separates it from the band
   before it; columns inside a band are separated by alignment alone. */
.tbl-bands .band-start { border-left: 1px solid var(--obs-border); }
.tbl-bands .band-start-soft { border-left: 1px solid var(--obs-grid); }

.tbl-bands tbody td { font-size: 14px; border-bottom: 1px solid var(--obs-grid); }
.tbl-bands tbody tr:last-child td { border-bottom: none; }

.tbl-bands .col-code { width: 74px; padding-right: 0; }
.tbl-bands td.col-code {
  font-size: 13px;
  color: var(--obs-text-muted);
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
}
.tbl-bands .col-item { min-width: 226px; padding-left: 0; }
.tbl-bands .cell-item { max-width: none; overflow: visible; text-wrap: pretty; }
.tbl-bands .cell-item .en { font-size: 14px; font-weight: 600; line-height: 1.3; }
.tbl-bands .cell-item .ja { margin-top: 2px; font-size: 13px; }

.tbl-bands .col-weight { width: 112px; }
.tbl-bands .col-index { width: 104px; }
.tbl-bands .col-prev { width: 104px; }
.tbl-bands .col-mom { width: 88px; }
.tbl-bands .col-yoy { width: 86px; }
.tbl-bands .col-yoyprior { width: 104px; }
.tbl-bands .col-contrib { width: 118px; }
.tbl-bands .col-ann { width: 104px; }
.tbl-bands .col-spark { width: 140px; }

/* These carry `table.data` because `table.data td.num` also sets a colour and
   would otherwise win on specificity — the prior-month and prior-year columns
   would come out at full ink and stop reading as the quieter comparison. */
.tbl-bands td.col-index, .tbl-bands td.col-yoy { font-weight: 600; }
table.data.tbl-bands td.col-prev,
table.data.tbl-bands td.col-yoyprior { color: var(--obs-text-faint); }
table.data.tbl-bands td.col-mom,
table.data.tbl-bands td.col-ann { color: var(--obs-text); }
/* Same amber-up / green-down reading as the overview strip, and never the only
   carrier of direction — the sign is printed beside it. */
table.data.tbl-bands td.trend-accel { color: var(--obs-trust-model); }
table.data.tbl-bands td.trend-decel { color: var(--obs-trust-official); }

.contrib-cell { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.contrib-track {
  flex: 1;
  min-width: 20px;
  height: 5px;
  background: var(--obs-grid);
  border-radius: 2px;
  overflow: hidden;
}
.contrib-track i { display: block; height: 100%; background: var(--obs-primary); border-radius: 2px; }
.contrib-val { flex: 0 0 auto; min-width: 34px; text-align: right; font-size: 13px; color: var(--obs-text); }

.table-foot { margin-top: 14px; max-width: 92ch; font-size: 12px; color: var(--obs-text-muted); }
.table-foot:empty { margin-top: 0; }

/* ---------- detail panel (explorer) ---------- */

.detail {
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 16px;
  margin-bottom: 24px;
}
.detail-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
/* the panel already is the container, so its title stays plain text — a band
   here would be a filled box inside a bordered box */
.detail-head h2 {
  display: block;
  border: none; padding: 0; margin: 0;
  font-size: 16px; font-weight: 600;
  text-transform: none; letter-spacing: normal;
  background: none; color: var(--obs-ink);
}
.detail-head .ja { color: var(--obs-text-muted); font-size: 13px; }
.detail-close { margin-left: auto; }
.detail-meta { font-size: 12.5px; color: var(--obs-text-muted); margin: 6px 0 12px; }

/* Range sits on its own row under the measure row: it is a control on the
   chart, not on the download buttons it would otherwise crowd. */
.range-row { gap: 6px; }
.range-row .seg { margin-right: 4px; }
.range-row select { padding: 4px 6px; font-size: 12.5px; }
.range-row .range-note {
  font-size: 11.5px;
  color: var(--obs-text-muted);
  margin-left: 4px;
}

/* ---------- yield-curve page ---------- */

/* the date scrubber: play button · slider · latest · the selected date */
.curve-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2px 0 10px;
}
.curve-row input[type="range"] {
  flex: 1;
  min-width: 0;
  accent-color: var(--obs-primary);
}
.curve-date {
  flex: 0 0 auto;
  min-width: 106px;
  text-align: right;
  font-size: 13px;
  font-weight: 600;
  color: var(--obs-ink);
}
/* pinned-date chips — outline-only, removable */
.pin-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 3px 8px;
  margin-right: 6px;
  font-size: 12px;
  color: var(--obs-text);
  background: none;
  cursor: pointer;
}
.pin-chip:hover { border-color: var(--obs-text-muted); }
.pin-chip .x { color: var(--obs-text-muted); font-size: 11px; }

/* ---------- states ---------- */

.skeleton {
  background: var(--obs-surface-subtle);
  border-radius: 3px;
  animation: obs-shimmer 1.2s ease-in-out infinite alternate;
}
@keyframes obs-shimmer { from { opacity: 1; } to { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}

.state-empty, .state-error {
  font-size: 13.5px;
  padding: 24px 16px;
  color: var(--obs-text-muted);
}
.state-error { color: var(--obs-trust-stale); }
.state-error details { margin-top: 8px; font-size: 12px; }

/* ---------- provenance card ---------- */

.prov-card { border: 1px solid var(--obs-border); border-radius: 3px; overflow: hidden; }
.prov-card-head {
  background: var(--obs-band-bg);
  color: var(--obs-band-ink);
  /* 20px matches the body inset, so the head title and the labels below it
     start on the same vertical line. */
  padding: 10px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.prov-card-head .prov-card-title {
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.prov-card-head .prov-card-id {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 12px;
  color: var(--obs-band-muted);
}
.prov-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; padding: 4px 20px; }
.prov-field { grid-column: span 1; padding: 14px 0; border-bottom: 1px solid var(--obs-grid); }
.prov-field.full { grid-column: 1 / -1; }
.prov-field:last-child { border-bottom: none; }
/* A label/value pair on one line in the provenance card. There was no rule
   for the row at all, so the two spans were plain inline text and printed
   with no gap whatsoever — "RELEASEData through January 2026". A fixed label
   column also lines the values up down the card, which is the point of
   reading it. */
.prov-row {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: 2px 14px;
  align-items: baseline;
  padding: 3px 20px;
}
.prov-row .prov-label { margin-bottom: 0; }
/* The card has two bodies: the .prov-grid variant, which carries its own
   20px inset, and the row/paragraph variant (population, representation),
   whose rows and notes sit directly in the card. That variant inherited no
   gutter at all, so the labels and the trust note printed hard against the
   border. Same 20px inset, plus clearance under the head band and above the
   bottom edge. */
.prov-card > .prov-row:first-of-type { padding-top: 14px; }
.prov-card > .prov-sub { padding: 0 20px; margin-top: 10px; }
.prov-card > .prov-sub:last-child { padding-bottom: 16px; }
@media (max-width: 560px) {
  .prov-row { grid-template-columns: minmax(0, 1fr); }
}

.prov-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--obs-text-muted);
  margin-bottom: 5px;
}
/* prose must not split mid-word; only the checksum needs a hard break */
.prov-value { font-size: 14px; color: var(--obs-text); line-height: 1.5; overflow-wrap: anywhere; }
.prov-sub { font-size: 12.5px; color: var(--obs-text-muted); margin-top: 3px; }
.prov-hash {
  background: var(--obs-surface-subtle);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 8px 12px;
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 12.5px;
  color: var(--obs-ink);
  word-break: break-all;
}

.site-footer {
  border-top: 1px solid var(--obs-border);
  margin-top: 48px;
}
.site-footer .inner {
  max-width: 1240px; margin: 0 auto; padding: 16px 20px;
  font-size: 12px; color: var(--obs-text-muted);
}

/* ---------- prose (methodology) ---------- */

/* The measure sits on the text, not on the block: running prose stays at a
   readable 74ch while the section bands, the tables and the dataset-note rows
   span the content width the way they do on every other page. */
.prose { font-size: 14.5px; line-height: 1.6; }
.prose p, .prose ul, .prose ol, .prose dl { max-width: 74ch; }
.prose p { margin: 10px 0; }
.prose ul, .prose ol { margin: 10px 0 10px 22px; }
.prose li { margin: 4px 0; }
.prose table { margin: 12px 0; }
.prose code {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 13px;
  background: var(--obs-surface-subtle);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 0 4px;
}

/* ---------- methodology: contents strip ---------- */

/* A reference page long enough that a reader arrives looking for one section.
   Plain links, not chips: this is a table of contents, not navigation. */
.toc {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin: 14px 0 0;
  padding: 10px 0;
  border-top: 1px solid var(--obs-border);
  border-bottom: 1px solid var(--obs-border);
  font-size: 12.5px;
}
.toc a { color: var(--obs-text-muted); }
.toc a:hover { color: var(--obs-ink); }

/* ---------- methodology: dataset notes ---------- */

/* Twelve stacked disclosures, one row each until opened, so the page reads as
   a list of datasets rather than forty screens of prose. Nothing is hidden
   from the record — the markup, and the copy served to assistants over MCP,
   carries every note whether or not a reader opens it. */
.ds { border-bottom: 1px solid var(--obs-border); }
.ds:first-of-type { border-top: 1px solid var(--obs-border); }
.ds > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  padding: 11px 2px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--obs-ink);
}
.ds > summary::-webkit-details-marker { display: none; }
.ds > summary::before {
  content: "\25B8";
  font-size: 10px;
  color: var(--obs-text-muted);
}
.ds[open] > summary::before { content: "\25BE"; }
.ds > summary:hover { color: var(--obs-primary); }
.ds > summary:focus-visible { outline: 2px solid var(--obs-primary); outline-offset: 2px; }
/* The qualifier sits right on one line and drops under the name when the row
   wraps, rather than being pushed off the end of it. */
.ds-note { font-weight: 400; font-size: 12px; color: var(--obs-text-muted); margin-left: auto; }
@media (max-width: 560px) {
  .ds-note { margin-left: 18px; flex-basis: 100%; }
}
.ds-body { padding: 0 2px 14px 20px; }
.ds-body > ul:first-child, .ds-body > p:first-child { margin-top: 0; }

/* ---------- responsive ---------- */

@media (max-width: 1024px) {
  .strip-grid { grid-template-columns: repeat(3, 1fr); }
  .strip-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
}
/* The scope hints are a legend for the search box; once the box is narrow
   enough that they crowd the query, the title tooltip carries them instead. */
@media (max-width: 860px) {
  .search-scope { display: none; }
}
@media (max-width: 700px) {
  .explorer-controls { flex-wrap: wrap; }
  .search-rail { flex: 1 0 100%; flex-wrap: wrap; }
  .seg-flush {
    flex: 1 0 100%;
    border-right: 0;
    border-bottom: 1px solid var(--obs-border);
  }
  .seg-flush button { flex: 1; }
  .search-field { flex: 1 0 100%; }
  .btn-tall { flex: 1; }
  .band-toggles { gap: 10px 18px; }
  /* the count and the trust sentence are on separate lines here, so the rule
     that separated them would be left hanging off the end of the first one */
  .meta-rule { display: none; }
}
@media (max-width: 768px) {
  .strip-grid, .strip-grid.cols-3, .strip-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
  .strip-value { font-size: 30px; }
  .site-header .inner { gap: 12px; }
  /* Section labels wrap as whole items, never mid-label. */
  .site-nav { flex-wrap: wrap; gap: 4px 12px; }
  .site-nav a { white-space: nowrap; }
  .header-asof { display: none; }
  .chart { height: 300px; }
  .chart-bars { height: 360px; }
  .cell-item { max-width: 200px; }
  .prov-grid { grid-template-columns: 1fr; }
}
/* Once the strip wraps, a last row one cell short would leave a dead half-row
   inside the frame and an orphaned divider; the final cell takes the slack so
   every row reaches the frame edge. Bounded on both sides: a `span 2` that
   leaked into the single-column layout would conjure a second column. */
@media (min-width: 769px) and (max-width: 1024px) {
  .strip-cell:last-child:nth-child(3n + 2) { grid-column: span 2; }
}
@media (min-width: 481px) and (max-width: 768px) {
  .strip-cell:last-child:nth-child(2n + 1) { grid-column: span 2; }
}
/* Below this the title and the stamp cannot share a line, and a stamp wrapped
   between the title and the sub-line reads as a caption on the wrong text. */
@media (max-width: 600px) {
  .metric-asof { order: 3; margin-top: 2px; }
  .metric-card { padding: 18px 16px 14px; }
}
@media (max-width: 480px) {
  /* cols-4 stacks here too: two columns on a phone leaves ~155px a cell, and
     an eight-digit grouped count (24,527,208) is clipped mid-number. */
  .strip-grid, .strip-grid.cols-3, .strip-grid.cols-4 { grid-template-columns: 1fr; }
  /* A 420px panel inset from both edges leaves nothing on a phone — take the
     whole viewport instead, using dvh so the browser chrome can't clip the
     compose row. */
  .ask-panel {
    right: 0;
    bottom: 0;
    top: 0;
    left: 0;
    width: 100vw;
    max-width: none;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
    border-width: 0;
  }
  .ask-launcher { right: 12px; bottom: 12px; }
  /* two columns get cramped below ~480px — stack label over detail */
  .ask-lookups { grid-template-columns: 1fr; gap: 0; }
  .ask-lookup-detail { margin-bottom: 6px; }
  .site-header .inner {
    height: auto;
    min-height: 44px;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 8px 14px;
  }
  .brand { white-space: nowrap; }
  /* Labels wrap as whole items onto a second line, never mid-label, and the
     bar never runs past the viewport. */
  .site-nav { gap: 4px 10px; font-size: 13px; flex-wrap: wrap; }
  .site-nav a { white-space: nowrap; }
  .header-right { gap: 8px; }
  .chart { height: 280px; }
  input[type="search"] { width: 100%; }
}

/* ---------- connect page: the URL block ---------- */

.connect-url {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin: 12px 0 4px;
  max-width: 74ch;
}
.connect-url code {
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  padding: 9px 12px;
  font-size: 13.5px;
}
.connect-url .btn { flex: none; }

@media (max-width: 480px) {
  .connect-url { flex-wrap: wrap; }
}

/* ---------- second-tier navigation ---------- */

/* Sections live in the navy bar; a section with more than one page gets this
   strip under it. Sticky on desktop — the navy bar alone says "Equities" but
   not where else the section goes, and the strip vanishing on scroll made the
   other pages undiscoverable. Phones keep it non-sticky: two fixed bars would
   eat a fifth of the screen. */
.site-subnav {
  background: var(--obs-surface);
  border-bottom: 1px solid var(--obs-border);
}
@media (min-width: 769px) {
  .site-subnav {
    position: sticky;
    top: 52px; /* .site-header .inner height; its border paints over the seam */
    z-index: 40;
  }
}
.site-subnav .inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 20px;
  height: 38px;
  display: flex;
  align-items: center;
  gap: 18px;
  overflow-x: auto;
}
body.page-wide .site-subnav .inner { max-width: 1360px; }
.site-subnav a {
  font-size: 13px;
  color: var(--obs-text-muted);
  white-space: nowrap;
  padding: 3px 1px;
}
.site-subnav a:hover { color: var(--obs-ink); text-decoration: none; }
.site-subnav a[aria-current="page"] {
  color: var(--obs-ink);
  font-weight: 600;
  border-bottom: 2px solid var(--obs-primary);
  margin-bottom: -2px;
}

/* ---------- page tabs (third nav tier) ----------
   The views of one destination — Inflation's headline page and its item
   table. Deliberately in the content column rather than a third sticky bar:
   two bars already cost 90px before any data appears. Same underline idiom as
   the subnav so "current" reads the same way at every tier. */

.page-tabs {
  display: flex;
  align-items: center;
  gap: 20px;
  margin: 10px 0 0;
  border-bottom: 1px solid var(--obs-border);
  /* Sideways scroll only: the -1px underline overlap below would otherwise
     open a vertical scrollbar inside the strip. */
  overflow-x: auto;
  overflow-y: hidden;
}
.page-tabs a {
  font-size: 14px;
  color: var(--obs-text-muted);
  white-space: nowrap;
  padding: 6px 1px 7px;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.page-tabs a:hover { color: var(--obs-ink); text-decoration: none; }
.page-tabs a[aria-current="page"] {
  color: var(--obs-ink);
  font-weight: 600;
  border-bottom-color: var(--obs-primary);
}

/* ---------- contents row (rendered by nav.js from the page's h2s) ---------- */

/* A tinted strip with one outlined chip per section: readable at a glance,
   and the chip for the section in view turns navy as the page scrolls. */
.page-toc {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 8px;
  margin: 12px 0 0;
  padding: 10px 14px;
  background: var(--obs-surface-subtle);
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  font-size: 13px;
}
.page-toc-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--obs-ink);
  margin-right: 6px;
}
.page-toc a {
  color: var(--obs-ink);
  background: var(--obs-surface);
  border: 1px solid var(--obs-border);
  border-radius: 3px;
  padding: 4px 10px;
  white-space: nowrap;
  transition: border-color .15s ease, color .15s ease;
}
.page-toc a:hover { border-color: var(--obs-primary); color: var(--obs-primary); text-decoration: none; }
.page-toc a[aria-current="true"] { border-color: var(--obs-primary); color: var(--obs-primary); font-weight: 600; }
.page-tabs + .page-toc { margin-top: 12px; }
/* Pinned under the sticky header stack on wider screens; --obs-stack is
   measured by nav.js. On a phone it scrolls away: it would take a third of
   the screen if it stuck. */
@media (min-width: 769px) {
  .page-toc { position: sticky; top: var(--obs-stack, 52px); z-index: 30; }
}
@media (max-width: 560px) {
  .page-toc { padding: 8px 10px; gap: 6px; font-size: 12.5px; }
  .page-toc a { padding: 3px 8px; }
}

/* ---------- landing: product list ---------- */

.prod-list { list-style: none; margin: 0; padding: 0; }
.prod {
  padding: 18px 0;
  border-bottom: 1px solid var(--obs-border);
}
.prod:last-child { border-bottom: none; }

.prod-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; }
.prod-name { font-size: 16px; font-weight: 700; color: var(--obs-ink); }
a.prod-name:hover { color: var(--obs-primary); text-decoration: underline; }

/* Outline only — a filled chip is the house's tell for a template. */
.status {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 2px 7px;
  border: 1px solid currentColor;
  border-radius: 3px;
  white-space: nowrap;
}
.status-live { color: var(--obs-trust-official); }
.status-progress { color: var(--obs-primary); }
.status-planned { color: var(--obs-text-muted); }

.prod-desc {
  margin: 6px 0 0;
  max-width: 74ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--obs-text-muted);
}

/* Figures share the strip's cell language, sized down: this is a directory
   entry, not the product page's headline. */
.prod-stats {
  margin-top: 14px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 720px;
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  overflow: hidden;
}
.prod-stat {
  padding: 10px 14px 12px;
  min-width: 0;
  border-right: 1px solid var(--obs-border);
}
.prod-stat:last-child { border-right: none; }
.prod-stat-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--obs-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.prod-stat-value {
  margin-top: 6px;
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.5px;
  color: var(--obs-ink);
  font-variant-numeric: tabular-nums;
}
.prod-stat-note { margin-top: 5px; font-size: 11.5px; color: var(--obs-text-faint); }

.prod-foot { margin: 8px 0 0; font-size: 12px; color: var(--obs-text-faint); }
.prod-foot a { color: inherit; text-decoration: underline; }

.prod-links { margin: 12px 0 0; display: flex; flex-wrap: wrap; gap: 16px; font-size: 13.5px; }

.build-list { margin: 12px 0 0 20px; max-width: 74ch; font-size: 14px; line-height: 1.6; }
.build-list li { margin: 7px 0; color: var(--obs-text-muted); }
.build-list b { color: var(--obs-ink); font-weight: 600; }

@media (max-width: 700px) {
  .prod-stats { grid-template-columns: 1fr; }
  .prod-stat { border-right: none; border-bottom: 1px solid var(--obs-border); }
  .prod-stat:last-child { border-bottom: none; }
}

/* ---------- landing: dataset directory tables ---------- */

/* The description column carries a sentence, so it wraps; the reading and
   as-of are short and never wrap. On a phone the description goes — name,
   reading and as-of fit 390px without a sideways scroll. */
.dir td.col-desc, .dir th.col-desc { white-space: normal; }
.dir td.col-desc { max-width: 46ch; color: var(--obs-text-muted); }
.dir td.col-name { white-space: nowrap; }
.dir td.col-name a { font-weight: 600; }
.dir td.col-asof { white-space: nowrap; color: var(--obs-text-muted); }
.dir .reading-note { color: var(--obs-text-muted); font-weight: 400; }
@media (max-width: 700px) {
  .dir td.col-desc, .dir th.col-desc { display: none; }
}
/* On a phone the qualifier drops under its value so the as-of column stays
   on screen instead of forcing a sideways scroll. */
@media (max-width: 560px) {
  .dir .reading-note { display: block; font-size: 11px; white-space: normal; max-width: 20ch; margin-left: auto; }
  .dir td.col-asof { white-space: normal; }
}
.dir td.col-cov { white-space: normal; max-width: 30ch; color: var(--obs-text-muted); font-size: 12.5px; }
/* Below 900px the coverage column goes and the reading's qualifier drops
   under its value, so the content column keeps a readable measure instead of
   being squeezed to a word a line by two no-wrap columns. */
@media (max-width: 900px) {
  .dir td.col-cov, .dir th.col-cov { display: none; }
  .dir td.col-desc { min-width: 22ch; }
  .dir .reading-note { display: block; font-size: 11px; }
  .dir td.col-asof { white-space: normal; }
}
.dir-foot { margin: 8px 0 0; font-size: 12px; color: var(--obs-text-faint); }
.dir-foot a { color: inherit; text-decoration: underline; }

/* A band's qualifier may be the section's entry link; it inherits the band's
   muted ink so it reads as part of the band, not a blue link on navy. */
.h2-note a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.h2-note a:hover { color: var(--obs-band-ink); }

/* ---------- landing: access list ---------- */

/* Label → value rows for the three ways in. A definition list, not a table:
   each value is a sentence. */
.access-list { margin: 0; max-width: 74ch; font-size: 14px; line-height: 1.55; }
.access-list > div {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  min-width: 0;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px solid var(--obs-border);
}
.access-list > div:last-child { border-bottom: none; }
.access-list dt { font-weight: 600; color: var(--obs-ink); }
.access-list dd { margin: 0; min-width: 0; color: var(--obs-text-muted); }
.access-list dd .connect-url { margin: 0; }
@media (max-width: 480px) {
  .access-list > div { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* ---------- section overview panels (macro.html / equities.html) ---------- */

/* One bordered panel per dataset: its latest readings, a small chart where
   the data is a time series, and the page it opens. The lead panel spans the
   row — an overview ranks its datasets rather than boxing them equally. */
.ov-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 12px; }
.ov-panel {
  min-width: 0;
  border: 1px solid var(--obs-border);
  border-radius: 4px;
  background: var(--obs-surface);
  padding: 14px 16px 10px;
}
.ov-panel.span-2 { grid-column: 1 / -1; }
.ov-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.ov-title { font-size: 15px; font-weight: 700; color: var(--obs-ink); }
a.ov-title:hover { color: var(--obs-primary); text-decoration: underline; }
.ov-asof { margin-left: auto; font-size: 11.5px; color: var(--obs-text-faint); white-space: nowrap; }
.ov-readings { display: flex; flex-wrap: wrap; gap: 10px 32px; margin-top: 12px; }
.ov-reading { min-width: 0; }
.ov-reading-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--obs-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ov-reading-value {
  margin-top: 4px;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.5px;
  color: var(--obs-ink);
}
.ov-reading-value .unit {
  font-size: 14px;
  font-weight: 600;
  color: var(--obs-text-muted);
  margin-left: 2px;
  letter-spacing: normal;
}
.ov-reading-note { margin-top: 3px; font-size: 11.5px; color: var(--obs-text-faint); }
.ov-chart { width: 100%; height: 250px; margin-top: 10px; }
.ov-panel.span-2 .ov-chart { height: 330px; }
.ov-foot { display: flex; align-items: baseline; gap: 4px 16px; flex-wrap: wrap; margin-top: 4px; }
.ov-foot .source-line { flex: 1 1 auto; min-width: 16ch; margin-top: 0; }
.ov-dls { display: inline-flex; gap: 14px; white-space: nowrap; }
.ov-dl { font-size: 11px; white-space: nowrap; }
@media (max-width: 840px) {
  .ov-grid { grid-template-columns: 1fr; }
  .ov-panel.span-2 .ov-chart { height: 260px; }
}

/* ======================================================================
   Home page (index.html). Everything below is scoped to body.page-home or
   to a .home-* / .asst-* / .hero* class, so no other page picks it up.
   Motion is CSS; home.js only adds class names on a timer.
   ====================================================================== */

/* The theme toggle keeps its markup from nav.js; on the home page it is an
   icon, because the status line it sat beside now lives in the hero. */
body.page-home .header-asof { display: none; }
body.page-home .theme-toggle {
  font-size: 0; width: 30px; height: 26px; padding: 0; border: none;
  background-color: var(--obs-header-text);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E") center / 18px 18px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E") center / 18px 18px no-repeat;
}
body.page-home .theme-toggle:hover { background-color: var(--obs-header-ink); }
body.page-home main { padding: 0; }
body.page-home .container { max-width: 1240px; margin: 0 auto; padding: 0 20px; }
body.page-home .muted { color: var(--obs-text-muted); }
body.page-home h2 { margin-top: 40px; }

/* ---------- entrance motion: one orchestrated rise on load ---------- */
@keyframes home-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* Any page may opt in with body.page-anim; the home page is one of them. */
body.page-home .r, body.page-anim .r { animation: home-rise .7s cubic-bezier(.2,.7,.2,1) both; }
body.page-home .d1, body.page-anim .d1 { animation-delay: .05s } body.page-home .d2, body.page-anim .d2 { animation-delay: .18s }
body.page-home .d3, body.page-anim .d3 { animation-delay: .32s } body.page-home .d4, body.page-anim .d4 { animation-delay: .46s }
body.page-home .d5, body.page-anim .d5 { animation-delay: .30s } body.page-home .d6, body.page-anim .d6 { animation-delay: .44s }
body.page-home .d7, body.page-anim .d7 { animation-delay: .58s }

/* ---------- ticker ---------- */
.home-ticker { background: var(--obs-surface-subtle); border-bottom: 1px solid var(--obs-border); height: 34px; overflow: hidden; white-space: nowrap; display: flex; align-items: center; }
.home-ticker-track { display: inline-flex; width: max-content; animation: home-tick 60s linear infinite; }
.home-ticker:hover .home-ticker-track { animation-play-state: paused; }
@keyframes home-tick { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.home-tick { display: inline-flex; align-items: baseline; gap: 8px; padding: 0 22px; border-right: 1px solid var(--obs-border); font-size: 12.5px; }
.home-tick-label { color: var(--obs-text-muted); }
.home-tick-value { font-weight: 600; color: var(--obs-ink); }
.home-tick-note { color: var(--obs-text-faint); font-size: 11px; }

/* ---------- hero ---------- */
.hero { position: relative; height: 560px; overflow: hidden; background: var(--obs-ink); }
.hero-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transform-origin: 60% 40%;
  animation: hero-slide 36s ease-in-out infinite, hero-drift 18s ease-in-out infinite alternate; }
.hero-photo.k1 { animation-delay: 0s, 0s } .hero-photo.k2 { animation-delay: 9s, 9s }
.hero-photo.k3 { animation-delay: 18s, 18s } .hero-photo.k4 { animation-delay: 27s, 27s }
@keyframes hero-slide { 0% { opacity: 0; } 7% { opacity: 1; } 26% { opacity: 1; } 33% { opacity: 0; } 100% { opacity: 0; } }
@keyframes hero-drift { from { transform: scale(1); } to { transform: scale(1.07) translate(-1%, -1%); } }
.hero-trace { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-trace path { stroke: var(--obs-series-2); }
.hero-trace path.is-drawn { stroke-dasharray: 1; stroke-dashoffset: 1; animation: hero-trace 13s cubic-bezier(.3,.6,.2,1) .8s infinite; }
@keyframes hero-trace { 0% { stroke-dashoffset: 1; opacity: 1; } 30% { stroke-dashoffset: 0; } 82% { stroke-dashoffset: 0; opacity: 1; } 90% { opacity: 0; } 100% { stroke-dashoffset: 1; opacity: 0; } }
.hero-inner { position: relative; height: 100%; display: flex; align-items: center; }
.hero-panel { display: flex; flex-direction: column; gap: 18px; max-width: 640px; padding: 32px 36px; border-radius: 4px;
  background: color-mix(in srgb, var(--obs-surface) 90%, transparent); }
.hero-status { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--obs-primary); }
.hero-title { font-size: 42px; font-weight: 700; line-height: 1.1; letter-spacing: -0.6px; color: var(--obs-ink); text-wrap: balance; margin: 0; }
.hero-sub { font-size: 16.5px; line-height: 1.5; color: var(--obs-text); max-width: 46ch; margin: 0; }
.hero-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 2px; }
.btn-lg { font-size: 14px; font-weight: 600; padding: 9px 18px; }
a.btn, a.btn:hover { text-decoration: none; }
.hero-legend { position: absolute; left: 0; right: 0; bottom: 12px; font-size: 11px; }
.chip { display: inline-block; background: color-mix(in srgb, var(--obs-surface) 85%, transparent); color: var(--obs-text); padding: 3px 8px; border-radius: 3px; }
.chip::before { content: ""; display: inline-block; width: 12px; height: 2px; background: var(--obs-series-2); vertical-align: middle; margin-right: 6px; }
.live-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--obs-trust-official); margin-right: 7px; vertical-align: middle; animation: home-pulse 1.8s ease-in-out infinite; }
.live-dot.is-stale { background: var(--obs-trust-stale); }
@keyframes home-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

/* ---------- coverage numbers ---------- */
.home-numbers { background: var(--obs-surface-subtle); border-bottom: 1px solid var(--obs-border); }
body.page-home .home-numbers-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; padding: 40px 20px 36px; }
.home-number { border-left: 3px solid var(--obs-primary); padding-left: 14px; }
.home-number-value { font-size: 44px; font-weight: 700; color: var(--obs-ink); line-height: 1; letter-spacing: -1.2px; }
.home-number-label { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--obs-text-muted); margin-top: 8px; }

/* ---------- entry points ---------- */
.home-entries { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; margin-top: 44px; }
/* Every entry is the same height and its link sits on the same baseline,
   whatever the sub-line says; a sub-line that would wrap is cut instead. */
.home-entry { display: flex; flex-direction: column; gap: 6px; min-height: 108px; padding: 16px 0 4px; border-top: 3px solid var(--obs-primary); color: inherit; transition: border-color .18s ease, transform .18s ease; }
.home-entry:hover { border-top-color: var(--obs-primary-dark); transform: translateY(-3px); text-decoration: none; }
.home-entry:hover .home-entry-open { text-decoration: underline; }
.home-entry-name { font-size: 19px; font-weight: 700; color: var(--obs-ink); letter-spacing: -0.2px; }
.home-entry-sub { font-size: 13px; color: var(--obs-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-entry-open { font-size: 13px; font-weight: 600; color: var(--obs-primary); margin-top: auto; padding-top: 6px; }

/* ---------- the assistant ---------- */
.asst { position: relative; min-height: 520px; }
.asst-scn { display: none; grid-template-columns: minmax(0, 1fr) 640px; gap: 24px; align-items: stretch; }
.asst-scn.is-active { display: grid; }
.asst-chat, .asst-result { border: 1px solid var(--obs-border); border-radius: 4px; background: var(--obs-surface); padding: 16px 18px; }
.asst-chat { display: flex; flex-direction: column; gap: 14px; }
.asst-head { display: flex; justify-content: space-between; align-items: baseline; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--obs-text-muted); }
.asst-head .muted { font-weight: 400; letter-spacing: 0; text-transform: none; }
.asst-q-row { display: flex; justify-content: flex-end; }
.asst-q { max-width: 92%; background: var(--obs-primary); color: var(--obs-header-ink); border-radius: 4px; padding: 11px 14px; font-size: 15px; line-height: 1.5; }
.asst-q .w { opacity: 0; transition: opacity .25s linear; transition-delay: calc(var(--i) * 110ms); }
.s-type .asst-q .w { opacity: 1; }
.asst-cur { display: inline-block; width: 2px; height: 1em; background: var(--obs-header-ink); vertical-align: text-bottom; margin-left: 2px; opacity: 0; }
.s-type .asst-cur { opacity: 1; animation: home-blink .9s steps(1) infinite; }
.s-status .asst-cur { opacity: 0; animation: none; }
@keyframes home-blink { 50% { visibility: hidden; } }
.asst-status { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--obs-text-muted); opacity: 0; transition: opacity .3s ease; }
.s-status .asst-status { opacity: 1; }
.s-answer .asst-status { opacity: 0; }
.asst-dots i { display: inline-block; width: 4px; height: 4px; border-radius: 50%; background: var(--obs-text-muted); margin-right: 3px; animation: home-dot 1.2s ease-in-out infinite; }
.asst-dots i:nth-child(2) { animation-delay: .2s } .asst-dots i:nth-child(3) { animation-delay: .4s }
@keyframes home-dot { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
.asst-tools { display: flex; flex-direction: column; gap: 6px; }
.asst-tool { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 8px 10px; border: 1px solid var(--obs-border); border-radius: 3px; background: var(--obs-surface-subtle); opacity: 0; transform: translateY(6px); transition: opacity .35s ease, transform .35s ease; }
.s-tool1 .asst-tool.t1, .s-tool2 .asst-tool.t2 { opacity: 1; transform: none; }
.asst-chk { color: var(--obs-trust-official); opacity: 0; transition: opacity .25s ease; }
.asst-tool-out { font-size: 11.5px; color: var(--obs-text-muted); white-space: nowrap; opacity: 0; transition: opacity .25s ease; }
.s-chk1 .c1, .s-chk2 .c2 { opacity: 1; }
.asst-mono { font-family: "IBM Plex Mono", "SFMono-Regular", Menlo, Consolas, monospace; font-size: 12.5px; color: var(--obs-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.asst-ans { display: flex; flex-direction: column; gap: 10px; opacity: 0; transform: translateY(6px); transition: opacity .45s ease, transform .45s ease; }
.s-answer .asst-ans { opacity: 1; transform: none; }
.asst-who { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--obs-text-muted); }
.asst-text { font-size: 15px; color: var(--obs-text); line-height: 1.55; }
.asst-text b { color: var(--obs-ink); font-weight: 600; }
.asst-trust { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 11.5px; }
.asst-foot { margin-top: auto; font-size: 11.5px; color: var(--obs-text-faint); }
.asst-result { position: relative; padding: 14px 16px 10px; }
.asst-ph { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--obs-text-faint); font-size: 13px; background: var(--obs-surface); border-radius: 4px; transition: opacity .5s ease; }
.asst-ph svg { color: var(--obs-border); }
.s-answer .asst-ph { opacity: 0; pointer-events: none; }
.asst-tiles { opacity: 0; transform: translateY(6px); transition: opacity .45s ease .2s, transform .45s ease .2s; }
.s-answer .asst-tiles { opacity: 1; transform: none; }
.asst-cap { opacity: 0; transition: opacity .4s ease .3s; }
.s-answer .asst-cap { opacity: 1; }
.asst-body { margin-top: 10px; min-height: 300px; height: 300px; clip-path: inset(0 100% 0 0); transition: clip-path 1.8s cubic-bezier(.3,.6,.2,1) .35s; }
.s-answer .asst-body { clip-path: inset(0 0 0 0); }
.asst-body.is-table { height: auto; min-height: 0; }
.asst-body .table-wrap { overflow: auto; }
.asst-row { opacity: 0; transform: translateY(4px); transition: opacity .35s ease, transform .35s ease; transition-delay: calc(.4s + var(--i) * 140ms); }
.s-answer .asst-row { opacity: 1; transform: none; }
.s-out .asst-chat > *, .s-out .asst-result > * { opacity: 0; transition: opacity .6s ease; }
.badge { font-size: 11px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; border: 1px solid currentColor; border-radius: 3px; padding: 2px 7px; white-space: nowrap; }
.badge-official { color: var(--obs-trust-official); }

/* ---------- section bands ----------
   White alternates with a pale navy tint (the brand blue at ~5% over the
   surface, so it holds in dark mode too). No hairlines: the tint alone marks
   the section, and each band gets room above and below. */
.home-band { padding: 8px 0 56px; }
.home-band.is-tint { background: color-mix(in srgb, var(--obs-primary) 5%, var(--obs-surface)); }
.home-band h2 { margin-top: 24px; }
body.page-home .home-entries { margin-bottom: 48px; }

/* ---------- API sample ---------- */
.home-api { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; align-items: start; }
.home-api-label { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--obs-text-muted); margin-bottom: 10px; }
.home-code { margin: 0; font-family: "IBM Plex Mono", "SFMono-Regular", Menlo, Consolas, monospace; font-size: 12.5px; line-height: 1.6; color: var(--obs-ink); background: var(--obs-surface-subtle); border: 1px solid var(--obs-border); border-radius: 4px; padding: 14px 16px; overflow-x: auto; white-space: pre; }
.home-api-note { font-size: 13.5px; color: var(--obs-text-muted); line-height: 1.55; margin: 10px 0 0; }
.home-api-note code { font-family: "IBM Plex Mono", "SFMono-Regular", Menlo, Consolas, monospace; font-size: 12.5px; color: var(--obs-ink); }

/* ---------- principles, letter, audience ---------- */
.home-principles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; }
.home-principle { display: flex; flex-direction: column; gap: 6px; }
.home-rule { width: 24px; height: 2px; background: var(--obs-primary); }
.home-principle-title { font-size: 15px; font-weight: 700; color: var(--obs-ink); }
.home-principle-text { font-size: 13.5px; line-height: 1.5; color: var(--obs-text-muted); }
.home-letter { display: grid; grid-template-columns: minmax(0, 1fr) 400px; gap: 40px; align-items: start; }
.home-letter.is-single { grid-template-columns: minmax(0, 1fr); }
.home-featured { display: flex; flex-direction: column; gap: 8px; }
.home-featured-kicker { font-size: 12px; color: var(--obs-text-faint); }
.home-featured-title { font-size: 24px; font-weight: 700; line-height: 1.25; color: var(--obs-ink); text-wrap: balance; }
.home-featured-chart { height: 240px; margin-top: 6px; }
.home-featured-foot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; align-items: baseline; }
.home-posts { display: flex; flex-direction: column; }
.home-post { display: flex; flex-direction: column; gap: 3px; padding: 11px 0; border-bottom: 1px solid var(--obs-border); }
.home-post-date { font-size: 11.5px; color: var(--obs-text-faint); }
.home-post-title { font-size: 14px; font-weight: 600; color: var(--obs-ink); line-height: 1.4; }
.home-post-more { padding-top: 12px; font-size: 13px; }
.home-audience { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; }
.home-audience-item { display: flex; flex-direction: column; gap: 6px; border-top: 3px solid var(--obs-primary); padding-top: 14px; }
.home-audience-title { font-size: 17px; font-weight: 700; color: var(--obs-ink); }
.home-audience-lead { font-size: 14px; font-weight: 600; color: var(--obs-text); }
.home-audience-text { font-size: 13.5px; line-height: 1.55; color: var(--obs-text-muted); }
.home-credits { margin-top: 8px; color: var(--obs-text-faint); }
.home-credits a { color: inherit; text-decoration: underline; }

/* ---------- responsive ---------- */
@media (max-width: 1100px) {
  .asst-scn { grid-template-columns: minmax(0, 1fr); }
  .home-entries { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .home-principles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-letter { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px) {
  .hero { height: auto; }
  body.page-home .hero-inner { padding: 40px 20px 72px; }
  .hero-panel { padding: 22px 20px; gap: 14px; }
  .hero-title { font-size: 30px; }
  .hero-sub { font-size: 15px; }
  .hero-legend { bottom: 8px; }
  body.page-home .home-numbers-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; padding: 24px 20px 20px; }
  .home-number-value { font-size: 34px; }
  .home-entries { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; margin-top: 24px; }
  .home-api { grid-template-columns: minmax(0, 1fr); }
  .home-audience { grid-template-columns: minmax(0, 1fr); }
  .asst-body { height: 260px; min-height: 260px; }
  .asst-tool { grid-template-columns: 18px minmax(0, 1fr); }
  .asst-tool-out { display: none; }
}
@media (max-width: 480px) {
  .home-principles { grid-template-columns: minmax(0, 1fr); }
  .home-entry-sub { white-space: normal; }
  .asst-tiles { gap: 8px 20px; }
}
@media (prefers-reduced-motion: reduce) {
  body.page-home .r, body.page-anim .r, .home-ticker-track, .hero-photo, .hero-trace path.is-drawn, .live-dot, .asst-dots i { animation: none !important; }
  .hero-photo.k1 { opacity: 1; }
  .asst-q .w, .asst-tool, .asst-ans, .asst-tiles, .asst-cap, .asst-row, .asst-body { transition: none !important; }
}

