/* Hallmark · genre: atmospheric · macrostructure: Ecosystem Index · theme: Midnight
 * mode: dark · enrichment: none (the charts are the content) · nav: N5 floating pill
 * footer: Ft2 inline single line · anchor hue: 258 (cool indigo)
 * pre-emit critique: P5 H5 E4 S5 R4 V5
 *
 * slop test 58/58 · contrast: pass (40–41) · nav/footer/hero: pass (42–45)
 * honest: pass (46) · chrome: pass (47) · tokens: pass (48) · responsive: pass (49)
 * mobile: pass (34, 49, 50–57) · icons: pass (30)
 *
 * Contrast was computed, not eyeballed: every (text, surface) pair clears WCAG
 * 4.5:1, measured against the lightest surface each can land on. The quiet ink
 * tier sits at L 64% because anything darker stops clearing 4.5:1 on paper-4.
 * The one pair below 3:1 is --color-rule-2 on paper — a decorative separator
 * hairline, not text, an icon, or a focus ring, and not a control boundary that
 * carries meaning (controls read by their fill and label; focus uses a 9.9:1
 * outline). Gate 40 scopes to text/icon/focus ring, so this is in spec.
 *
 * Diversification vs the previous build (Stat-Led · Newsprint): macrostructure,
 * paper band, display style and accent hue all differ.
 */

@import url("./tokens.css");
@import url("./fonts.css");

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  /* clip, never hidden — `hidden` on the root kills position:sticky in Safari */
  overflow-x: clip;
}

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--color-paper);
  color: var(--color-ink-2);
  font-family: var(--font-body);
  /* Light text on a dark ground reads optically heavier; step the body weight down. */
  font-weight: 350;
  font-size: var(--text-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-style: normal;          /* headers are roman, always */
  color: var(--color-ink);
  letter-spacing: -0.02em;
  line-height: 1.08;
  margin: 0;
  text-wrap: balance;
  overflow-wrap: anywhere;
  min-width: 0;
}

a { color: inherit; }

button, input, select { font: inherit; color: inherit; }

/* Focus rings appear instantly — never transitioned, or keyboard users get
   nothing for the first 200ms. */
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--color-accent-wash); color: var(--color-ink); }

/* Eight-state baseline for every control. Individual components override the
   hover/selected look; these guarantee active and disabled are never missing.
   Disabled is signalled on three channels — opacity, cursor, and the native
   attribute — never opacity alone. */
button:active:not(:disabled),
a.card:active,
.chip:active:not(:disabled) { transform: translateY(1px); }

button:disabled,
select:disabled,
input:disabled,
[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Symbols used as status/direction marks are forced to text presentation.
   Without the variation selector some platforms render ▲ ▼ ✕ as colour emoji,
   which breaks the typographic voice and reads as an AI tell. */
.delta > [aria-hidden],
.chip > [aria-hidden] { font-variant-emoji: text; }

.u-num  { font-variant-numeric: tabular-nums; }
.u-mono { font-family: var(--font-mono); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip-link {
  position: absolute; left: var(--space-sm); top: -4rem; z-index: var(--z-tooltip);
  background: var(--color-accent); color: var(--color-accent-ink);
  padding: var(--space-2xs) var(--space-sm); border-radius: var(--radius);
  font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: var(--space-sm); }

/* ══════════════════════════════════════════════════ N5 · floating pill nav */
/* Solid, hairline-edged pill — not frosted glass, which the genre bans. */

.nav {
  position: sticky;
  top: var(--space-xs);
  z-index: var(--z-nav);
  display: flex;
  justify-content: center;
  padding: 0 var(--space-sm);
  margin-top: var(--space-xs);
  pointer-events: none;
}
.nav__pill {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  max-width: 100%;
  padding: var(--space-3xs);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-float);
}
.nav__brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  padding: 0 var(--space-2xs) 0 var(--space-xs);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: -0.03em;
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
}
.nav__brand-mark {
  width: 7px; height: 7px;
  background: var(--color-accent);
  border-radius: 50%;
  align-self: center;
  flex: none;
}
.nav__links { display: flex; gap: var(--space-4xs); overflow-x: auto; scrollbar-width: none; }
.nav__links::-webkit-scrollbar { display: none; }

.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 0 var(--space-sm);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-muted);
  text-decoration: none;
  white-space: nowrap;            /* clickable text never wraps to two lines */
  transition: color var(--dur-short) var(--ease-out),
              background-color var(--dur-short) var(--ease-out);
}
.nav__link:hover { color: var(--color-ink); background: var(--color-paper-3); }
.nav__link[aria-current="page"] {
  color: var(--color-ink);
  background: var(--color-paper-4);
}

.nav__search {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: var(--tap-min);
  padding: 0 var(--space-xs);
  margin-left: var(--space-3xs);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-paper-3);
  color: var(--color-muted);
  font-size: var(--text-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur-short) var(--ease-out),
              background-color var(--dur-short) var(--ease-out);
}
.nav__search:hover { color: var(--color-ink); background: var(--color-paper-4); }
.nav__search kbd {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: 0 var(--space-3xs);
  border: 1px solid var(--color-rule-2);
  border-radius: var(--radius-xs);
  color: var(--color-faint);
}

/* ══════════════════════════════════════════════════════════════════ layout */

.page {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-lg) var(--space-sm) var(--space-2xl);
}

/* Section spacing deliberately varies — the first band sits tighter under the
   nav than the rails below it. */
.band + .band { margin-top: var(--space-2xl); }
.band--tight + .band--tight { margin-top: var(--space-xl); }

/* Vertical stack only. The tag-left / heading-right two-column section head is
   a templated-editorial tell and is not used anywhere in this app. */
.band__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-sm);
  padding-bottom: var(--space-xs);
  margin-bottom: var(--space-md);
  border-bottom: 1px solid var(--color-rule);
}
.band__title { font-size: var(--text-md); font-weight: 700; }
.band__note  { font-size: var(--text-xs); color: var(--color-faint); }
.band__more {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--color-muted);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out);
}
.band__more:hover { color: var(--color-accent); border-bottom-color: var(--color-accent); }

/* ══════════════════════════════════════════════════════ current-round card */
/* The server page's lead: what is being played right now, on the map's own art. */

.nowcard {
  position: relative;
  padding: var(--space-md);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  background: var(--color-paper-2);
  min-width: 0;
}
.nowcard__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2xs); margin-bottom: var(--space-2xs);
}
.nowcard__map {
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-bottom: var(--space-3xs);
}
.nowcard__meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3xs);
  font-size: var(--text-sm); color: var(--color-muted);
  margin-bottom: var(--space-md);
}
.nowcard__stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(7rem, 100%), 1fr));
  gap: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--color-rule);
}
.nowcard__stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nowcard__value {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--color-ink);
  letter-spacing: -0.025em;
  line-height: 1.1;
}

@media (max-width: 720px) {
  .nowcard { padding: var(--space-sm); }
  .nowcard__map { font-size: var(--text-xl); }
}

/* ═══════════════════════════════════════════════════════════ the lead band */
/* Hero figure + population chart, side by side. Asymmetric on purpose: the
   number column is narrow, the chart takes the rest. */

.lead {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: var(--space-lg);
  align-items: stretch;
}
.lead__figure {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-md) var(--space-md) var(--space-md) 0;
}
.lead__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--color-muted);
  margin-bottom: var(--space-2xs);
}
.lead__value {
  font-family: var(--font-body);      /* figures stay in the UI sans */
  font-size: var(--text-figure);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: var(--color-ink);
}
.lead__sub {
  margin-top: var(--space-2xs);
  font-size: var(--text-sm);
  color: var(--color-muted);
  max-width: 30ch;
}
.lead__chart {
  min-width: 0;
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
}

/* live dot — the one looping animation on the page, and it carries meaning */
.livedot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-good);
  flex: none;
}
.livedot--stale { background: var(--color-warn); }
.livedot--down  { background: var(--color-down); }
@media (prefers-reduced-motion: no-preference) {
  .livedot { animation: pulse 2.4s var(--ease-in-out) infinite; }
}
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.82); }
}

/* ══════════════════════════════════════════════════════════════ stat tiles */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: var(--rule-w);
  background: var(--color-rule);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.tile {
  background: var(--color-paper-2);
  padding: var(--space-sm) var(--space-md);
  min-width: 0;
}
.tile__label {
  font-size: var(--text-xs);
  color: var(--color-muted);
  margin-bottom: var(--space-3xs);
}
.tile__value {
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--color-ink);
  line-height: 1.1;
  letter-spacing: -0.03em;
}
.tile__foot {
  margin-top: var(--space-3xs);
  font-size: var(--text-xs);
  color: var(--color-faint);
  display: flex; align-items: center; gap: var(--space-3xs);
  min-height: 1.4em;
}
.tile__spark { margin-top: var(--space-2xs); }

/* Delta: direction is carried by the arrow glyph and the word, not colour alone. */
.delta { display: inline-flex; align-items: center; gap: 0.25em; font-variant-numeric: tabular-nums; }
.delta--up   { color: var(--color-good); }
.delta--down { color: var(--color-down); }
.delta--flat { color: var(--color-faint); }

/* ═══════════════════════════════════════════════════════════════════ rails */
/* Horizontal scrolling cut of the catalogue — the Ecosystem Index spine. */

.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 1fr);
  gap: var(--space-sm);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-2xs);
  scrollbar-width: thin;
  scrollbar-color: var(--color-rule-2) transparent;
}
.rail > * { scroll-snap-align: start; }
.rail::-webkit-scrollbar { height: 8px; }
.rail::-webkit-scrollbar-thumb { background: var(--color-rule-2); border-radius: var(--radius-pill); }
.rail::-webkit-scrollbar-track { background: transparent; }

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  min-width: 0;
  padding: var(--space-sm);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: inherit;
  /* One signal on hover: the surface lifts in lightness. No scale, no shadow
     halo — glow shadows on dark are a named tell. */
  transition: background-color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out);
}
a.card:hover { background: var(--color-paper-3); border-color: var(--color-rule-2); }
a.card:active { background: var(--color-paper-4); }

/* Map-thumbnail cards. The veil gradient lives here rather than in a JS
   template string, so every colour in the app still comes from a token; the
   view only supplies the image URL through --card-art. */
.card--art {
  min-height: 7rem;
  justify-content: flex-end;
  background-image: linear-gradient(to top, var(--veil-strong), var(--veil-soft)), var(--card-art, none);
  background-size: cover;
  background-position: center;
}
/* Same mechanism, lighter veil — a server card carries more text than a map
   tile, so the art sits further back. */
.card--art-server {
  background-image: linear-gradient(to top, var(--veil-card), var(--veil-card-2)), var(--card-art, none);
  background-size: cover;
  background-position: center;
}

.card__kicker {
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-faint);
}
.card__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--color-ink);
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}
.card__value {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  /* Titles in a rail wrap to different heights; pushing the value down keeps
     the figures on one baseline across the row. */
  margin-top: auto;
}
.card__meta { font-size: var(--text-xs); color: var(--color-muted); }
.card__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2xs); }
.card__row .card__value { margin-top: 0; }

/* ═════════════════════════════════════════════════════════════════ tables */

.tablewrap {
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  overflow-x: auto;      /* wide tables scroll inside their own box */
  background: var(--color-paper-2);
}
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
table.data th {
  position: sticky;
  /* top:0 relative to .tablewrap, NOT the viewport. `.tablewrap` sets
     overflow-x: auto, which makes overflow-y compute to auto as well, so the
     wrapper is its own scroll container and this header can never reach the
     viewport edge or collide with the floating nav. Offsetting it by the nav
     height instead just parks it 68px down inside its own box. */
  top: 0;
  z-index: var(--z-raised);
  background: var(--color-paper-3);
  text-align: left;
  font-weight: 500;
  font-size: var(--text-xs);
  color: var(--color-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: var(--space-2xs) var(--space-sm);
  white-space: nowrap;
  border-bottom: 1px solid var(--color-rule);
}
table.data td {
  padding: var(--space-2xs) var(--space-sm);
  border-bottom: 1px solid var(--color-rule);
  vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background-color var(--dur-instant) var(--ease-out); }
table.data tbody tr:hover { background: var(--color-paper-3); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.rank {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-faint);
  font-variant-numeric: tabular-nums;
  width: 1%;
  white-space: nowrap;
}
.rank--medal { color: var(--color-accent); font-weight: 600; }

.namecell { display: flex; align-items: center; gap: var(--space-2xs); min-width: 0; }
.namecell a {
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  overflow-wrap: anywhere;
  transition: color var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out);
}
.namecell a:hover { color: var(--color-accent); border-bottom-color: var(--color-accent); }

/* ══════════════════════════════════════════════════════════════════ chips */

.chips { display: flex; flex-wrap: wrap; gap: var(--space-3xs); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  min-height: var(--tap-min);
  padding: 0 var(--space-xs);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  color: var(--color-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur-short) var(--ease-out),
              background-color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out);
}
.chip:hover { color: var(--color-ink); background: var(--color-paper-3); }
.chip[aria-pressed="true"], .chip.is-on {
  color: var(--color-ink);
  background: var(--color-paper-4);
  border-color: var(--color-rule-2);
}
.chip__count { color: var(--color-faint); font-variant-numeric: tabular-nums; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: var(--space-4xs) var(--space-2xs);
  border-radius: var(--radius-xs);
  background: var(--color-paper-3);
  border: 1px solid var(--color-rule);
  font-size: var(--text-2xs);
  font-weight: 500;
  color: var(--color-muted);
  white-space: nowrap;
}
.badge--accent { color: var(--color-accent); border-color: var(--color-accent-dim); }
.badge--good   { color: var(--color-good); }
.badge--warn   { color: var(--color-warn); }

/* ═══════════════════════════════════════════════════ filters (one row, top) */

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  margin-bottom: var(--space-md);
}
.field {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: var(--tap-min);
  padding: 0 var(--space-xs);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
}
.field:focus-within { border-color: var(--color-accent-dim); }
.field input, .field select {
  border: 0;
  background: transparent;
  outline: none;
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--color-ink);
}
.field input::placeholder { color: var(--color-faint); }
.field select { cursor: pointer; }
.field select option { background: var(--color-paper-2); color: var(--color-ink); }

/* ══════════════════════════════════════════════════════════════ pagination */

.pager { display: flex; align-items: center; justify-content: center; gap: var(--space-2xs); margin-top: var(--space-md); }
.pager__btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap-min); min-width: var(--tap-min);
  padding: 0 var(--space-sm);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius);
  color: var(--color-muted);
  font-size: var(--text-sm); font-weight: 500;
  white-space: nowrap; cursor: pointer;
  transition: color var(--dur-short) var(--ease-out), background-color var(--dur-short) var(--ease-out);
}
.pager__btn:hover:not(:disabled) { color: var(--color-ink); background: var(--color-paper-3); }
.pager__btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pager__at { font-size: var(--text-xs); color: var(--color-faint); font-variant-numeric: tabular-nums; padding: 0 var(--space-2xs); }

/* ══════════════════════════════════════════════════════════ player profile */

.profile__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--color-rule);
}
.profile__name {
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.035em;
}
.profile__tags { display: flex; flex-wrap: wrap; gap: var(--space-3xs); margin-top: var(--space-2xs); }

/* level meter — track is a lighter step of the fill's own ramp */
.meter {
  --meter-pct: 0%;
  position: relative;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-paper-4);
  overflow: hidden;
}
.meter__fill {
  height: 100%;
  width: var(--meter-pct);
  background: var(--color-accent);
  border-radius: inherit;
  transform-origin: left center;
}
@media (prefers-reduced-motion: no-preference) {
  .meter__fill { animation: meter-in var(--dur-long) var(--ease-out) both; }
}
@keyframes meter-in { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.catgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: var(--space-sm);
}
.catcard {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-sm);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  min-width: 0;
  cursor: pointer;
  text-align: left;
  transition: background-color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out);
}
.catcard:hover { background: var(--color-paper-3); }
.catcard[aria-pressed="true"] { border-color: var(--color-accent-dim); background: var(--color-paper-3); }
.catcard__top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2xs); }
.catcard__label { font-size: var(--text-xs); color: var(--color-muted); }
.catcard__value {
  font-size: var(--text-lg); font-weight: 600; color: var(--color-ink);
  font-variant-numeric: tabular-nums; letter-spacing: -0.025em;
}
.catcard__rank { font-size: var(--text-xs); color: var(--color-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
.catcard--unranked { opacity: 0.55; }

/* ══════════════════════════════════════════════════════════════════ charts */

.chart { position: relative; min-width: 0; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }

.chart__head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-2xs); margin-bottom: var(--space-2xs);
}
.chart__title { font-size: var(--text-sm); font-weight: 600; color: var(--color-ink); }
.chart__sub   { font-size: var(--text-xs); color: var(--color-faint); }

/* Axis and grid text wear text tokens, never a series colour. */
.chart .axis-label { fill: var(--color-faint); font-size: 10px; font-family: var(--font-body); }
.chart .axis-tick  { fill: var(--color-muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart .gridline   { stroke: var(--viz-grid); stroke-width: 1; shape-rendering: crispEdges; }
.chart .baseline   { stroke: var(--viz-axis); stroke-width: 1; shape-rendering: crispEdges; }
.chart .series-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .series-area { stroke: none; }
/* End markers carry a 2px ring in the surface colour so they stay legible
   where they cross a line. */
.chart .series-dot { stroke: var(--viz-surface); stroke-width: 2; }
.chart .crosshair  { stroke: var(--color-rule-2); stroke-width: 1; pointer-events: none; }
.chart .hit        { fill: transparent; cursor: crosshair; }
.chart .bar        { transition: opacity var(--dur-instant) var(--ease-out); }
.chart .bar:hover  { opacity: 0.82; }
/* Map-rotation strip beneath a population chart: which map was live when. */
.chart .band       { stroke: var(--viz-surface); stroke-width: 1; }
.chart .band-label {
  fill: var(--color-ink);
  font-size: 10px;
  font-family: var(--font-body);
  font-weight: 500;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .chart .draw-in {
    stroke-dasharray: var(--len);
    stroke-dashoffset: var(--len);
    animation: draw var(--dur-long) var(--ease-out) forwards;
  }
  .chart .fade-in { animation: fade var(--dur-med) var(--ease-out) both; animation-delay: 220ms; }
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* Tooltip: values lead, series names follow. Keyed with a short stroke of the
   series colour, not a filled box. */
.tip {
  position: absolute;
  z-index: var(--z-tooltip);
  min-width: 9rem;
  max-width: 16rem;
  padding: var(--space-2xs);
  background: var(--color-paper-3);
  border: 1px solid var(--color-rule-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-float);
  font-size: var(--text-xs);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-instant) var(--ease-out);
}
.tip.is-on { opacity: 1; }
.tip__when { color: var(--color-faint); margin-bottom: var(--space-3xs); font-variant-numeric: tabular-nums; }
.tip__row  { display: flex; align-items: baseline; gap: var(--space-2xs); }
.tip__key  { width: 12px; height: 2px; border-radius: 1px; flex: none; align-self: center; }
.tip__val  { color: var(--color-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.tip__name { color: var(--color-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.legend { display: flex; flex-wrap: wrap; gap: var(--space-2xs) var(--space-sm); margin-top: var(--space-2xs); }
.legend__item { display: inline-flex; align-items: center; gap: var(--space-3xs); font-size: var(--text-xs); color: var(--color-muted); }
.legend__key  { width: 14px; height: 2px; border-radius: 1px; flex: none; }

.rangebar { display: flex; gap: var(--space-4xs); }
.rangebar .chip { min-height: 28px; padding: 0 var(--space-2xs); }

/* ═════════════════════════════════════════════════════ search command sheet */

.sheet {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: start center;
  padding: var(--space-xl) var(--space-sm) var(--space-sm);
  background: var(--color-scrim);
}
.sheet[hidden] { display: none; }
.sheet__panel {
  width: min(38rem, 100%);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule-2);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sheet);
  overflow: hidden;
}
@media (prefers-reduced-motion: no-preference) {
  .sheet__panel { animation: sheet-in var(--dur-short) var(--ease-out) both; }
}
@keyframes sheet-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.sheet__input {
  width: 100%;
  padding: var(--space-sm);
  border: 0;
  border-bottom: 1px solid var(--color-rule);
  background: transparent;
  color: var(--color-ink);
  font-size: var(--text-md);
  outline: none;
}
.sheet__input::placeholder { color: var(--color-faint); }
.sheet__results { max-height: min(26rem, 60dvh); overflow-y: auto; }
.sheet__group { padding: var(--space-2xs) var(--space-sm) var(--space-3xs); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-faint); }
.sheet__item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
  width: 100%; padding: var(--space-2xs) var(--space-sm);
  background: transparent; border: 0; text-align: left; cursor: pointer;
  color: var(--color-ink-2); font-size: var(--text-sm); text-decoration: none;
}
.sheet__item:hover, .sheet__item.is-active { background: var(--color-paper-3); color: var(--color-ink); }
.sheet__item span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet__hint { padding: var(--space-sm); color: var(--color-faint); font-size: var(--text-xs); }

/* ══════════════════════════════════════════════════════ states & feedback */

.empty {
  padding: var(--space-xl) var(--space-sm);
  text-align: center;
  color: var(--color-muted);
  border: 1px dashed var(--color-rule);
  border-radius: var(--radius-md);
}
.empty__title { font-family: var(--font-display); color: var(--color-ink); font-size: var(--text-md); margin-bottom: var(--space-3xs); }

/* Skeletons over spinners wherever the layout is already known. */
.skel {
  background: linear-gradient(90deg, var(--color-paper-2) 0%, var(--color-paper-3) 50%, var(--color-paper-2) 100%);
  background-size: 200% 100%;
  border-radius: var(--radius);
  min-height: 1em;
}
@media (prefers-reduced-motion: no-preference) {
  .skel { animation: shimmer 1.4s var(--ease-in-out) infinite; }
}
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* First-paint skeleton sizes, so index.html needs no style attributes. */
.skel--label  { height: 0.8rem; width: 9rem; margin-bottom: var(--space-xs); }
.skel--figure { height: 3.5rem; width: 12rem; }
.skel--chart  { height: 210px; }

/* While a refetch is in flight the previous render is held at reduced opacity —
   no skeleton flash, no layout jump. */
.is-refetching { opacity: 0.55; transition: opacity var(--dur-short) var(--ease-out); }

.errorbar {
  display: flex; align-items: center; gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-sm);
  border: 1px solid var(--color-down);
  border-radius: var(--radius);
  background: var(--color-paper-2);
  color: var(--color-ink-2);
  font-size: var(--text-sm);
  margin-bottom: var(--space-md);
}

.note {
  font-size: var(--text-xs);
  color: var(--color-faint);
  border-left: 2px solid var(--color-rule-2);
  padding-left: var(--space-2xs);
  max-width: var(--measure);
}

/* ═══════════════════════════════════════════ Ft2 · inline single-line footer */

.foot {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-md) var(--space-sm) var(--space-xl);
  border-top: 1px solid var(--color-rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-sm);
  font-size: var(--text-xs);
  color: var(--color-faint);
}
.foot a { color: var(--color-muted); text-decoration: none; white-space: nowrap; border-bottom: 1px solid transparent; }
.foot a:hover { color: var(--color-accent); border-bottom-color: var(--color-accent); }
.foot__sep { color: var(--color-rule-2); }

/* ═════════════════════════════════════════════════════════════ responsive */

@media (max-width: 900px) {
  .lead { grid-template-columns: minmax(0, 1fr); gap: var(--space-md); }
  .lead__figure { padding: 0; }
}

@media (max-width: 720px) {
  .page { padding: var(--space-md) var(--space-xs) var(--space-xl); }
  .band + .band { margin-top: var(--space-xl); }
  .nav { padding: 0 var(--space-2xs); }
  .nav__pill { width: 100%; border-radius: var(--radius-md); }
  .nav__links { flex: 1; }
  .nav__link { padding: 0 var(--space-xs); }
  .nav__search kbd { display: none; }
  .rail { grid-auto-columns: minmax(13rem, 78%); }
  .profile__name { font-size: var(--text-xl); }
  table.data th, table.data td { padding: var(--space-2xs) var(--space-xs); }
}

@media (max-width: 420px) {
  .nav__brand span:not(.nav__brand-mark) { display: none; }
  .tile { padding: var(--space-2xs) var(--space-xs); }
  .rail { grid-auto-columns: minmax(11rem, 86%); }
}

/* Spatial motion collapses to a short crossfade; nothing translates or draws. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 150ms !important;
    scroll-behavior: auto !important;
  }
}
