/* =========================================================================
   EVERY LAST JOULE — tokens, type and layout
   ========================================================================= */

/* ---------- Theme system fonts (woff2, self-hosted, OFL) ---------- */
/* Schibsted Grotesk and IBM Plex Mono — the brand system's two faces, in both
   modes (2026-09-24). Schibsted Grotesk is display and body (one variable
   file, roman only: nothing on the site sets it in italic); IBM Plex Mono 500
   is tabular figures and labels. Logged in src/fonts/SOURCES.md. */
@font-face { font-family: "Schibsted Grotesk"; src: url("/fonts/SchibstedGrotesk-Variable.woff2") format("woff2"); font-weight: 400 900; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Mono";     src: url("/fonts/IBMPlexMono-Medium.woff2")       format("woff2"); font-weight: 500;     font-style: normal; font-display: swap; }

/* Fraunces and Inter: the paper figure's faces (src/embed/globe.md sets
   both). Nothing else on the site loads them. */
@font-face { font-family: "Fraunces";        src: url("/fonts/Fraunces-Regular.woff2")     format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Fraunces";        src: url("/fonts/Fraunces-SemiBold.woff2")    format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Fraunces";        src: url("/fonts/Fraunces-ExtraBold.woff2")   format("woff2"); font-weight: 800; font-style: normal; font-display: swap; }

@font-face { font-family: "Inter";           src: url("/fonts/Inter-Regular.woff2")        format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Inter";           src: url("/fonts/Inter-Medium.woff2")         format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Inter";           src: url("/fonts/Inter-Bold.woff2")           format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }

/* =========================================================================
   THEME SYSTEM — two modes, light and dark, as data-theme blocks.
   Tokens shared across modes (spacing, radii, type scale, motion) live in :root.
   Per-mode tokens (colour, fonts, weight/letter-spacing baselines) live in
   :root[data-theme="light"] and :root[data-theme="dark"] below. Every colour a
   rule paints comes from a token; tests/style-colour-literals.test.ts fails on
   a colour literal anywhere else in this sheet.
   ========================================================================= */

:root {
  /* ============ TYPE SCALE (theme-invariant) ============ */
  --fs-h1:         44px;
  --fs-h2:         32px;
  --fs-h3:         24px;
  --fs-h4:         20px;
  --fs-body-lg:    18px;
  --fs-body:       16px;
  --fs-body-sm:    14px;
  --fs-caption:    12px;
  --fs-micro:      11px;

  --lh-tight: 1.02;
  --lh-heading: 1.15;
  --lh-body: 1.55;
  --lh-ui: 1.3;

  --ls-tight: -0.02em;
  --ls-display: -0.015em;
  --ls-normal: 0;
  --ls-caps: 0.12em;

  /* ============ ACCENT (theme-invariant) ============ */
  /* Bitcoin orange. Now only the base of --quality-warning below. */
  --amber-500: #f7931a;
  /* Stale-feed (degraded) alarm ring on globe pillars + the legend swatch.
     Amber reads as "caution" on the dark ground (8.8:1). It is 2.0:1 on
     paper, under the 3:1 a ring needs, so the light block overrides it. */
  --quality-warning: var(--amber-500);

  /* ============ SPACING ============ */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;

  /* ============ RADII ============ */
  --r-none: 0;
  --r-sm: 4px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-xl: 20px;
  --r-pill: 999px;

  /* ============ SHADOWS ============ */
  --shadow-xs: 0 1px 2px rgba(11, 12, 13, 0.04);
  --shadow-sm: 0 2px 6px rgba(11, 12, 13, 0.06);
  --shadow-md: 0 8px 20px rgba(11, 12, 13, 0.08);
  --shadow-lg: 0 20px 40px rgba(11, 12, 13, 0.10);
  --shadow-brand: 0 10px 30px rgba(var(--brand-rgb), 0.25);
  --shadow-focus: 0 0 0 3px rgba(var(--brand-rgb), 0.35);

  /* ============ MOTION ============ */
  --dur-fast: 120ms;
  --dur-base: 200ms;
  --dur-slow: 320ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);

  /* ============ LAYOUT ============ */
  --container-max: 1200px;
  --container-wide: 1400px;

  /* ============ FONT WEIGHTS (semantic, mapped per theme) ============ */
  --fw-thin: 100;
  --fw-xlight: 200;
  --fw-light: 300;
  --fw-book: 400;
  --fw-medium: 500;
  --fw-bold: 700;
  --fw-black: 800;
  --fw-ultra: 900;
}

/* =========================================================================
   LIGHT (Almanac layout, Daylight palette) and DARK (Horizon layout,
   Nightgrid palette) — the site's two modes.

   data-theme="light" | "dark" on <html> selects the palette. The boot script
   in observablehq.config.ts (src/lib/theme-boot.ts) sets it before this sheet
   loads: a stored choice wins (a value the old theme picker stored maps to
   dark), and a first visit gets dark, whatever the OS prefers.

   Token NAMES are the ones every rule already reads; tokens the redesign adds
   are marked NEW. The layouts are the light/dark redesign's (2026-09-23). The
   colours are the Nightgrid + Daylight pair and the type is the brand system's
   Schibsted Grotesk and IBM Plex Mono (2026-09-24). The WCAG pairs are pinned
   by tests/theme-contrast.test.ts, which computes them from these values.
   ========================================================================= */

:root {
  /* NEW, theme-invariant */
  --ls-label: 0.08em;                 /* mono uppercase labels, both modes */
  --fs-label: 11px;
  /* --quality-warning (#f7931a via --amber-500) stays in the base :root; light overrides it. */
}

/* ------------------------------------------------------------------ LIGHT · Almanac layout, Daylight palette */
:root[data-theme="light"] {
  color-scheme: light;

  /* brand: a deep gold that carries small text on paper (5.2:1). Full gold
     (#ffd05a) is 1.3:1 on paper, so it never appears as text or a rule here. */
  --brand:               #8a5a00;
  --brand-strong:        #6e4700;
  --brand-subtle:        rgba(138, 90, 0, 0.10);
  --brand-rgb:           138, 90, 0;
  --brand-on:            #fffbf0;
  --brand-text:          var(--brand);  /* NEW: accent that has to carry small text (links, eyebrows) */

  /* surfaces: warm paper; hierarchy still comes from rules, not fills */
  --surface-bg-1:        #ece2c8;       /* wells: slider track, skeletons */
  --surface-bg-2:        #fffbf0;       /* a lighter sheet: Framework's alt background */
  --surface-bg-3:        #f6f0e0;       /* page (html, body) */
  --surface-raised:      #fffdf8;       /* cards and tooltips: paper + 1px ink border */
  --surface-panel:       rgba(246, 240, 224, 0.92);   /* NEW: sticky bars over content */
  --hairline:            rgba(11, 18, 29, 0.16);
  --hairline-strong:     #0b121d;

  /* foreground: navy ink, the dark mode's ground. Muted copy is 7.6:1. */
  --ink:                 #0b121d;
  --ink-muted:           #484c50;
  --ink-soft:            rgba(11, 18, 29, 0.62);      /* disabled and tertiary only; 5.1:1 */

  --data-renewable:      #08778d;
  --data-renewable-tip:  #08778d;

  /* fuels: gold, cyan, violet - the same hue families as dark, darkened for
     paper. Violet hydro keeps wind and hydro apart under deuteranopia. */
  --fuel-solar:          #b07800;
  --fuel-wind:           #08778d;
  --fuel-hydro:          #7a4fd0;
  --fuel-solar-tip:      #b07800;       /* NEW (tips = base in light) */
  --fuel-wind-tip:       #08778d;       /* NEW */
  --fuel-hydro-tip:      #7a4fd0;       /* NEW */

  /* engraved globe. Existing globe tokens are mapped so stragglers still read. */
  --globe-ink-rgb:       11, 18, 29;    /* NEW: line screen, stipple, coastline, limb */
  --globe-paper:         #f6f0e0;       /* NEW: land knock-out and needle halos */
  --globe-ocean:         #f6f0e0;
  --globe-ocean-lit:     #f6f0e0;
  --globe-terminator:    rgba(11, 18, 29, 0.30);
  --globe-keyline:       #f6f0e0;       /* the keyline IS the paper halo in light */
  --globe-dot-day:       #0b121d;
  --globe-dot-night:     #0b121d;
  --globe-border:        rgba(11, 18, 29, 0.85);
  --globe-body-hi:       #f6f0e0;
  --globe-body-mid:      #f6f0e0;
  --globe-body-lo:       #f6f0e0;
  --globe-dot-neutral:   #0b121d;
  --globe-atmosphere-rgb: 11, 18, 29;   /* NEW, unused in light; defined so readers never get "" */
  --globe-land-rgb:      11, 18, 29;    /* NEW, unused in light */
  --globe-star-rgb:      11, 18, 29;    /* unused in light; the horizon's star field */
  --bar-track:           rgba(11, 18, 29, 0.12);      /* rail bars' unfilled track */

  /* state. The base :root --quality-warning (#f7931a) is 2.0:1 on paper, below the
     3:1 a stale ring needs, so light overrides it. Dark keeps the base value (8.8:1). */
  --quality-warning:     #c2410c;       /* 4.5:1 on paper */
  --success:             #0d6b63;
  --warning:             #9a4a07;
  --danger:              #b42318;
  --info:                var(--data-renewable);

  /* mark (NEW): read by the loader mark and the inline header mark (brand-mark.ts).
     The brand system's mark in a paper variant: the same gold and cyan, deep
     enough that the disc (3.3:1) and the curtailed arc (3.6:1) hold on paper. */
  --mark-disc:           #b07800;
  --mark-lead:           #0b8aa3;       /* first 26% of pillars (the curtailed share) */
  --mark-lead-opacity:   1;
  --mark-rest:           #e6a020;
  --mark-rest-opacity:   1;
  --mark-tick:           #0b121d;       /* the tick each pillar fires as it drops */
  --mark-glow:           transparent;   /* no halo behind the disc on paper */

  /* type */
  --font-display:        "Schibsted Grotesk", Inter, -apple-system, system-ui, "Segoe UI", sans-serif;
  --font-body:           "Schibsted Grotesk", Inter, -apple-system, system-ui, "Segoe UI", sans-serif;
  --font-mono:           "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-sans:           var(--font-body);
  --display-weight-strong: 800;         /* hero % and stat figures */
  --display-weight-base:   700;         /* h2 "Largest now", wordmark, selected label */
  --display-tracking:    -0.03em;       /* NEW: hero only; -0.01em for 25-30px figures */
  --display-leading:     0.92;          /* NEW */
  --fs-hero:             clamp(112px, 10.84vw, 156px);   /* NEW: 156px at 1440 */

  /* Observable Framework's own chrome (bare links, the pager, form controls)
     reads these; its theme is "dark", so without this they stay dark-on-paper. */
  --theme-foreground:       var(--ink);
  --theme-foreground-focus: var(--brand-text);
  --theme-background-b:     var(--surface-bg-2);
  --theme-background:       var(--surface-bg-3);
}

/* ------------------------------------------------------------------ DARK · Horizon layout, Nightgrid palette */
:root[data-theme="dark"] {
  color-scheme: dark;

  --brand:               #ffd05a;
  --brand-strong:        #e6a020;
  --brand-subtle:        rgba(255, 208, 90, 0.16);   /* active segmented-control chip */
  --brand-rgb:           255, 208, 90;
  --brand-on:            #060a11;
  --brand-text:          var(--brand);  /* NEW: gold is 13.6:1 on the dark ground */

  --surface-bg-1:        #15202f;
  --surface-bg-2:        #0b121d;
  --surface-bg-3:        #060a11;       /* page; the globe backdrop paints over it */
  --surface-raised:      #101a28;
  --surface-panel:       rgba(6, 10, 17, 0.74);       /* NEW: glass dock; pair with backdrop-filter: blur(18px) */
  --hairline:            rgba(255, 248, 224, 0.14);
  --hairline-strong:     rgba(255, 248, 224, 0.30);

  --ink:                 #fff8e0;
  --ink-muted:           #c8c4b2;       /* 11.3:1 on --surface-bg-3 */
  --ink-soft:            rgba(255, 248, 224, 0.60);   /* 6.9:1 */

  --data-renewable:      #67e8f9;
  --data-renewable-tip:  #cffafe;

  /* fuels: gold, cyan, violet. Violet, not periwinkle, keeps hydro apart from
     wind under deuteranopia. */
  --fuel-solar:          #ffd05a;
  --fuel-wind:           #67e8f9;
  --fuel-hydro:          #9d8cff;
  --fuel-solar-tip:      #ffecb3;       /* NEW */
  --fuel-wind-tip:       #cffafe;       /* NEW */
  --fuel-hydro-tip:      #ddd6ff;       /* NEW */

  /* horizon globe */
  --globe-ink-rgb:       255, 248, 224; /* NEW */
  --globe-paper:         #060a11;       /* NEW */
  --globe-atmosphere-rgb: 120, 170, 235; /* NEW */
  --globe-land-rgb:      207, 214, 223; /* NEW: cool, so day-side land never reads as solar */
  --globe-star-rgb:      255, 248, 224; /* the horizon's star field */
  --bar-track:           rgba(255, 248, 224, 0.12);   /* the dock's bar tracks (dark mock) */
  --globe-ocean:         #0a1220;
  --globe-ocean-lit:     #1b2b42;
  --globe-terminator:    rgba(255, 248, 224, 0.30);
  --globe-keyline:       #060a11;
  --globe-dot-day:       #cfd6df;
  --globe-dot-night:     #6f84a8;
  --globe-border:        rgba(255, 248, 224, 0.16);
  --globe-body-hi:       #04070c;       /* body gradient, centre to limb */
  --globe-body-mid:      #0a1220;
  --globe-body-lo:       #1b2b42;
  --globe-dot-neutral:   #cfd6df;

  --success:             #5eead4;
  --warning:             #ffb84d;
  --danger:              #f87171;
  --info:                var(--data-renewable);

  /* mark: the brand system's, unchanged — gold disc, gold pillars at 55%, the
     cyan curtailed share at 95%. The published SVGs use these (brand-mark.ts). */
  --mark-disc:           #ffd05a;       /* NEW */
  --mark-lead:           #67e8f9;       /* NEW */
  --mark-lead-opacity:   0.95;          /* NEW */
  --mark-rest:           #e6a020;       /* NEW */
  --mark-rest-opacity:   0.55;          /* NEW */
  --mark-tick:           #fff8e0;       /* NEW */
  --mark-glow:           rgba(255, 208, 90, 0.28);   /* NEW: halo behind the disc */

  --font-display:        "Schibsted Grotesk", Inter, -apple-system, system-ui, "Segoe UI", sans-serif;
  --font-body:           "Schibsted Grotesk", Inter, -apple-system, system-ui, "Segoe UI", sans-serif;
  --font-mono:           "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-sans:           var(--font-body);
  --display-weight-strong: 800;
  --display-weight-base:   700;
  --display-tracking:    -0.03em;       /* NEW: hero only; -0.02em for 28-30px figures */
  --display-leading:     0.92;          /* NEW */
  --fs-hero:             clamp(120px, 12.78vw, 184px);   /* NEW: 184px at 1440 */

  --theme-foreground:       var(--ink);
  --theme-foreground-focus: var(--brand-text);
  --theme-background-b:     var(--surface-bg-2);
  --theme-background:       var(--surface-bg-3);
}

/* Phone hero sizes (the mocks are 390 wide). */
@media (max-width: 640px) {
  :root[data-theme="light"] { --fs-hero: clamp(92px, 30.2vw, 118px); }
  :root[data-theme="dark"]  { --fs-hero: clamp(92px, 29.7vw, 116px); }
}

/* ------------------------------------------------------------------ EMBED · the paper figure only
   src/embed/globe.md (the globe the DARI paper iframes) pins data-theme="embed".
   Its look is part of a published artefact, so these are the palette it was
   published in (the site's old "Sunfire" theme), unchanged. The boot script pins
   it on /embed/ paths too, so the figure never paints a mode first. No page of
   the site sets it. */
:root[data-theme="embed"] {
  /* brand identity */
  --brand:               #ffd05a;
  --brand-strong:        #e6a020;
  --brand-subtle:        rgba(255, 208, 90, 0.10);
  --brand-rgb:           255, 208, 90;
  --brand-on:            #150e08;

  /* surfaces */
  --surface-bg-1:        #2d1f0e;
  --surface-bg-2:        #1a1207;
  --surface-bg-3:        #0a0703;
  --surface-raised:      #1f160a;
  --hairline:            rgba(255, 248, 224, 0.08);
  --hairline-strong:     rgba(255, 248, 224, 0.16);

  /* foreground */
  --ink:                 #fff8e0;
  --ink-muted:           rgba(255, 248, 224, 0.65);
  --ink-soft:            rgba(255, 248, 224, 0.40);

  /* data semantics */
  --data-renewable:      #67e8f9;
  --data-renewable-tip:  #cffafe;

  /* fuel breakouts */
  --fuel-solar:          #ffd05a;
  --fuel-wind:           #67e8f9;
  --fuel-hydro:          #b8cdff;

  /* globe — "lit land": the sphere takes one flat ocean fill and the land
     matrix carries day/night. Night land is warm amber rather than a dimmed
     grey, which is what used to read as cold. The border is neutral ink, not
     gold: gold on a gold-washed sphere is what camouflaged the solar pillars. */
  --globe-ocean:         #15110a;
  --globe-ocean-lit:     #332816;
  --globe-terminator:    rgba(255, 248, 224, 0.30);
  --globe-keyline:       #17110a;
  --globe-dot-day:       #fffdf2;
  --globe-dot-night:     #f0bf7a;
  --globe-border:        rgba(255, 248, 224, 0.16);
  /* G1 Lantern sphere: body gradient lit from the upper left, and the neutral
     land-dot tint (kept off cream so day-side land never reads as solar). */
  --globe-body-hi:       #4a3414;
  --globe-body-mid:      #1f160a;
  --globe-body-lo:       #0c0804;
  --globe-dot-neutral:   #e4dccc;

  /* state */
  --success:             #5eead4;
  --warning:             #ffb84d;
  --danger:              #f87171;
  --info:                var(--data-renewable);

  /* type: the figure's own rules set Inter and Fraunces; these only back them */
  --font-display:        "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-body:           "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono:           ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-sans:           var(--font-body);   /* alias: legacy rules read --font-sans */
  --display-weight-strong: 800;
  --display-weight-base:   600;
}

/* No-JS / pre-boot fallback. The boot script sets data-theme before first
   paint, so this only shows if it never runs. Without data-theme no token
   block applies, which is why these two literals are the one place this
   sheet paints a colour that is not a token (allowlisted in
   tests/style-colour-literals.test.ts). Dark, the site's default mode. */
:root:not([data-theme]) { color-scheme: dark; }
:root:not([data-theme]), html:not([data-theme]) body { background: #060a11; color: #fff8e0; }


/* ============ SEMANTIC ELEMENT STYLES ============ */
html, body {
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--surface-bg-3);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: var(--fw-book);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-heading);
  font-weight: var(--fw-bold);
  text-wrap: balance;
  margin: 0;
}

h1 { font-size: var(--fs-h1); font-weight: var(--fw-bold); }
h2 { font-size: var(--fs-h2); font-weight: var(--fw-bold); }
h3 { font-size: var(--fs-h3); font-weight: var(--fw-medium); }
h4 { font-size: var(--fs-h4); font-weight: var(--fw-medium); }

p { margin: 0; text-wrap: pretty; }
p.lead  { font-size: var(--fs-body-lg); color: var(--ink-muted); line-height: 1.5; }
p.small { font-size: var(--fs-body-sm); }

.eyebrow {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--brand-text);
}

.caption { font-size: var(--fs-caption); color: var(--ink-muted); }
.micro   { font-size: var(--fs-micro);   color: var(--ink-soft);  letter-spacing: 0.04em; }

code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-feature-settings: "tnum", "zero";
}

/* Tabular figures for money/BTC amounts */
.num-tabular { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }

/* =========================================================
   PAGE LOADER — visible immediately from raw HTML, before
   any JS executes. Dismissed via JS after globe mounts.
   ========================================================= */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--surface-bg-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* Ensure it covers the Observable Framework chrome while JS boots */
  pointer-events: none;
}

#page-loader.is-fading {
  animation: loader-fade-out 0.38s ease-out forwards;
}

@keyframes loader-fade-out {
  to { opacity: 0; }
}

/* The loading screen's mark. The geometry and the whole 6.6s sweep-and-release
   cycle between the markers below are GENERATED by `npm run brand:assets` from
   scripts/lib/brand-mark.ts — edit that, not this. tests/brand-mark.test.ts
   fails if the two drift apart.

   It is HTML elements and CSS transforms rather than the SVG in src/brand/,
   because SMIL inside an <img> runs on the main thread: on this screen, with
   ~135 data files landing, it froze a few hundred milliseconds in and only
   snapped to a full ring once the work was done. CSS transform animations are
   composited, so the mark keeps running no matter how busy the page is — which
   is the only honest thing for an animation whose job is to say "still alive".

   Size comes from one font-size: every generated length is in em, where 1em is
   the mark's diameter. */
.loader-mark {
  font-size: 148px;
}

/* brand-mark:begin — generated, do not edit */
.loader-mark{position:relative;width:1em;height:1em;flex-shrink:0;line-height:0}
.loader-mark::before{content:"";position:absolute;left:50%;top:50%;width:0.3em;height:0.3em;margin:-0.15em 0 0 -0.15em;border-radius:50%;box-shadow:0 0 0.3em 0.08em var(--mark-glow)}
.loader-mark u{position:absolute;left:50%;top:50%;width:0.3em;height:0.3em;margin:-0.15em 0 0 -0.15em;border-radius:50%;background:var(--mark-disc)}
.loader-mark i{position:absolute;left:50%;top:50%;width:0.016em;margin-left:-0.008em}
.loader-mark b{display:block;width:100%;height:100%;border-radius:0.008em;transform-origin:50% 100%;transform:scaleY(0);animation-duration:6.6s;animation-timing-function:linear;animation-iteration-count:infinite}
.loader-mark i::after{content:"";position:absolute;left:0;top:-0.022em;width:100%;height:0.018em;border-radius:0.008em;background:var(--mark-tick);opacity:0;animation-duration:6.6s;animation-timing-function:cubic-bezier(.25,.6,.5,1);animation-iteration-count:infinite}
.loader-mark .p0{height:0.1665em;transform-origin:50% 0;transform:rotate(0deg) translateY(-0.3665em)}
.loader-mark .p0 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p0}
.loader-mark .p0::after{animation-name:elj-t0}
@keyframes elj-p0{0%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}7.576%,53.03%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}59.848%,100%{transform:scaleY(0)}}
@keyframes elj-t0{0%,53.03%{transform:translateY(0);opacity:0}54.667%{opacity:0.95}66.667%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p1{height:0.237em;transform-origin:50% 0;transform:rotate(8.18deg) translateY(-0.437em)}
.loader-mark .p1 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p1}
.loader-mark .p1::after{animation-name:elj-t1}
@keyframes elj-p1{0%,0.895%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}8.471%,53.719%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}60.537%,100%{transform:scaleY(0)}}
@keyframes elj-t1{0%,53.719%{transform:translateY(0);opacity:0}55.355%{opacity:0.95}67.355%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p2{height:0.2262em;transform-origin:50% 0;transform:rotate(16.36deg) translateY(-0.4262em)}
.loader-mark .p2 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p2}
.loader-mark .p2::after{animation-name:elj-t2}
@keyframes elj-p2{0%,1.791%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}9.366%,54.408%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}61.226%,100%{transform:scaleY(0)}}
@keyframes elj-t2{0%,54.408%{transform:translateY(0);opacity:0}56.044%{opacity:0.95}68.044%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p3{height:0.2101em;transform-origin:50% 0;transform:rotate(24.55deg) translateY(-0.4101em)}
.loader-mark .p3 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p3}
.loader-mark .p3::after{animation-name:elj-t3}
@keyframes elj-p3{0%,2.686%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}10.262%,55.096%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}61.915%,100%{transform:scaleY(0)}}
@keyframes elj-t3{0%,55.096%{transform:translateY(0);opacity:0}56.733%{opacity:0.95}68.733%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p4{height:0.2314em;transform-origin:50% 0;transform:rotate(32.73deg) translateY(-0.4314em)}
.loader-mark .p4 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p4}
.loader-mark .p4::after{animation-name:elj-t4}
@keyframes elj-p4{0%,3.581%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}11.157%,55.785%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}62.603%,100%{transform:scaleY(0)}}
@keyframes elj-t4{0%,55.785%{transform:translateY(0);opacity:0}57.421%{opacity:0.95}69.421%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p5{height:0.1979em;transform-origin:50% 0;transform:rotate(40.91deg) translateY(-0.3979em)}
.loader-mark .p5 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p5}
.loader-mark .p5::after{animation-name:elj-t5}
@keyframes elj-p5{0%,4.477%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}12.052%,56.474%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}63.292%,100%{transform:scaleY(0)}}
@keyframes elj-t5{0%,56.474%{transform:translateY(0);opacity:0}58.11%{opacity:0.95}70.11%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p6{height:0.1811em;transform-origin:50% 0;transform:rotate(49.09deg) translateY(-0.3811em)}
.loader-mark .p6 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p6}
.loader-mark .p6::after{animation-name:elj-t6}
@keyframes elj-p6{0%,5.372%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}12.948%,57.163%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}63.981%,100%{transform:scaleY(0)}}
@keyframes elj-t6{0%,57.163%{transform:translateY(0);opacity:0}58.799%{opacity:0.95}70.799%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p7{height:0.1066em;transform-origin:50% 0;transform:rotate(57.27deg) translateY(-0.3066em)}
.loader-mark .p7 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p7}
.loader-mark .p7::after{animation-name:elj-t7}
@keyframes elj-p7{0%,6.267%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}13.843%,57.851%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}64.669%,100%{transform:scaleY(0)}}
@keyframes elj-t7{0%,57.851%{transform:translateY(0);opacity:0}59.488%{opacity:0.95}71.488%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p8{height:0.2292em;transform-origin:50% 0;transform:rotate(65.45deg) translateY(-0.4292em)}
.loader-mark .p8 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p8}
.loader-mark .p8::after{animation-name:elj-t8}
@keyframes elj-p8{0%,7.163%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}14.738%,58.54%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}65.358%,100%{transform:scaleY(0)}}
@keyframes elj-t8{0%,58.54%{transform:translateY(0);opacity:0}60.176%{opacity:0.95}72.176%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p9{height:0.0923em;transform-origin:50% 0;transform:rotate(73.64deg) translateY(-0.2923em)}
.loader-mark .p9 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p9}
.loader-mark .p9::after{animation-name:elj-t9}
@keyframes elj-p9{0%,8.058%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}15.634%,59.229%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}66.047%,100%{transform:scaleY(0)}}
@keyframes elj-t9{0%,59.229%{transform:translateY(0);opacity:0}60.865%{opacity:0.95}72.865%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p10{height:0.2115em;transform-origin:50% 0;transform:rotate(81.82deg) translateY(-0.4115em)}
.loader-mark .p10 b{background:var(--mark-lead);opacity:var(--mark-lead-opacity);animation-name:elj-p10}
.loader-mark .p10::after{animation-name:elj-t10}
@keyframes elj-p10{0%,8.953%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}16.529%,59.917%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}66.736%,100%{transform:scaleY(0)}}
@keyframes elj-t10{0%,59.917%{transform:translateY(0);opacity:0}61.554%{opacity:0.95}73.554%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p11{height:0.1011em;transform-origin:50% 0;transform:rotate(90deg) translateY(-0.3011em)}
.loader-mark .p11 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p11}
.loader-mark .p11::after{animation-name:elj-t11}
@keyframes elj-p11{0%,9.848%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}17.424%,60.606%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}67.424%,100%{transform:scaleY(0)}}
@keyframes elj-t11{0%,60.606%{transform:translateY(0);opacity:0}62.242%{opacity:0.95}74.242%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p12{height:0.0833em;transform-origin:50% 0;transform:rotate(98.18deg) translateY(-0.2833em)}
.loader-mark .p12 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p12}
.loader-mark .p12::after{animation-name:elj-t12}
@keyframes elj-p12{0%,10.744%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}18.32%,61.295%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}68.113%,100%{transform:scaleY(0)}}
@keyframes elj-t12{0%,61.295%{transform:translateY(0);opacity:0}62.931%{opacity:0.95}74.931%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p13{height:0.2308em;transform-origin:50% 0;transform:rotate(106.36deg) translateY(-0.4308em)}
.loader-mark .p13 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p13}
.loader-mark .p13::after{animation-name:elj-t13}
@keyframes elj-p13{0%,11.639%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}19.215%,61.983%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}68.802%,100%{transform:scaleY(0)}}
@keyframes elj-t13{0%,61.983%{transform:translateY(0);opacity:0}63.62%{opacity:0.95}75.62%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p14{height:0.1054em;transform-origin:50% 0;transform:rotate(114.55deg) translateY(-0.3054em)}
.loader-mark .p14 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p14}
.loader-mark .p14::after{animation-name:elj-t14}
@keyframes elj-p14{0%,12.534%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}20.11%,62.672%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}69.49%,100%{transform:scaleY(0)}}
@keyframes elj-t14{0%,62.672%{transform:translateY(0);opacity:0}64.309%{opacity:0.95}76.309%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p15{height:0.1943em;transform-origin:50% 0;transform:rotate(122.73deg) translateY(-0.3943em)}
.loader-mark .p15 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p15}
.loader-mark .p15::after{animation-name:elj-t15}
@keyframes elj-p15{0%,13.43%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}21.006%,63.361%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}70.179%,100%{transform:scaleY(0)}}
@keyframes elj-t15{0%,63.361%{transform:translateY(0);opacity:0}64.997%{opacity:0.95}76.997%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p16{height:0.0899em;transform-origin:50% 0;transform:rotate(130.91deg) translateY(-0.2899em)}
.loader-mark .p16 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p16}
.loader-mark .p16::after{animation-name:elj-t16}
@keyframes elj-p16{0%,14.325%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}21.901%,64.05%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}70.868%,100%{transform:scaleY(0)}}
@keyframes elj-t16{0%,64.05%{transform:translateY(0);opacity:0}65.686%{opacity:0.95}77.686%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p17{height:0.1381em;transform-origin:50% 0;transform:rotate(139.09deg) translateY(-0.3381em)}
.loader-mark .p17 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p17}
.loader-mark .p17::after{animation-name:elj-t17}
@keyframes elj-p17{0%,15.22%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}22.796%,64.738%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}71.556%,100%{transform:scaleY(0)}}
@keyframes elj-t17{0%,64.738%{transform:translateY(0);opacity:0}66.375%{opacity:0.95}78.375%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p18{height:0.2149em;transform-origin:50% 0;transform:rotate(147.27deg) translateY(-0.4149em)}
.loader-mark .p18 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p18}
.loader-mark .p18::after{animation-name:elj-t18}
@keyframes elj-p18{0%,16.116%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}23.691%,65.427%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}72.245%,100%{transform:scaleY(0)}}
@keyframes elj-t18{0%,65.427%{transform:translateY(0);opacity:0}67.063%{opacity:0.95}79.063%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p19{height:0.1103em;transform-origin:50% 0;transform:rotate(155.45deg) translateY(-0.3103em)}
.loader-mark .p19 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p19}
.loader-mark .p19::after{animation-name:elj-t19}
@keyframes elj-p19{0%,17.011%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}24.587%,66.116%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}72.934%,100%{transform:scaleY(0)}}
@keyframes elj-t19{0%,66.116%{transform:translateY(0);opacity:0}67.752%{opacity:0.95}79.752%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p20{height:0.1615em;transform-origin:50% 0;transform:rotate(163.64deg) translateY(-0.3615em)}
.loader-mark .p20 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p20}
.loader-mark .p20::after{animation-name:elj-t20}
@keyframes elj-p20{0%,17.906%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}25.482%,66.804%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}73.623%,100%{transform:scaleY(0)}}
@keyframes elj-t20{0%,66.804%{transform:translateY(0);opacity:0}68.441%{opacity:0.95}80.441%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p21{height:0.17em;transform-origin:50% 0;transform:rotate(171.82deg) translateY(-0.37em)}
.loader-mark .p21 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p21}
.loader-mark .p21::after{animation-name:elj-t21}
@keyframes elj-p21{0%,18.802%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}26.377%,67.493%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}74.311%,100%{transform:scaleY(0)}}
@keyframes elj-t21{0%,67.493%{transform:translateY(0);opacity:0}69.129%{opacity:0.95}81.129%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p22{height:0.1543em;transform-origin:50% 0;transform:rotate(180deg) translateY(-0.3543em)}
.loader-mark .p22 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p22}
.loader-mark .p22::after{animation-name:elj-t22}
@keyframes elj-p22{0%,19.697%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}27.273%,68.182%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}75%,100%{transform:scaleY(0)}}
@keyframes elj-t22{0%,68.182%{transform:translateY(0);opacity:0}69.818%{opacity:0.95}81.818%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p23{height:0.0811em;transform-origin:50% 0;transform:rotate(188.18deg) translateY(-0.2811em)}
.loader-mark .p23 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p23}
.loader-mark .p23::after{animation-name:elj-t23}
@keyframes elj-p23{0%,20.592%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}28.168%,68.871%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}75.689%,100%{transform:scaleY(0)}}
@keyframes elj-t23{0%,68.871%{transform:translateY(0);opacity:0}70.507%{opacity:0.95}82.507%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p24{height:0.0816em;transform-origin:50% 0;transform:rotate(196.36deg) translateY(-0.2816em)}
.loader-mark .p24 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p24}
.loader-mark .p24::after{animation-name:elj-t24}
@keyframes elj-p24{0%,21.488%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}29.063%,69.559%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}76.377%,100%{transform:scaleY(0)}}
@keyframes elj-t24{0%,69.559%{transform:translateY(0);opacity:0}71.196%{opacity:0.95}83.196%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p25{height:0.1209em;transform-origin:50% 0;transform:rotate(204.55deg) translateY(-0.3209em)}
.loader-mark .p25 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p25}
.loader-mark .p25::after{animation-name:elj-t25}
@keyframes elj-p25{0%,22.383%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}29.959%,70.248%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}77.066%,100%{transform:scaleY(0)}}
@keyframes elj-t25{0%,70.248%{transform:translateY(0);opacity:0}71.884%{opacity:0.95}83.884%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p26{height:0.1784em;transform-origin:50% 0;transform:rotate(212.73deg) translateY(-0.3784em)}
.loader-mark .p26 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p26}
.loader-mark .p26::after{animation-name:elj-t26}
@keyframes elj-p26{0%,23.278%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}30.854%,70.937%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}77.755%,100%{transform:scaleY(0)}}
@keyframes elj-t26{0%,70.937%{transform:translateY(0);opacity:0}72.573%{opacity:0.95}84.573%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p27{height:0.0787em;transform-origin:50% 0;transform:rotate(220.91deg) translateY(-0.2787em)}
.loader-mark .p27 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p27}
.loader-mark .p27::after{animation-name:elj-t27}
@keyframes elj-p27{0%,24.174%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}31.749%,71.625%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}78.444%,100%{transform:scaleY(0)}}
@keyframes elj-t27{0%,71.625%{transform:translateY(0);opacity:0}73.262%{opacity:0.95}85.262%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p28{height:0.1325em;transform-origin:50% 0;transform:rotate(229.09deg) translateY(-0.3325em)}
.loader-mark .p28 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p28}
.loader-mark .p28::after{animation-name:elj-t28}
@keyframes elj-p28{0%,25.069%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}32.645%,72.314%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}79.132%,100%{transform:scaleY(0)}}
@keyframes elj-t28{0%,72.314%{transform:translateY(0);opacity:0}73.95%{opacity:0.95}85.95%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p29{height:0.1971em;transform-origin:50% 0;transform:rotate(237.27deg) translateY(-0.3971em)}
.loader-mark .p29 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p29}
.loader-mark .p29::after{animation-name:elj-t29}
@keyframes elj-p29{0%,25.964%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}33.54%,73.003%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}79.821%,100%{transform:scaleY(0)}}
@keyframes elj-t29{0%,73.003%{transform:translateY(0);opacity:0}74.639%{opacity:0.95}86.639%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p30{height:0.0784em;transform-origin:50% 0;transform:rotate(245.45deg) translateY(-0.2784em)}
.loader-mark .p30 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p30}
.loader-mark .p30::after{animation-name:elj-t30}
@keyframes elj-p30{0%,26.86%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}34.435%,73.691%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}80.51%,100%{transform:scaleY(0)}}
@keyframes elj-t30{0%,73.691%{transform:translateY(0);opacity:0}75.328%{opacity:0.95}87.328%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p31{height:0.2381em;transform-origin:50% 0;transform:rotate(253.64deg) translateY(-0.4381em)}
.loader-mark .p31 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p31}
.loader-mark .p31::after{animation-name:elj-t31}
@keyframes elj-p31{0%,27.755%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}35.331%,74.38%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}81.198%,100%{transform:scaleY(0)}}
@keyframes elj-t31{0%,74.38%{transform:translateY(0);opacity:0}76.017%{opacity:0.95}88.017%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p32{height:0.0806em;transform-origin:50% 0;transform:rotate(261.82deg) translateY(-0.2806em)}
.loader-mark .p32 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p32}
.loader-mark .p32::after{animation-name:elj-t32}
@keyframes elj-p32{0%,28.65%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}36.226%,75.069%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}81.887%,100%{transform:scaleY(0)}}
@keyframes elj-t32{0%,75.069%{transform:translateY(0);opacity:0}76.705%{opacity:0.95}88.705%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p33{height:0.1235em;transform-origin:50% 0;transform:rotate(270deg) translateY(-0.3235em)}
.loader-mark .p33 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p33}
.loader-mark .p33::after{animation-name:elj-t33}
@keyframes elj-p33{0%,29.545%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}37.121%,75.758%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}82.576%,100%{transform:scaleY(0)}}
@keyframes elj-t33{0%,75.758%{transform:translateY(0);opacity:0}77.394%{opacity:0.95}89.394%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p34{height:0.2207em;transform-origin:50% 0;transform:rotate(278.18deg) translateY(-0.4207em)}
.loader-mark .p34 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p34}
.loader-mark .p34::after{animation-name:elj-t34}
@keyframes elj-p34{0%,30.441%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}38.017%,76.446%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}83.264%,100%{transform:scaleY(0)}}
@keyframes elj-t34{0%,76.446%{transform:translateY(0);opacity:0}78.083%{opacity:0.95}90.083%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p35{height:0.0938em;transform-origin:50% 0;transform:rotate(286.36deg) translateY(-0.2938em)}
.loader-mark .p35 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p35}
.loader-mark .p35::after{animation-name:elj-t35}
@keyframes elj-p35{0%,31.336%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}38.912%,77.135%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}83.953%,100%{transform:scaleY(0)}}
@keyframes elj-t35{0%,77.135%{transform:translateY(0);opacity:0}78.771%{opacity:0.95}90.771%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p36{height:0.1667em;transform-origin:50% 0;transform:rotate(294.55deg) translateY(-0.3667em)}
.loader-mark .p36 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p36}
.loader-mark .p36::after{animation-name:elj-t36}
@keyframes elj-p36{0%,32.231%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}39.807%,77.824%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}84.642%,100%{transform:scaleY(0)}}
@keyframes elj-t36{0%,77.824%{transform:translateY(0);opacity:0}79.46%{opacity:0.95}91.46%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p37{height:0.1209em;transform-origin:50% 0;transform:rotate(302.73deg) translateY(-0.3209em)}
.loader-mark .p37 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p37}
.loader-mark .p37::after{animation-name:elj-t37}
@keyframes elj-p37{0%,33.127%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}40.702%,78.512%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}85.331%,100%{transform:scaleY(0)}}
@keyframes elj-t37{0%,78.512%{transform:translateY(0);opacity:0}80.149%{opacity:0.95}92.149%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p38{height:0.1653em;transform-origin:50% 0;transform:rotate(310.91deg) translateY(-0.3653em)}
.loader-mark .p38 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p38}
.loader-mark .p38::after{animation-name:elj-t38}
@keyframes elj-p38{0%,34.022%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}41.598%,79.201%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}86.019%,100%{transform:scaleY(0)}}
@keyframes elj-t38{0%,79.201%{transform:translateY(0);opacity:0}80.837%{opacity:0.95}92.837%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p39{height:0.1516em;transform-origin:50% 0;transform:rotate(319.09deg) translateY(-0.3516em)}
.loader-mark .p39 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p39}
.loader-mark .p39::after{animation-name:elj-t39}
@keyframes elj-p39{0%,34.917%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}42.493%,79.89%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}86.708%,100%{transform:scaleY(0)}}
@keyframes elj-t39{0%,79.89%{transform:translateY(0);opacity:0}81.526%{opacity:0.95}93.526%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p40{height:0.1945em;transform-origin:50% 0;transform:rotate(327.27deg) translateY(-0.3945em)}
.loader-mark .p40 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p40}
.loader-mark .p40::after{animation-name:elj-t40}
@keyframes elj-p40{0%,35.813%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}43.388%,80.579%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}87.397%,100%{transform:scaleY(0)}}
@keyframes elj-t40{0%,80.579%{transform:translateY(0);opacity:0}82.215%{opacity:0.95}94.215%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p41{height:0.1794em;transform-origin:50% 0;transform:rotate(335.45deg) translateY(-0.3794em)}
.loader-mark .p41 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p41}
.loader-mark .p41::after{animation-name:elj-t41}
@keyframes elj-p41{0%,36.708%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}44.284%,81.267%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}88.085%,100%{transform:scaleY(0)}}
@keyframes elj-t41{0%,81.267%{transform:translateY(0);opacity:0}82.904%{opacity:0.95}94.904%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p42{height:0.148em;transform-origin:50% 0;transform:rotate(343.64deg) translateY(-0.348em)}
.loader-mark .p42 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p42}
.loader-mark .p42::after{animation-name:elj-t42}
@keyframes elj-p42{0%,37.603%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}45.179%,81.956%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}88.774%,100%{transform:scaleY(0)}}
@keyframes elj-t42{0%,81.956%{transform:translateY(0);opacity:0}83.592%{opacity:0.95}95.592%,100%{transform:translateY(-0.062em);opacity:0}}
.loader-mark .p43{height:0.109em;transform-origin:50% 0;transform:rotate(351.82deg) translateY(-0.309em)}
.loader-mark .p43 b{background:var(--mark-rest);opacity:var(--mark-rest-opacity);animation-name:elj-p43}
.loader-mark .p43::after{animation-name:elj-t43}
@keyframes elj-p43{0%,38.499%{transform:scaleY(0);animation-timing-function:cubic-bezier(.16,1,.3,1)}46.074%,82.645%{transform:scaleY(1);animation-timing-function:cubic-bezier(.65,0,.85,.2)}89.463%,100%{transform:scaleY(0)}}
@keyframes elj-t43{0%,82.645%{transform:translateY(0);opacity:0}84.281%{opacity:0.95}96.281%,100%{transform:translateY(-0.062em);opacity:0}}
@media (prefers-reduced-motion: reduce){
.loader-mark b{animation:none;transform:scaleY(1)}
.loader-mark i::after{animation:none;opacity:0}}
/* brand-mark:end */

/* The loading screen's wordmark is the same lockup as the one in the header
   (see .app-wordmark). */
.loader-wordmark {
  font-size: clamp(30px, 5vw, 40px);
  line-height: 1;
  margin-top: 14px;
}

/* Determinate rail. One file resolved is one step, which is the only
   progress the page actually knows — the region counter below it is an
   even share of each file and lands exactly on the total (see
   loader-progress.js and tests/loader-progress.test.ts). */
.loader-rail {
  width: min(220px, 60vw);
  height: 2px;
  border-radius: 1px;
  background: var(--hairline);
  overflow: hidden;
  margin-top: 4px;
}

.loader-rail-fill {
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--brand);
  transition: width 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .loader-rail-fill { transition: none; }
}

.loader-counter {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  font-family: var(--font-mono, monospace);
  /* Source names run long ("National Grid ESO — Balancing Mechanism"), so the
     line wraps and stays centred rather than running off a phone screen. */
  max-width: min(88vw, 340px);
  text-align: center;
  line-height: 1.6;
  text-wrap: balance;
}

.loader-counter #loader-n {
  color: var(--ink-muted);
  font-weight: 600;
}

.loader-counter #loader-total {
  color: var(--ink-soft);
}

/* The source that just landed, in place of the old five-row terminal.
   Empty until the first file resolves, and it carries its own separator so
   the line does not sit with a dangling middot. */
.loader-source {
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: opacity 0.2s ease-out;
}

.loader-source:not(:empty)::before {
  content: "·";
  margin: 0 0.5em;
  color: var(--ink-soft);
}

@media (max-width: 520px) {
  .loader-mark { font-size: 112px; }
}

/* Page ground, in both modes. Target html as well as body so mobile
   overscroll shows the mode's page colour, not a fallback. */
html,
body {
  background: var(--surface-bg-3);
  color: var(--ink);
  min-height: 100vh;
}

/* =========================================================================
   RESPONSIVENESS & ACCESSIBILITY
   ========================================================================= */

*, *::before, *::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
  font-size: clamp(15px, 0.95rem + 0.15vw, var(--fs-body));
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

:focus-visible {
  /* Ink in both modes (15.8:1 on paper, 18.4:1 on the dark ground). The
     brand colour only just clears a focus indicator's 3:1 on paper, and
     not on its own brand-subtle fills. */
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

@media (max-width: 640px) {
  main > div[style*="display: flex"][style*="gap: 2rem"] {
    flex-wrap: wrap;
    gap: 1rem !important;
  }

  body {
    padding-inline: 4vw;
  }

  /* The dashboard brings its own gutter (.app-shell padding). Stacked on
     the 4vw above and Framework's 2rem #observablehq-center margin it left
     253px of a 375px phone, and 198px of a 320px one. Drop the two generic
     gutters on the dashboard only; the doc pages keep theirs. */
  body:has(.app-shell) {
    padding-inline: 0;
  }
  #observablehq-center:has(.app-shell) {
    margin-inline: 0;
  }
  /* Framework's "Next page" pager sits outside .app-shell; give it the
     shell's phone gutter back so it does not touch the screen edge. */
  #observablehq-center:has(.app-shell) > #observablehq-footer {
    margin-inline: 14px;
  }
}

main table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
}

/* =========================================================================
   DASHBOARD — one DOM, two layouts
   src/index.md renders one tree; the mode's layout comes from CSS on
   :root[data-theme] (redesign plan 3). Rendering a second tree and hiding
   it would duplicate IDs and make the aria-live readouts announce twice.

   Light desktop (≥1100px) is the Almanac board (mocks/light-desktop.html):
   hero 396 | globe | 34 | rail 234, with the timeline band below and the
   footer after the fold. Dark desktop is the Horizon stage
   (mocks/dark-desktop.html): the globe fills the first viewport behind the
   hero and a glass dock. Until the tablet and phone layouts (PR 4) land,
   narrower screens stack in both modes.
   ========================================================================= */

/* The dashboard owns its gutters at every width: lift Framework's 1440px
   body cap and its page margins, as #1082 did at phone widths. */
body:has(.app-shell) { max-width: none; }
#observablehq-center:has(.app-shell) { margin: 0; }
#observablehq-main:has(.app-shell) { margin: 0; }

.app-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "header" "hero" "globe" "rail" "timeline" "footer";
  max-width: 1680px;
  margin: 0 auto;
  padding: 0 20px;
  color: var(--ink);
  font-family: var(--font-body);
}

/* The Spectrum mark, static. The loader runs the animated version once;
   a second copy animating forever in the header would compete with the
   globe for the same main thread that #1054 had to rescue. It is inline SVG
   (generated between the brand-mark-still markers in src/index.md) rather
   than an <img>, because an <img> cannot read the --mark-* tokens. */
.app-mark {
  width: 26px;
  height: 26px;
  display: block;
  flex-shrink: 0;
  overflow: visible;
}

/* The wordmark lockup, shared by the header and the loading screen, is the
   brand system's in both modes: Schibsted Grotesk 700 at -0.01em, "Every
   Last" in ink and "Joule" in the brand colour (--brand-text, the brand hue
   that carries small text in each mode). */
.app-wordmark,
.loader-wordmark {
  font-family: var(--font-display);
  font-weight: var(--display-weight-base);
  letter-spacing: -0.01em;
  color: var(--ink);
}
.app-wordmark-accent,
.loader-wordmark span {
  color: var(--brand-text);
}

/* ---- Header: lockup left, nav + DOI pill + mode switch right ------------ */
.app-header {
  grid-area: header;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  flex-wrap: wrap;
  min-height: 64px;
  padding: 10px 0;
  border-bottom: 1px solid var(--hairline);
  position: relative;
  z-index: 10;
}

.app-lockup {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
}
.app-lockup:hover { text-decoration: none; }
.app-lockup .app-mark { width: 26px; height: 26px; }
.app-lockup .app-wordmark { font-size: 17px; line-height: 1; }
/* The dashboard's dark header floats over the sky: no rule (redesign plan
   3.2, 3.4). The doc pages keep theirs. */
:root[data-theme="dark"] .app-shell > .app-header { border-bottom-color: transparent; }

.app-header-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 10px 20px;
  min-width: 0;
}

.app-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px 22px;
  font-size: 14px;
}
.app-nav a {
  color: var(--ink);
  text-decoration: none;
}
.app-nav a:hover { text-decoration: underline; text-underline-offset: 3px; }

.app-version {
  font: 12px/1 var(--font-mono);
  padding: 7px 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  white-space: nowrap;
}
:root[data-theme="dark"] .app-version { border-color: var(--hairline); }
.app-nav .app-version:hover { text-decoration: none; background: color-mix(in srgb, var(--ink) 8%, transparent); }

/* ---- Hero ------------------------------------------------------------------ */
.hero {
  grid-area: hero;
  display: flex;
  flex-direction: column;
  padding: 24px 0 8px;
  position: relative;
  z-index: 1;
}

.hero-eyebrow {
  font: 400 12px/1.3 var(--font-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink);
}
.hero-eyebrow-time { display: none; }

.hero-pct {
  margin: 18px 0 0 -4px;
  font-family: var(--font-display);
  font-weight: var(--display-weight-strong);
  font-size: var(--fs-hero);
  line-height: var(--display-leading);
  letter-spacing: var(--display-tracking);
  color: var(--ink);
}
.hero-pct-sign { font-style: normal; }

.hero .lead {
  margin: 20px 0 0;
  max-width: none;
  font-size: 16px;
  line-height: 1.45;
  color: var(--ink-muted);
}

.hero-stats {
  margin: 24px 0 0;
  border-bottom: 1px solid var(--hairline);
}
.hero-stats .stat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 11px 0 10px;
  border-top: 1px solid var(--hairline);
}
.stat-label {
  margin: 0;
  font-size: 14px;
  color: var(--ink);
}
/* Per-mode wording: .label-long is the accessible text, which light shows;
   .label-short is dark's, aria-hidden so an accessible name never changes
   with the mode (redesign plan 3). Dark keeps the long text for screen
   readers only. */
.label-short { display: none; }
:root[data-theme="dark"] .label-short { display: inline; }
:root[data-theme="dark"] .label-long {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.stat-value {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-display);
  font-weight: var(--display-weight-strong);
  font-size: 30px;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}
.stat-unit {
  font: 400 12px/1 var(--font-mono);
  letter-spacing: 0;
  color: var(--ink-muted);
}

/* Dark hero (mocks/dark-desktop.html): the eyebrow is the brand colour, led
   by a glowing dot and the live time; the lead is muted; the three stats sit
   in one row of hairline-divided cells with short Mono labels. */
:root[data-theme="dark"] .hero-eyebrow { font-size: 11px; color: var(--brand-text); }
:root[data-theme="dark"] .hero-eyebrow::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 10px;
  vertical-align: 1px;
  border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 10px var(--brand);
}
:root[data-theme="dark"] .hero-eyebrow-time { display: inline; }
:root[data-theme="dark"] .hero-eyebrow-time::after { content: " · "; }
:root[data-theme="dark"] .hero .lead { line-height: 1.5; color: var(--ink-muted); }
:root[data-theme="dark"] .hero-stats {
  display: flex;
  flex-wrap: wrap;           /* one row from 360px up; wraps on the narrowest phones */
  row-gap: 16px;
  margin: 28px 0 0 -22px;
  border-bottom: 0;
}
:root[data-theme="dark"] .hero-stats .stat {
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
  padding: 0 22px;
  border-top: 0;
  border-left: 1px solid transparent;
}
:root[data-theme="dark"] .hero-stats .stat + .stat { border-left-color: var(--hairline); }
:root[data-theme="dark"] .stat-label {
  font: 400 11px/1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
:root[data-theme="dark"] .stat-value {
  font-family: var(--font-body);
  font-weight: 500;
  letter-spacing: -0.02em;
}
:root[data-theme="dark"] .stat-unit { font-size: 11px; }

.hero-caption {
  margin: 18px 0 0;
  max-width: none;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink);
}
/* "Fig. 1" is an <em>; Schibsted Grotesk ships no italic, so it is a mono
   label rather than a synthesised slant. */
.hero-fig {
  font: 500 11px/1 var(--font-mono);
  font-style: normal;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
/* The dark board has no figure caption (redesign plan 5). */
:root[data-theme="dark"] .hero-caption { display: none; }

/* ---- Globe stage ------------------------------------------------------------ */
.globe-stage {
  grid-area: globe;
  position: relative;
  min-width: 0;
  aspect-ratio: 1;
  max-height: 80svh;
  width: 100%;
  justify-self: center;
}

#globe-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
#globe-canvas.is-dragging { cursor: grabbing; }
#globe-canvas[hidden] { visibility: hidden; }

.globe-placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.globe-placeholder-label {
  font: 11px/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* The selected region's label card: tracks its needle head, flips side at
   the canvas edge (placed by src/globe-engraved.js placeSelectionLabel). */
.globe-selection {
  position: absolute;
  z-index: 3;
  width: 196px;
  box-sizing: border-box;
  padding: 10px 12px 11px;
  background: var(--surface-raised);
  border: 1px solid var(--hairline-strong);
  color: var(--ink);
  pointer-events: auto;
}
.globe-selection[hidden] { display: none; }
.gs-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font: 400 10.5px/1.3 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* The fuel is named in ink with a swatch beside it: fuel colours are
   graphics-only on paper (hydro 3.7:1, solar 3.2:1). */
.gs-fuel { display: inline-flex; align-items: center; gap: 5px; }
.gs-fuel .dot { width: 7px; height: 7px; }
/* Ink, like the hover card's name: Framework's a[href] rule would paint it
   the link colour, which is amber in dark. */
.globe-selection .gs-name {
  display: block;
  margin-top: 4px;
  font-family: var(--font-display);
  font-weight: var(--display-weight-base);
  font-size: 25px;
  line-height: 1.1;
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.gs-name:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.gs-now { margin-top: 2px; font-size: 13px; }
/* Dark: glass, as the dock; the name in 500 20px (redesign plan 6.3). */
:root[data-theme="dark"] .globe-selection {
  background: var(--surface-panel);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  border-color: var(--hairline);
  border-radius: 12px;
}
:root[data-theme="dark"] .gs-name { font-family: var(--font-body); font-weight: 500; font-size: 20px; }

/* Zoom: the wheel and a pinch zoom the globe everywhere; the slider is the
   keyboard route. The light board draws no zoom control, so it sits quietly
   in the stage's corner. */
.globe-zoom-controls {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
}
.globe-zoom-controls[hidden] { display: none; }
:root[data-theme="dark"] .globe-zoom-controls { display: none; }

/* Dark: the globe zooms with a scroll over it, a pinch or these buttons, a
   glass column at the stage's right, under the header and clear of the dock.
   Phones zoom in the explorer, with a pinch. */
.horizon-view { display: none; }
@media (min-width: 641px) {
  :root[data-theme="dark"] .horizon-view:not([hidden]) {
    position: absolute;
    top: 96px;
    right: 24px;
    z-index: 3;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--hairline);
    border-radius: 12px;
    background: var(--surface-panel);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    overflow: hidden;
  }
}
.horizon-view button {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.horizon-view button + button { border-top: 1px solid var(--hairline); }
.horizon-view button:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.horizon-view button:disabled { color: var(--ink-soft); opacity: 0.5; cursor: default; }
.horizon-view button:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.globe-zoom-label {
  font: 10px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  user-select: none;
}
.globe-zoom-controls .globe-zoom-slider {
  width: 96px;
  cursor: pointer;
  accent-color: var(--ink-muted);
  opacity: 0.5;
  transition: opacity 0.15s;
}
.globe-zoom-slider:hover,
.globe-zoom-slider:focus { opacity: 1; }
.globe-zoom-slider:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---- Rail: "Largest now" --------------------------------------------------- */
.rail {
  grid-area: rail;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 20px 0 8px;
  position: relative;
  z-index: 1;
}
.rail-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  padding-bottom: 10px;
}
.rail-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight-base);
  font-size: 25px;
  line-height: 1;
  letter-spacing: 0;
  color: var(--ink);
}
.rail-time { font: 11px/1 var(--font-mono); color: var(--ink); white-space: nowrap; }

.hotspot-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  border-bottom: 1px solid var(--hairline);
}
.hotspot-item {
  display: grid;
  grid-template-columns: 20px 26px minmax(0, 1fr) auto;
  column-gap: 8px;
  align-items: center;
  padding: 8px 0;
  border-top: 1px solid var(--hairline);
  font-size: 13.5px;
  line-height: 1.2;
  color: var(--ink);
}
.hs-rank { font: 11px/1 var(--font-mono); color: var(--ink); }
.hs-needle { display: block; line-height: 0; }
.fuel-solar { color: var(--fuel-solar); }
.fuel-wind { color: var(--fuel-wind); }
.fuel-hydro { color: var(--fuel-hydro); }
.hotspot-item > :not(.hs-needle) { color: var(--ink); }
.needle-glyph { display: block; overflow: visible; }
.needle-glyph-stale { stroke: var(--quality-warning); }
.hotspot-name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* "est." and "stale" are <em>s set as mono labels (no synthesised italic). */
.hs-tag {
  font: 400 11px/1 var(--font-mono);
  font-style: normal;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hs-bar { display: none; }
/* Dark rows are the dock's (mocks/dark-desktop.html): name, a glowing bar
   and the value. The beams carry no needle, so neither does the list; the
   est. and stale tags stay, as the list's words for what the beams show by
   shape (WCAG 1.4.1). */
:root[data-theme="dark"] .hotspot-list { border-bottom: 0; }
:root[data-theme="dark"] .hotspot-item {
  grid-template-columns: minmax(0, 1fr) 110px 52px;
  column-gap: 12px;
  min-height: 25px;
  padding: 0;
  border-top: 0;
  font-size: 14px;
}
:root[data-theme="dark"] :is(.hs-rank, .hs-needle) { display: none; }
:root[data-theme="dark"] .hs-tag {
  font: 400 10px/1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
:root[data-theme="dark"] .hs-bar {
  display: block;
  height: 3px;
  border-radius: 2px;
  background: var(--bar-track);
}
:root[data-theme="dark"] .hs-bar > span {
  display: block;
  height: 100%;
  min-width: 4px;
  border-radius: 2px;
  background: currentColor;
  box-shadow: 0 0 10px currentColor;
}
:root[data-theme="dark"] .hotspot-item > .hs-bar { color: inherit; }
:root[data-theme="dark"] .hotspot-item.fuel-solar > .hs-bar { color: var(--fuel-solar); }
:root[data-theme="dark"] .hotspot-item.fuel-wind > .hs-bar { color: var(--fuel-wind); }
:root[data-theme="dark"] .hotspot-item.fuel-hydro > .hs-bar { color: var(--fuel-hydro); }
:root[data-theme="dark"] .hotspot-gw { font-size: 12px; }
.hotspot-gw {
  font: 13px/1 var(--font-mono);
  text-align: right;
  white-space: nowrap;
}
/* The unit rides in the rail header's context on desktop; screen readers
   still hear it. */
.hs-unit {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.hotspot-item-unavailable { cursor: help; }
.hotspot-item-unavailable .hotspot-name,
.hotspot-item-unavailable .hotspot-gw { color: var(--ink-soft); }
.hotspot-item-unavailable .hotspot-gw { font-style: italic; }
.hotspot-unavailable-head {
  padding: 10px 0 6px;
  border-top: 1px dashed var(--hairline);
  font: 10px/1.3 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.hotspot-list:empty::after {
  content: "—";
  display: block;
  padding: 8px 0;
  color: var(--ink-soft);
}

/* Explains what the share view measures. Hidden in the absolute view. */
.hotspot-units-note {
  margin: 0 0 10px;
  max-width: none;
  padding-left: 8px;
  border-left: 2px solid var(--warning);
  font-size: 11px;
  line-height: 1.45;
  color: var(--ink-soft);
}

.rail-note {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  margin: 12px 0 0;
  max-width: none;
  font-size: 13px;
  color: var(--ink);
}
.rail-all { color: var(--ink); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
:root[data-theme="dark"] .rail-all { color: var(--brand-text); text-decoration: none; }
/* Dark names the whole directory in the head instead ("All N", the count
   /regions lists); light keeps "N more curtailing · All regions" below. */
.rail-all-head { display: none; }
:root[data-theme="dark"] .rail-all-head {
  display: inline;
  font: 400 11px/1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-text);
  text-decoration: none;
  white-space: nowrap;
}
:root[data-theme="dark"] .rail-all-head:hover { text-decoration: underline; text-underline-offset: 3px; }
:root[data-theme="dark"] .rail-time { display: none; }
:root[data-theme="dark"] .rail-title {
  font: 400 11px/1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The legend (#globe-legend): each mode keys its own marks. Light lists the
   needle glyphs and the fuels. Dark says "brighter beam = higher confidence"
   (measured 1, anchored 0.8, estimated 0.62) and keys the two shape cues,
   the estimated beam's dashed core and the stale feed's dashed ring; its
   fuels are keyed in the dock's timeline header. */
.globe-legend {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 12px;
  margin-top: 26px;
  font-size: 12.5px;
  color: var(--ink);
}
.legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.legend-needle { display: block; line-height: 0; color: var(--fuel-solar); }
.legend-beam { display: none; line-height: 0; color: var(--fuel-solar); }
.beam-glyph { display: block; overflow: visible; }
.beam-glyph-stale { stroke: var(--quality-warning); }
.legend-fuel .dot { width: 9px; height: 9px; }
.legend-caption { display: none; }
:root[data-theme="dark"] .globe-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 12px;
  margin-top: 0;
  font: 400 10px/1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
:root[data-theme="dark"] .legend-caption { display: block; order: -1; }
:root[data-theme="dark"] :is(.legend-needle, .legend-fuel, .legend-measured, .legend-anchored) { display: none; }
:root[data-theme="dark"] .legend-beam { display: block; }
:root[data-theme="dark"] .legend-item { gap: 5px; }

/* ---- Timeline band ----------------------------------------------------------- */
.app-timeline {
  grid-area: timeline;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "label" "fuels" "plot" "controls";
  gap: 12px;
  padding: 12px 0 16px;
  border-top: 1px solid var(--hairline-strong);
  position: relative;
  z-index: 1;
}
.timeline-label {
  grid-area: label;
  font: 11px/1.3 var(--font-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink);
}
.timeline-fuels {
  grid-area: fuels;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px 16px;
}
.timeline-fuel {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 8px;
  min-height: 26px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink);
}
.timeline-fuel-name { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; }
.timeline-fuel .dot { width: 8px; height: 8px; }
.timeline-fuel-gw { font: 13px/1.2 var(--font-mono); white-space: nowrap; }

.timeline-plot {
  grid-area: plot;
  position: relative;
  min-width: 0;
  padding-top: 18px;
}
.timeline-hours {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 14px;
  font: 11px/1 var(--font-mono);
  color: var(--ink);
}
.timeline-hours span { position: absolute; transform: translateX(-50%); }
.timeline-hours span:nth-child(1) { left: 0; transform: none; }
.timeline-hours span:nth-child(2) { left: 25%; }
.timeline-hours span:nth-child(3) { left: 50%; }
.timeline-hours span:nth-child(4) { left: 75%; }
.timeline-hours span:nth-child(5) { left: 100%; transform: translateX(-100%); }
#timeline-canvas {
  display: block;
  width: 100%;
  height: 104px;
  cursor: ew-resize;
  touch-action: pan-y;
}
/* Dark: the ribbon, its hour labels below it, and the fuel key as a row of
   glowing dots (mocks/dark-desktop.html). The canvas carries 8px of
   headroom for the playhead above the 80px chart. */
:root[data-theme="dark"] .app-timeline { border-top: 0; }
:root[data-theme="dark"] .timeline-label { letter-spacing: 0.08em; }
:root[data-theme="dark"] .timeline-fuels {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
}
:root[data-theme="dark"] .timeline-fuel { min-height: 0; border-bottom: 0; }
:root[data-theme="dark"] .timeline-fuel-name {
  gap: 7px;
  font: 400 11px/1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
:root[data-theme="dark"] .timeline-fuel .dot--solar { box-shadow: 0 0 8px var(--fuel-solar); }
:root[data-theme="dark"] .timeline-fuel .dot--wind { box-shadow: 0 0 8px var(--fuel-wind); }
:root[data-theme="dark"] .timeline-fuel .dot--hydro { box-shadow: 0 0 8px var(--fuel-hydro); }
:root[data-theme="dark"] .timeline-fuel-gw { display: none; }
:root[data-theme="dark"] .timeline-plot { padding: 0 0 20px; }
:root[data-theme="dark"] .timeline-hours {
  top: auto;
  bottom: 0;
  font-size: 10px;
  color: var(--ink-muted);
}
:root[data-theme="dark"] .timeline-hours span:is(:nth-child(1), :nth-child(5)) { transform: translateX(-50%); }
:root[data-theme="dark"] #timeline-canvas { height: 88px; margin-top: -8px; }

.timeline-controls {
  grid-area: controls;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
}
.timeline-controls > * { max-width: 100%; }

/* ---- Controls: play, segmented groups, Now ---------------------------------- */
.ctl-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.ctl-play {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  color: var(--surface-bg-3);
  cursor: pointer;
}
.ctl-play svg { display: block; }
:root[data-theme="dark"] .ctl-play {
  width: 44px;
  height: 44px;
  background: var(--brand);
  color: var(--brand-on);
  box-shadow: 0 0 22px color-mix(in srgb, var(--brand) 40%, transparent);
}

.seg {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  min-height: 34px;
  padding: 3px;
  box-sizing: border-box;
  border: 1px solid var(--hairline-strong);
  border-radius: 17px;
}
:root[data-theme="dark"] .seg { border-color: var(--hairline); padding: 4px; }
.seg-btn,
.ctl-now {
  height: 28px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: 500 13px/1 var(--font-body);
  white-space: nowrap;
  cursor: pointer;
}
.seg-btn:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.seg-btn[aria-pressed="true"] {
  background: var(--ink);
  color: var(--surface-bg-3);
}
:root[data-theme="dark"] .seg-btn[aria-pressed="true"] {
  background: var(--brand-subtle);
  color: var(--brand-text);
}
/* Dark controls speak Mono 10.5 uppercase (redesign plan 3.2). */
:root[data-theme="dark"] :is(.seg-btn, .ctl-now) {
  height: 26px;
  padding: 0 11px;
  font: 400 10.5px/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.ctl-now {
  height: 34px;
  border: 1px solid var(--hairline-strong);
}
:root[data-theme="dark"] .ctl-now { height: 34px; border-color: var(--hairline); }
.ctl-now[aria-pressed="true"] {
  background: var(--ink);
  color: var(--surface-bg-3);
}
:root[data-theme="dark"] .ctl-now[aria-pressed="true"] {
  background: var(--brand-subtle);
  color: var(--brand-text);
}

/* ---- Footer ---------------------------------------------------------------------- */
.app-footer {
  grid-area: footer;
  padding: 16px 0 24px;
  border-top: 1px solid var(--hairline);
  position: relative;
  z-index: 1;
}
.app-footer .caption {
  max-width: 1100px;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.app-footer .caption strong { color: var(--ink-muted); font-weight: 500; letter-spacing: 0.03em; }
.app-footer .caption a { color: var(--brand-text); text-decoration: none; }
.app-footer .caption a:hover { text-decoration: underline; }
.footer-refresh { display: inline-block; margin-left: 6px; }

/* ---- Light desktop: the Almanac grid --------------------------------------------- */
@media (min-width: 1100px) {
  .app-shell {
    grid-template-columns: 396px minmax(0, 1fr) 34px 234px;
    /* The middle row fills the first viewport (76 + row + 152 = 100svh), but
       never less than the hero and rail need: on a short window the band
       moves below the fold rather than the hero running into it. */
    grid-template-rows: 76px minmax(max-content, calc(100svh - 228px)) 152px auto;
    grid-template-areas:
      "header header header header"
      "hero globe . rail"
      "timeline timeline timeline timeline"
      "footer footer footer footer";
    padding: 0 56px;
  }
  .app-header { min-height: 0; padding: 0; flex-wrap: nowrap; }
  .app-lockup { gap: 12px; }
  .app-lockup .app-mark { width: 30px; height: 30px; }
  .app-lockup .app-wordmark { font-size: 18px; }
  .app-header-right { flex-wrap: nowrap; gap: 28px; }
  .app-nav { flex-wrap: nowrap; gap: 28px; }

  .hero { padding: 32px 0 0; }
  .hero-pct { margin: 22px 0 0 -6px; }
  .hero .lead { margin-top: 22px; font-size: 18px; }
  .hero-stats { margin-top: 28px; }

  /* The globe fills its cell; the renderer sizes the sphere to 0.43 of the
     cell's shorter side and centres it. */
  .globe-stage { aspect-ratio: auto; max-height: none; height: 100%; }

  .rail { padding-top: 28px; }

  .app-timeline {
    grid-template-columns: 180px minmax(0, 1fr) 272px;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "label plot controls"
      "fuels plot controls";
    column-gap: 20px;
    row-gap: 12px;
    padding: 12px 0 0;
    align-content: start;
  }
  .timeline-fuels { grid-template-columns: minmax(0, 1fr); gap: 8px; align-self: start; }
  .timeline-plot { padding-top: 18px; }
  .timeline-controls { padding-top: 18px; }
  .timeline-controls .ctl-row { flex-wrap: nowrap; }
  .timeline-controls .seg { flex-wrap: nowrap; }
  /* Play, four speeds (0.5× to 8×) and Now fit the 272px column at 10px padding. */
  :root[data-theme="light"] .ctl-speed .seg-btn { padding: 0 10px; }
}

/* ---- Dark: the Horizon stage (tablet and desktop) ------------------------------ */
/* From 641px the first viewport is a stage (100svh, at least 720px): the
   globe canvas fills it behind the header and the hero, and the dock's two
   glass cells sit at its foot (redesign plan 3.2, section 2). The footer
   follows the stage. Desktop sets the cells side by side; tablet stacks
   them. */
@media (min-width: 641px) {
  :root[data-theme="dark"] .app-shell { max-width: none; padding: 0; }

  /* The stage: the globe's cell spans the stage's rows, and its height sets
     theirs (a 1fr row takes the slack). */
  :root[data-theme="dark"] .globe-stage {
    width: auto;
    height: auto;
    min-height: max(100svh, 720px);
    aspect-ratio: auto;
    max-height: none;
    justify-self: stretch;
  }
  /* A vertical swipe on the stage scrolls the page; a horizontal drag turns
     the globe. */
  :root[data-theme="dark"] #globe-canvas { touch-action: pan-y; }

  :root[data-theme="dark"] .hero {
    width: min(600px, 100%);
    justify-self: start;
    padding: 0;
  }
  /* The scrim that keeps the hero legible over bright beams: a 980 x 760
     box at (-200, -120) on the page, fading from the ground colour. */
  :root[data-theme="dark"] .hero::before {
    content: "";
    position: absolute;
    left: -248px;
    top: -248px;
    width: 980px;
    height: 760px;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--surface-bg-3) 82%, transparent), transparent);
  }
  :root[data-theme="dark"] .hero-pct { margin: 20px 0 0 -8px; }
  :root[data-theme="dark"] .hero .lead { max-width: 470px; margin-top: 24px; font-size: 18px; }
  :root[data-theme="dark"] .hero-stats { margin-top: 32px; }

  :root[data-theme="dark"] :is(.app-timeline, .rail) {
    min-width: 0;
    padding: 18px 24px;
    background: var(--surface-panel);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    border: 1px solid var(--hairline);
    border-radius: 20px;
  }
  /* The ribbon takes whatever width the dock leaves beside the controls,
     so a wider or narrower screen stretches or squashes the chart, not the
     gap between them. */
  :root[data-theme="dark"] .app-timeline {
    grid-template-columns: minmax(0, 1fr) 32px auto;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "label label fuels"
      "plot . controls";
    column-gap: 0;
    row-gap: 18px;
    align-content: start;
    overflow: hidden;
  }
  :root[data-theme="dark"] .timeline-fuels { justify-self: end; align-self: center; }
  /* The plot keeps its own height (ribbon + hour labels 6px under it)
     rather than stretching down the dock with the controls column. */
  :root[data-theme="dark"] .timeline-plot { padding-top: 0; align-self: start; }
  :root[data-theme="dark"] .timeline-controls {
    align-self: start;
    align-items: flex-end;
    gap: 8px;
    margin-top: 8px;
    padding-top: 0;
  }
  :root[data-theme="dark"] .timeline-controls .ctl-row { flex-wrap: nowrap; }

  :root[data-theme="dark"] .rail {
    gap: 10px;
    overflow-y: auto;
    scrollbar-width: thin;
  }
  :root[data-theme="dark"] .rail-head { padding-bottom: 0; }
  :root[data-theme="dark"] .rail-note { display: none; }
  /* The dock lists five; the other five rows stay in the DOM for the modes
     and widths that show ten. */
  :root[data-theme="dark"] .hotspot-item:nth-child(n + 6) { display: none; }
}

/* Desktop: the dock's cells side by side, 196px tall, joined along the
   rail's hairline; the hero at (48, 128). */
@media (min-width: 1100px) {
  :root[data-theme="dark"] .app-shell {
    grid-template-columns: 24px minmax(0, 1fr) 420px 24px;
    grid-template-rows: 76px auto minmax(24px, 1fr) 196px 24px auto;
    grid-template-areas:
      ". header header ."
      ". hero hero ."
      ". . . ."
      ". timeline rail ."
      ". . . ."
      "footer footer footer footer";
  }
  :root[data-theme="dark"] .app-shell > .app-header { padding: 0 24px; }
  :root[data-theme="dark"] .globe-stage { grid-area: 1 / 1 / 6 / -1; }
  /* The label card keeps clear of the dock (196 + 24 + 12). */
  :root[data-theme="dark"] #globe-canvas { --globe-label-clear: 232px; --globe-top-clear: 76px; }
  :root[data-theme="dark"] .hero { margin: 52px 0 0 24px; }
  :root[data-theme="dark"] .app-timeline { border-right: 0; border-radius: 20px 0 0 20px; }
  :root[data-theme="dark"] .rail { border-radius: 0 20px 20px 0; }
  :root[data-theme="dark"] .app-footer { padding: 16px 48px 24px; }
}

/* Tablet: the dock splits into two stacked cards (section 2). */
@media (min-width: 641px) and (max-width: 1099px) {
  :root[data-theme="dark"] .app-shell {
    grid-template-columns: 24px minmax(0, 1fr) 24px;
    grid-template-rows: auto auto minmax(24px, 1fr) auto 12px auto 24px auto;
    grid-template-areas:
      ". header ."
      ". hero ."
      ". . ."
      ". timeline ."
      ". . ."
      ". rail ."
      ". . ."
      "footer footer footer";
  }
  :root[data-theme="dark"] .globe-stage { grid-area: 1 / 1 / 8 / -1; }
  /* The label card keeps clear of both cards. */
  :root[data-theme="dark"] #globe-canvas { --globe-label-clear: 480px; --globe-top-clear: 76px; }
  :root[data-theme="dark"] .hero { margin: 40px 0 0; }
  :root[data-theme="dark"] .app-footer { padding: 16px 24px 24px; }
}

/* Light tablet: hero and globe side by side, the rail and the timeline full
   width below (section 2). */
@media (min-width: 641px) and (max-width: 1099px) {
  :root[data-theme="light"] .app-shell {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "header header"
      "hero globe"
      "rail rail"
      "timeline timeline"
      "footer footer";
    column-gap: 32px;
    padding: 0 24px;
  }
  :root[data-theme="light"] .globe-stage { align-self: center; }
  :root[data-theme="light"] .rail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 232px;
    grid-template-areas: "head head" "note legend" "list legend" "more legend";
    column-gap: 40px;
    align-content: start;
    padding-top: 28px;
  }
  :root[data-theme="light"] .rail-head { grid-area: head; }
  :root[data-theme="light"] .hotspot-units-note { grid-area: note; }
  :root[data-theme="light"] .hotspot-list { grid-area: list; }
  :root[data-theme="light"] .rail-note { grid-area: more; }
  :root[data-theme="light"] .globe-legend { grid-area: legend; align-self: start; margin-top: 0; }
  :root[data-theme="light"] .timeline-controls { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
}

/* ---- The header's menu (below 960px) ------------------------------------------------ */
/* Below 960px the nav and the DOI pill do not fit beside the lockup, so they
   move into a menu under the header; src/components/site-chrome.js opens it.
   The nav keeps its place in the DOM and its landmark. */
.app-menu-btn {
  display: none;
  width: 44px;
  height: 44px;
  flex: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.app-menu-btn:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.app-menu-btn svg { display: block; }
.app-nav a[aria-current="page"] { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
@media (max-width: 960px) {
  .app-header { flex-wrap: nowrap; }
  .app-header-right { flex-wrap: nowrap; gap: 4px; }
  .app-menu-btn { display: inline-flex; }
  .app-nav { display: none; }
  .app-header.is-menu-open .app-nav {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    position: absolute;
    top: calc(100% + 1px);
    right: 0;
    z-index: 40;
    min-width: 232px;
    padding: 6px 0;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
  }
  :root[data-theme="dark"] .app-header.is-menu-open .app-nav {
    background: var(--surface-panel);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    border-color: var(--hairline);
    border-radius: 12px;
  }
  .app-header.is-menu-open .app-nav a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 18px;
    font-size: 16px;
  }
  .app-header.is-menu-open .app-nav .app-version {
    align-self: flex-start;
    min-height: 0;
    margin: 8px 18px 8px;
    padding: 7px 10px;
    font-size: 12px;
  }
}

/* ---- The doc pages' header ------------------------------------------------------------ */
/* observablehq.config.ts puts src/lib/site-header.ts's header in Framework's
   header slot, which is a fixed bar with a look of its own. Ours sits in the
   page's flow, like the dashboard's, and reads the same .app-header rules. */
#observablehq-header {
  position: relative;
  inset: auto;           /* Framework's left/right place its fixed bar; they would shift ours */
  z-index: 30;
  display: block;
  height: auto;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
}
:root:has(#observablehq-header) { scroll-padding-top: 2.5rem; }
/* The header meets the top of the page, as the dashboard's does. */
#observablehq-center:has(> #observablehq-header) { margin-top: 0; }
#observablehq-header ~ #observablehq-main { margin-top: 0; }
.site-header {
  min-height: 64px;
  padding: 0;
  border-bottom: 1px solid var(--hairline);
}
@media (min-width: 1100px) {
  .site-header { min-height: 76px; padding: 0 24px; }
}
@media (max-width: 640px) {
  /* Edge to edge whatever gutters the page keeps, then the phone header's
     own 16/20px, as the dashboard's. */
  #observablehq-header { margin-inline: calc(50% - 50vw); }
  .site-header { height: 64px; margin: 0 16px 0 20px; }
}

/* ---- Phones (≤640px), both modes ------------------------------------------------------ */
.explore-btn,
.explorer-close,
.explorer-bar,
.sheet-handle { display: none; }
/* Outside the phone sheet the dock is only a wrapper: its sections are the
   page grid's own items. */
.dock { display: contents; }

@media (max-width: 640px) {
  .app-shell { padding: 0 16px 0 20px; }
  .app-shell > .app-header { height: 64px; min-height: 64px; padding: 0; gap: 8px; }
  .app-lockup .app-wordmark { white-space: nowrap; }
  .hero-pct { font-size: var(--fs-hero); }
  .hero .lead { font-size: 16px; }
  .globe-zoom-controls { display: none; }
  /* The network hashrate is left out on phones, as both phone boards do. */
  .hero-stats .stat:nth-child(2) { display: none; }

  /* The phone globe is a picture, so a vertical swipe scrolls the page;
     "Explore the globe" opens it full screen (section 6.4). */
  #globe-canvas { pointer-events: none; touch-action: auto; cursor: default; }
  .explore-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    z-index: 2;
    height: 44px;
    padding: 0 16px;
    border-radius: 999px;
    font: 500 14px/1 var(--font-body);
    white-space: nowrap;
    cursor: pointer;
  }

  .timeline-fuels { grid-template-columns: minmax(0, 1fr); }
  /* The controls wrap: play, speeds and Now; then the time window and the
     units, each full width. */
  .timeline-controls { align-items: stretch; }
  .timeline-controls > :is(#mode-toggle, #units-toggle) .seg { display: flex; width: 100%; }
  .timeline-controls > :is(#mode-toggle, #units-toggle) .seg-btn { flex: 1 1 0; }
}

/* ---- Light phone (redesign plan 3.3) ----------------------------------------------- */
@media (max-width: 640px) {
  /* The hero's parts join the page's column so the stats can follow the
     globe, as the board draws them. */
  :root[data-theme="light"] .app-shell { display: flex; flex-direction: column; }
  :root[data-theme="light"] .hero { display: contents; }
  :root[data-theme="light"] :is(.hero-eyebrow, .hero-pct, .hero .lead) { order: 1; }
  :root[data-theme="light"] .globe-stage { order: 2; }
  :root[data-theme="light"] .hero-stats { order: 3; }
  :root[data-theme="light"] .rail { order: 4; }
  :root[data-theme="light"] .app-timeline { order: 5; }
  :root[data-theme="light"] .app-footer { order: 6; }
  /* The figure caption has no room on the board; the legend below keys the
     needles. */
  :root[data-theme="light"] .hero-caption { display: none; }

  :root[data-theme="light"] .hero-eyebrow { display: flex; flex-wrap: wrap; margin-top: 22px; font-size: 11px; }
  :root[data-theme="light"] .hero-eyebrow-time { display: inline; order: 1; }
  :root[data-theme="light"] .hero-eyebrow-time::before { content: "\00a0·\00a0"; }
  :root[data-theme="light"] .hero-pct { margin: 16px 0 0 -4px; }
  :root[data-theme="light"] .hero .lead { margin-top: 16px; }

  /* The globe bleeds past both edges: a (width + 30) square at (-15, -12)
     in a figure 372/390 of the width tall. */
  :root[data-theme="light"] .globe-stage {
    width: auto;
    height: calc(100vw * 372 / 390);
    aspect-ratio: auto;
    max-height: none;
    margin: 34px -16px 0 -20px;
    overflow: hidden;
  }
  :root[data-theme="light"] #globe-canvas {
    inset: auto;
    left: -15px;
    top: -12px;
    width: calc(100vw + 30px);
    height: calc(100vw + 30px);
  }
  :root[data-theme="light"] .explore-btn {
    right: 20px;
    bottom: 6px;
    border: 0;
    background: var(--ink);
    color: var(--surface-bg-3);
  }

  :root[data-theme="light"] .hero-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin: 14px 0 0;
    border-top: 1px solid var(--hairline-strong);
    border-bottom: 1px solid var(--hairline);
  }
  :root[data-theme="light"] .hero-stats .stat {
    flex-direction: column-reverse;
    justify-content: flex-end;
    align-items: flex-start;
    gap: 4px;
    min-width: 0;
    padding: 10px 0;
    border-top: 0;
  }
  :root[data-theme="light"] .hero-stats .stat:nth-child(3) { padding-left: 14px; border-left: 1px solid var(--hairline); }
  :root[data-theme="light"] .stat-label { font-size: 12.5px; }

  :root[data-theme="light"] .rail { padding-top: 18px; }
  :root[data-theme="light"] .rail-title { font-size: 23px; }
  :root[data-theme="light"] .hotspot-item {
    grid-template-columns: 22px 26px minmax(0, 1fr) auto;
    padding: 10px 0;
    font-size: 15px;
  }
  :root[data-theme="light"] .hotspot-gw { font-size: 14px; }
  /* The rows carry their unit on phones, as the board does. */
  :root[data-theme="light"] .hs-unit { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
}

/* ---- Dark phone (redesign plan 3.4) ------------------------------------------------ */
/* One screen: the header and the hero over the sky, the horizon in a band
   under them, and the dock as a sheet fixed to the bottom (132px collapsed,
   70% of the viewport open; src/components/sheet.js). The two stats ride at
   the sheet's top. */
@media (max-width: 640px) {
  :root[data-theme="dark"] .app-shell {
    --sheet-h: 132px;
    display: block;
    position: relative;
  }
  :root[data-theme="dark"] .app-shell:has(.dock.is-open) { --sheet-h: 70svh; }
  :root[data-theme="dark"] .app-shell > .app-header { position: relative; z-index: 10; }

  /* The hero fills the first screen, so the footer follows it. It opens no
     stacking context: its stats sit in the sheet, above the glass. */
  :root[data-theme="dark"] .hero {
    z-index: auto;
    min-height: calc(100svh - 64px);
    padding: 16px 0 0;
  }
  :root[data-theme="dark"] :is(.hero-eyebrow, .hero-pct, .hero .lead) { position: relative; z-index: 1; }
  :root[data-theme="dark"] .hero-eyebrow { font-size: 10px; }
  :root[data-theme="dark"] .hero-eyebrow::before { width: 6px; height: 6px; margin-right: 8px; box-shadow: none; }
  :root[data-theme="dark"] .hero-pct { margin: 14px 0 0 -5px; }
  :root[data-theme="dark"] .hero .lead { margin-top: 16px; font-size: 15px; }

  /* The band: from 314px on an 844px screen to the bottom (390 x 530). */
  /* justify-self: stretch - box alignment applies to absolute boxes too, and
     the base rule's `center` would shrink the band to its (empty) content. */
  :root[data-theme="dark"] .globe-stage {
    position: absolute;
    left: 0;
    right: 0;
    top: max(250px, calc(100svh - 530px));
    height: min(530px, calc(100svh - 250px));
    width: auto;
    aspect-ratio: auto;
    max-height: none;
    margin: 0;
    justify-self: stretch;
    align-self: stretch;
  }
  :root[data-theme="dark"] .explore-btn {
    left: 50%;
    bottom: 190px;
    transform: translateX(-50%);
    padding: 0 18px;
    border: 1px solid var(--hairline);
    background: color-mix(in srgb, var(--surface-panel) 95%, transparent);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    color: var(--ink);
  }

  :root[data-theme="dark"] .dock {
    position: fixed;
    left: 8px;
    right: 8px;
    bottom: 8px;
    z-index: 30;
    height: var(--sheet-h);
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    padding: 0 16px 14px;
    overflow: hidden;
    background: color-mix(in srgb, var(--surface-bg-3) 82%, transparent);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border: 1px solid var(--hairline);
    border-radius: 20px;
    transition: height 220ms var(--ease-out, cubic-bezier(0.2, 0.8, 0.2, 1));
  }
  :root[data-theme="dark"] .dock.is-open { overflow-y: auto; overscroll-behavior: contain; }
  :root[data-theme="dark"] .dock:focus-visible { outline-offset: -2px; }
  /* Room for the stats, which are the hero's and ride here. */
  :root[data-theme="dark"] .dock::before { content: ""; order: 1; flex: none; height: 58px; }
  :root[data-theme="dark"] .sheet-handle {
    display: flex;
    order: 0;
    flex: none;
    justify-content: center;
    align-items: flex-start;
    width: 100%;
    height: 24px;
    padding: 10px 0 0;
    border: 0;
    background: transparent;
    cursor: grab;
    touch-action: none;
  }
  :root[data-theme="dark"] .sheet-handle-bar {
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--ink-muted) 45%, transparent);
  }
  :root[data-theme="dark"] .sheet-handle-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  :root[data-theme="dark"] .hero-stats {
    position: fixed;
    left: 25px;
    right: 25px;
    bottom: calc(8px + var(--sheet-h) - 1px - 24px - 46px);
    z-index: 31;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    height: 46px;
    margin: 0;
    transition: bottom 220ms var(--ease-out, cubic-bezier(0.2, 0.8, 0.2, 1));
  }
  :root[data-theme="dark"] .hero-stats .stat { gap: 6px; padding: 0; }
  :root[data-theme="dark"] .hero-stats .stat:nth-child(3) { padding-left: 16px; border-left-color: var(--hairline); }
  :root[data-theme="dark"] .stat-label { font-size: 10px; }
  :root[data-theme="dark"] .stat-value { font-size: 28px; }

  /* Collapsed: the region that leads, under a hairline. */
  :root[data-theme="dark"] .rail { order: 3; padding: 0; min-width: 0; }
  :root[data-theme="dark"] .app-timeline { order: 2; padding: 16px 0 0; gap: 12px; }
  :root[data-theme="dark"] .dock:not(.is-open) .app-timeline { display: none; }
  :root[data-theme="dark"] .dock:not(.is-open) .rail > :not(.hotspot-list) { display: none; }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-list {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--hairline);
  }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-list > :not(:first-child) { display: none; }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-item:first-child {
    grid-template-columns: 8px minmax(0, 1fr) auto;
    column-gap: 8px;
  }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-item:first-child::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 8px currentColor;
  }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-item:first-child .hotspot-name::after { content: " leads"; }
  :root[data-theme="dark"] .dock:not(.is-open) .hotspot-item:first-child .hs-bar { display: none; }
  :root[data-theme="dark"] .hs-unit { position: static; width: auto; height: auto; overflow: visible; clip: auto; }

  /* Open: the ribbon and the controls, then the top ten and the legend. */
  :root[data-theme="dark"] .dock.is-open .rail { gap: 10px; padding-top: 20px; }
  :root[data-theme="dark"] .dock.is-open .rail-note { display: none; }
  :root[data-theme="dark"] .dock.is-open .hotspot-item { grid-template-columns: minmax(0, 1fr) 72px 60px; }
  :root[data-theme="dark"] .timeline-fuels { justify-content: flex-start; }

  /* The page scrolls above the collapsed sheet. */
  :root[data-theme="dark"] .app-footer { padding-bottom: calc(132px + 32px); }
}

/* ---- The explorer (phones, both modes; redesign plan 6.4) ------------------------ */
/* The globe's own stage, fixed over the page (src/components/explorer.js).
   `:root` lifts these over the phone layouts' mode-scoped rules. */
html.is-exploring,
html.is-exploring body { overflow: hidden; }
:root .globe-stage.is-exploring {
  position: fixed;
  inset: 0;
  z-index: 100;
  justify-self: stretch;
  align-self: stretch;
  width: auto;
  height: auto;
  min-height: 0;
  max-height: none;
  aspect-ratio: auto;
  margin: 0;
  overflow: hidden;
  background: var(--surface-bg-3);
}
:root .globe-stage.is-exploring #globe-canvas {
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: auto;
  touch-action: none;
  cursor: grab;
}
.globe-stage.is-exploring .explore-btn { display: none; }
.globe-stage.is-exploring .explorer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: calc(10px + env(safe-area-inset-top, 0px));
  right: 12px;
  z-index: 3;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--hairline-strong);
  background: var(--surface-raised);
  color: var(--ink);
  cursor: pointer;
}
.globe-stage.is-exploring .explorer-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: 3;
  padding: 6px 16px 6px 6px;
  border-radius: 999px;
  border: 1px solid var(--hairline-strong);
  background: var(--surface-raised);
}
:root[data-theme="dark"] .globe-stage.is-exploring :is(.explorer-close, .explorer-bar) {
  border-color: var(--hairline);
  background: var(--surface-panel);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}
.explorer-bar .ctl-play { width: 44px; height: 44px; }
.explorer-scrub { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.explorer-time { font: 11px/1.2 var(--font-mono); letter-spacing: 0.06em; color: var(--ink); }
.explorer-range { width: 100%; margin: 0; accent-color: var(--ink); }
:root[data-theme="dark"] .explorer-range { accent-color: var(--brand); }
/* The selection is a card above the bar, not a label by its mark. */
.globe-stage.is-exploring .globe-selection {
  left: 12px !important;
  right: 12px;
  top: auto !important;
  bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  width: auto;
}

/* =========================================================================
   REGION TOOLTIP — floating card shown on globe hotspot click
   ========================================================================= */

.region-tooltip {
  position: fixed;
  z-index: 100;
  width: 260px;
  padding: 12px 14px 10px;
  background: var(--surface-raised);
  border-radius: 12px;
  border: 1px solid var(--hairline-strong);
  color: var(--ink);
  font-size: 12px;
  line-height: 1.4;
  pointer-events: auto;
  animation: region-tooltip-in 140ms var(--ease-out, cubic-bezier(0.2, 0.8, 0.2, 1));
}

@keyframes region-tooltip-in {
  from { opacity: 0; transform: translateY(4px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.region-tooltip[hidden] { display: none; }

.region-tooltip-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: transparent;
  border: none;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
  transition: background 120ms, color 120ms;
}
.region-tooltip-close:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
}

.region-tooltip-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 22px;
  margin-bottom: 8px;
}
.region-tooltip-titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.region-tooltip-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.region-tooltip-country {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
  margin-top: 1px;
}

.region-tooltip-stats {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 8px;
}
.region-tooltip-stat {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
}
.region-tooltip-stat > span:first-child {
  color: var(--ink-soft);
}
.region-tooltip-stat > span:last-child {
  color: var(--ink);
  font-weight: 500;
}

.region-tooltip-sparkline {
  display: block;
  width: 100%;
  height: 48px;
  margin: 4px 0 8px;
  border-radius: 4px;
}

.region-tooltip-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--hairline);
  font-size: 11px;
}
.region-tooltip-footer a {
  color: var(--brand-text);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 60%;
}
.region-tooltip-footer a:hover { text-decoration: underline; }

.region-tooltip-freshness-live {
  color: var(--success);
  font-size: 10.5px;
  white-space: nowrap;
}
.region-tooltip-freshness-cached {
  color: var(--warning);
  font-size: 10.5px;
  white-space: nowrap;
}
.region-tooltip-freshness-degraded {
  color: var(--quality-warning);
  font-size: 10.5px;
  white-space: nowrap;
}
.region-tooltip-freshness-modeled,
.region-tooltip-freshness-anchored {
  color: var(--ink-soft);
  font-size: 10.5px;
  white-space: nowrap;
}

.region-tooltip-note {
  margin-top: 4px;
  font-size: 10px;
  line-height: 1.35;
  color: var(--ink-soft);
}

.region-tooltip-fuel-swatch {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 2px;
}

/* The detail card in light: paper, a 1px ink rule and no shadow, the name
   in the display face (redesign plan 6.1). */
:root[data-theme="light"] .region-tooltip {
  border: 1px solid var(--hairline-strong);
  border-radius: 0;
}
:root[data-theme="light"] .region-tooltip-name {
  font-family: var(--font-display);
  font-weight: var(--display-weight-base);
  font-size: 20px;
  line-height: 1.15;
}

/* Dark: glass, like the dock (redesign plan 6.1). */
:root[data-theme="dark"] .region-tooltip {
  background: var(--surface-panel);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  border: 1px solid var(--hairline);
  border-radius: 12px;
}

/* Fuel dots: coloured from the fuel tokens at paint time, so they always
   match the canvas marks whichever mode is active. */
.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}

/* Fuel-themed dots — resolved at paint time from CSS custom properties so
   they always match the canvas bars regardless of which theme is active.
   Avoids the bake-at-eval bug that occurred when inline style="background:
   getFuelColor()" was called before the mode's CSS had resolved. */
.dot--solar {
  background: var(--fuel-solar);
}
.dot--wind {
  background: var(--fuel-wind);
}
.dot--hydro {
  background: var(--fuel-hydro);
}

/* Touch targets on the detail card's close button (iOS 44, Material 48). */
@media (hover: none) {
  .region-tooltip-close {
    font-size: 24px;
    padding: 6px 10px;
    min-width: 36px;
    min-height: 36px;
  }
}

/* Tooltip width shouldn't overflow narrow viewports. */
@media (max-width: 400px) {
  .region-tooltip {
    width: min(260px, calc(100vw - 20px));
  }
}

main > h1:first-child {
  display: none;
}

/* =========================================================================
   METHODOLOGY PAGE — academic typography pass
   ========================================================================= */

/* Back-nav that appears at the top of Methodology and About pages when the
   Framework sidebar is disabled (sidebar: false in observablehq.config.ts). */
.page-back-nav {
  max-width: 780px;
  margin: 0 auto;
  padding: 20px 32px 0;
}
.page-back-nav a {
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand-text);
  text-decoration: none;
  transition: color 0.15s;
}
.page-back-nav a:hover {
  color: var(--brand-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.methodology-doc {
  max-width: 780px;
  margin: 0 auto;
  padding: 24px 32px 96px;
  color: var(--ink);
  font-size: 15px;
  line-height: 1.68;
}

.methodology-doc .methodology-header {
  padding-bottom: 28px;
  margin-bottom: 44px;
  border-bottom: 1px solid var(--hairline);
}

.methodology-doc .methodology-eyebrow {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-text);
  margin-bottom: 14px;
}

.methodology-doc h1 {
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.12;
  margin: 0 0 18px;
  color: var(--ink);
  border-bottom: none;
  padding-bottom: 0;
}

.methodology-doc .methodology-deck {
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 680px;
  margin: 0 0 20px;
}


.methodology-doc h2 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin: 56px 0 16px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink);
}

.methodology-doc h3 {
  font-size: 16px;
  font-weight: 600;
  margin: 32px 0 8px;
  color: var(--ink);
}

.methodology-doc p {
  margin: 0 0 16px;
  color: var(--ink-muted);
}

.methodology-doc strong {
  color: var(--ink);
  font-weight: 600;
}

.methodology-doc a {
  color: var(--brand-text);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
  transition: border-color 140ms, color 140ms;
}
.methodology-doc a:hover {
  color: var(--ink);
  border-bottom-color: var(--brand);
}
/* Framework wraps each heading's text in a self-link
   (.observablehq-header-anchor). That is navigation, not a reference, so it
   takes no link rule: with one, every heading on the doc pages was
   underlined. */
.methodology-doc a.observablehq-header-anchor {
  border-bottom: 0;
}

.methodology-doc ul,
.methodology-doc ol {
  padding-left: 24px;
  margin: 0 0 18px;
}
.methodology-doc li {
  margin-bottom: 8px;
  color: var(--ink-muted);
}
.methodology-doc li::marker {
  color: var(--ink-soft);
}

.methodology-doc code {
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 2px 6px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  color: var(--ink);
}

.methodology-doc pre {
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 14px 16px;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.5;
  margin: 16px 0 24px;
}
.methodology-doc pre code {
  background: none;
  padding: 0;
}

/* Bare URLs, file paths and filenames are single unbroken runs wider than a
   phone, and one of them was enough to lay /methodology out 446px wide at 375.
   They turn up as link text, in inline code and in plain source strings
   (region pages print `source:` text verbatim), so the whole doc column lets
   a run break anywhere. `anywhere` rather than `break-word` because it also
   lowers the run's min-content width, which is what lets the grid track
   holding a source URL on /region/<id> shrink back to the viewport. Tables and
   code blocks opt out: both already scroll sideways inside their own box, and
   breaking their contents would squeeze them instead. */
.methodology-doc {
  overflow-wrap: anywhere;
}
.methodology-doc :is(table, pre) {
  overflow-wrap: normal;
}

/* Tables */
.methodology-doc table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0 28px;
  font-size: 13px;
}
.methodology-doc th,
.methodology-doc td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
}
.methodology-doc th {
  font-weight: 600;
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--hairline-strong);
}
.methodology-doc td {
  color: var(--ink-muted);
}
.methodology-doc tr:hover td {
  background: color-mix(in srgb, var(--ink) 3%, transparent);
}

/* Callout boxes */
.methodology-doc .methodology-callout {
  padding: 20px 24px;
  margin: 20px 0 28px;
  border-left: 3px solid var(--brand);
  background: rgba(var(--brand-rgb),0.04);
  border-radius: 0 6px 6px 0;
}
.methodology-doc .methodology-callout p:last-child {
  margin-bottom: 0;
}
.methodology-doc .methodology-callout-abstract {
  font-size: 15.5px;
  line-height: 1.65;
}
.methodology-doc .methodology-callout-abstract p {
  color: var(--ink);
}

/* Horizontal rules */
.methodology-doc hr {
  border: none;
  border-top: 1px solid var(--hairline);
  margin: 40px 0;
}

/* References (§7) — compact list style */
.methodology-doc h2[id="references"] + ul {
  font-size: 13px;
  line-height: 1.55;
  padding-left: 0;
  list-style: none;
}
.methodology-doc h2[id="references"] + ul li {
  padding: 7px 0;
  border-bottom: 1px dotted var(--hairline);
  color: var(--ink-muted);
}
.methodology-doc h2[id="references"] + ul li strong {
  color: var(--ink);
  font-weight: 500;
}

/* Trailing italic author note */
.methodology-doc p em:only-child {
  display: inline-block;
  font-size: 13px;
  color: var(--ink-soft);
  font-style: italic;
  line-height: 1.5;
}

@media (max-width: 700px) {
  .methodology-doc {
    padding: 16px 18px 64px;
    font-size: 14.5px;
  }
  .methodology-doc h1 { font-size: 32px; }
  .methodology-doc .methodology-deck { font-size: 16px; }
  .methodology-doc h2 { font-size: 20px; margin-top: 40px; }
}

/* ============ THEME TOGGLE ============
   Two looks, one component (src/components/theme-toggle.js). Desktop: a
   34px pill holding a sun and a moon, the active one filled with ink and its
   icon drawn in the page colour. Phones (the `compact` option): one 44px
   round button showing the mode it switches TO. Icons stroke in currentColor.
   Focus uses the global :focus-visible ring. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 34px;
  padding: 3px;
  box-sizing: border-box;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
}
:root[data-theme="dark"] .theme-toggle { border-color: var(--hairline); }
.theme-toggle button {
  width: 40px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.theme-toggle button:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.theme-toggle button[aria-checked="true"] {
  background: var(--ink);
  color: var(--surface-bg-3);
}
.theme-toggle svg { display: block; flex-shrink: 0; }

.theme-toggle--compact {
  width: 44px;
  height: 44px;
  padding: 0;
  justify-content: center;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.theme-toggle--compact:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }

/* Switching mode cross-fades where the browser has view transitions. The
   toggle skips the transition under prefers-reduced-motion. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 200ms;
}

/* Links in light are ink with an underline: the brand colour is 3.2:1 on
   paper, too low for small text. Dark keeps amber (11.5:1) without one. */
:root[data-theme="light"] :is(.page-back-nav a, .app-footer .caption a, .region-tooltip-footer a) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* State labels in the region card are small text. In light, --success and
   --warning fall under 4.5:1 on paper, so the labels go ink; the words
   ("live", "cached", "degraded") carry the state either way. */
:root[data-theme="light"] :is(.region-tooltip-freshness-live, .region-tooltip-freshness-cached, .region-tooltip-freshness-degraded) {
  color: var(--ink);
}

/* ============ QUALITY DOTS ============
   The G1 globe's base-dot vocabulary, which the region pages (/regions,
   /region/<id>) use. The dashboard's legend keys its own marks. */
.ql-dot {
  display: inline-block; width: 12px; height: 12px; border-radius: 50%;
  flex: 0 0 auto; box-sizing: border-box;
}
.ql-measured { background: var(--ink); }
.ql-anchored { background: var(--ink); box-shadow: 0 0 0 2px var(--surface-bg-2), 0 0 0 3px var(--ink); }
.ql-estimated { background: transparent; border: 1.5px solid var(--ink); }
.ql-degraded { background: transparent; border: 1.5px dashed var(--quality-warning); }

/* =========================================================================
   REGION PAGES — the /regions directory and the /region/<id> records
   =========================================================================
   Both surfaces sit inside .methodology-doc, so the type scale, link colours,
   table styling, and both theme token sets already apply. Nothing here
   introduces a colour value: every rule reads --ink / --ink-muted /
   --ink-soft / --hairline / --brand-rgb / --surface-*, which
   :root[data-theme="light"] and :root[data-theme="dark"] both
   define. Quality dots use the .ql-dot vocabulary above. */

.page-back-sep { color: var(--ink-soft); margin: 0 6px; }

/* ---- Shared: the identity facts strip under a page's deck --------------- */
.region-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px 24px;
  margin: 22px 0 0;
}
.region-facts .region-fact dt {
  font: 500 11px/1.2 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 5px;
}
.region-facts .region-fact dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink);
}

/* ---- /region/<id>: the provenance panel --------------------------------
   Deliberately the first thing under the header. This project's value is
   honesty about data quality, so the tier, its envelope, and what the tier
   means are not allowed to sit below the fold. */
.region-doc .region-provenance {
  border: 1px solid var(--hairline-strong);
  border-left: 3px solid rgba(var(--brand-rgb), 0.7);
  border-radius: var(--r-md);
  background: var(--surface-raised);
  padding: 20px 24px;
  margin: 0 0 44px;
}
.region-doc .region-provenance-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.region-doc .region-provenance-title {
  font: 600 13px/1.2 var(--font-body);
  letter-spacing: 0.02em;
  color: var(--ink-muted);
}
.region-quality-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px 4px 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-pill);
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--surface-bg-2);
}
.region-doc .region-provenance-grid { margin: 0; display: grid; gap: 16px; }
.region-doc .region-provenance-row {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 4px 20px;
}
.region-doc .region-provenance-row dt {
  font: 500 11px/1.5 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.region-doc .region-provenance-row dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink);
}
.region-doc .region-provenance-row dd p {
  margin: 5px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-muted);
}
.region-doc .region-provenance-row dd p.region-provenance-note {
  color: var(--ink-soft);
  font-style: italic;
}
.region-doc .region-provenance-foot {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-soft);
}
.region-doc .region-doc-foot {
  font-size: 13px;
  color: var(--ink-muted);
}

/* ---- /regions: legend, filter, and list --------------------------------- */
.region-directory { max-width: 980px; }

.region-legend {
  list-style: none;
  padding: 16px 20px;
  margin: 0 0 10px;
  display: grid;
  gap: 9px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-raised);
  font-size: 13px;
}
.region-legend li {
  display: flex;
  align-items: baseline;
  gap: 9px;
  color: var(--ink-muted);
  margin: 0;
  padding: 0;
}
.region-legend .ql-dot { position: relative; top: 2px; }
.region-legend strong { color: var(--ink); font-weight: 600; }
.region-legend-count {
  margin-left: auto;
  padding-left: 14px;
  white-space: nowrap;
  font: 500 11px/1 var(--font-mono);
  color: var(--ink-soft);
}
.region-directory .region-legend-foot {
  font-size: 12px;
  color: var(--ink-soft);
  margin: 0 0 28px;
}

.region-filter {
  display: grid;
  gap: 16px;
  padding: 18px 20px;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-md);
  background: var(--surface-bg-2);
  margin-bottom: 20px;
}
.region-filter-search { display: grid; gap: 6px; }
.region-filter-search label {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.region-filter input[type="search"] {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  font: 400 15px/1.3 var(--font-body);
  color: var(--ink);
  background: var(--surface-bg-3);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-sm);
}
.region-filter input[type="search"]:focus-visible,
.region-filter select:focus-visible,
.region-chip input:focus-visible + span {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-color: rgba(var(--brand-rgb), 0.6);
}
.region-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 28px;
}
.region-chip-group { border: 0; margin: 0; padding: 0; min-width: 0; }
.region-chip-group legend {
  padding: 0 0 7px;
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.region-chip { display: inline-block; margin: 0 6px 6px 0; cursor: pointer; }
.region-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.region-chip span {
  display: inline-block;
  padding: 5px 11px;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-pill);
  font: 500 12px/1.2 var(--font-mono);
  color: var(--ink-muted);
  background: var(--surface-raised);
  transition: color var(--dur-fast, 120ms) ease, border-color var(--dur-fast, 120ms) ease;
}
.region-chip:hover span { color: var(--ink); }
.region-chip input:checked + span {
  color: var(--brand-on);
  background: var(--brand);
  border-color: var(--brand);
}
.region-filter select {
  padding: 7px 10px;
  font: 400 13px/1.2 var(--font-body);
  color: var(--ink);
  background: var(--surface-raised);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-sm);
  max-width: 100%;
}
.region-filter-status {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  border-top: 1px solid var(--hairline);
  padding-top: 14px;
}
.region-directory .region-count {
  margin: 0;
  font-size: 13px;
  color: var(--ink-muted);
}
.region-filter-reset {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 7px 13px;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
}
.region-filter-reset:hover { color: var(--ink); border-color: var(--ink-soft); }

.region-list {
  list-style: none;
  padding: 0;
  margin: 0 0 32px;
  border-top: 1px solid var(--hairline);
}
.region-list .region-row { margin: 0; padding: 0; }
.region-list .region-row[hidden] { display: none; }
.region-row > a {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 14px;
  padding: 11px 10px;
  border-bottom: 1px solid var(--hairline);
  text-decoration: none;
  color: inherit;
  border-left: 2px solid transparent;
}
.region-row > a:hover {
  background: var(--surface-raised);
  border-left-color: rgba(var(--brand-rgb), 0.7);
  text-decoration: none;
}
/* Wrap rather than truncate. The name and the id are both things a reader
   might be here to copy — an ellipsis in either is a lossy reference page. */
.region-row-main {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 10px;
  min-width: 0;
}
.region-row-name { font-size: 14.5px; color: var(--ink); }
.region-row-id { font: 400 11px/1.4 var(--font-mono); color: var(--ink-soft); }
.region-row-meta {
  font-size: 12px;
  color: var(--ink-muted);
  white-space: nowrap;
}
.region-row-tier {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-pill);
  padding: 4px 9px;
  white-space: nowrap;
}
.region-directory .region-empty {
  padding: 28px 0;
  text-align: center;
  color: var(--ink-muted);
}

@media (max-width: 760px) {
  .region-doc .region-provenance { padding: 16px 16px; }
  .region-doc .region-provenance-row { grid-template-columns: 1fr; }
  /* Let the per-bucket count drop below its definition rather than squeezing
     the definition into a two-word column. */
  .region-legend li { flex-wrap: wrap; }
  .region-legend-count { flex: 1 0 100%; margin-left: 21px; padding-left: 0; }
  .region-row > a { grid-template-columns: 12px minmax(0, 1fr); gap: 4px 12px; }
  .region-row-main { flex-direction: column; gap: 2px; }
  .region-row-meta,
  .region-row-tier { grid-column: 2; justify-self: start; }
  .region-row-tier { margin-top: 4px; }
}

/* The .ql-anchored ring paints its gap in --surface-bg-2, which is the globe
   legend's own background. Repaint it where the directory puts a dot on a
   raised surface, so the ring reads as a ring and not as a smudge. */
.region-legend .ql-anchored,
.region-row > a:hover .ql-anchored {
  box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 3px var(--ink);
}

/* ---------------------------------------------------------------------------
   /history — the historical record page (src/history.md.js)

   Every chart on that page is inline SVG emitted by the page loader, so all of
   its colour lives here rather than in the markup. That is what makes the
   figures theme-aware for free: the loader runs under node, where
   getFuelColor() can only return its fallback hex, so baking colours
   server-side would freeze one theme's palette into the page. The SVG carries
   classes and var(--fuel-*) references; these rules resolve them per theme.
   --------------------------------------------------------------------------- */

.history-doc { max-width: 980px; }

.hc-figure {
  margin: 0 0 32px;
  padding: 18px 20px 14px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-raised);
}
.hc-figcaption {
  font-size: 13px;
  line-height: var(--lh-body);
  color: var(--ink-muted);
  margin: 0 0 12px;
}
.hc-figcaption strong { color: var(--ink); }

/* Wide charts scroll inside their own container rather than forcing the page
   to scroll sideways. A 75-month axis cannot be read at 390px scaled to fit —
   the year labels collapse into each other — so below the min-width the figure
   pans instead of shrinking. */
.hc-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
.hc-scroll > svg {
  display: block;
  width: 100%;
  min-width: 560px;
  height: auto;
}

.hc-legend {
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
  gap: 16px;
  flex-wrap: wrap;
  color: var(--ink-muted);
}
.hc-swatch {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 2px;
  margin-right: 7px;
  vertical-align: -1px;
}
.hc-swatch--band {
  background: rgba(var(--brand-rgb), 0.18);
  border: 1px solid rgba(var(--brand-rgb), 0.45);
}

/* Chart internals. Fills come from the markup (var(--fuel-*)); everything
   structural is themed here. */
.hc-grid { stroke: var(--hairline); stroke-width: 1; }
.hc-axis { stroke: var(--hairline-strong); stroke-width: 1; }
.hc-tick {
  fill: var(--ink-soft);
  font: 500 11px/1 var(--font-mono);
}
.hc-axis-label {
  fill: var(--ink-soft);
  font: 500 10px/1 var(--font-body);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}
.hc-area { stroke: none; opacity: 0.85; }
.hc-bar { stroke: none; opacity: 0.9; }
.hc-total {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.25;
  stroke-linejoin: round;
  opacity: 0.55;
}
.hc-total--archive { opacity: 0.9; stroke-width: 1.75; }

/* The uncertainty envelope. Deliberately quiet — it is a published band, not a
   measurement — but never invisible: a single line would imply a precision the
   reconstruction does not have. */
.hc-band {
  fill: rgba(var(--brand-rgb), 0.14);
  stroke: rgba(var(--brand-rgb), 0.4);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}
.hc-whisker { stroke: var(--ink-muted); stroke-width: 1.25; }
.hc-bar-value {
  fill: var(--ink);
  font: 600 11px/1 var(--font-mono);
}

/* The capture-change rule on the archive figures. */
.hc-rule {
  stroke: var(--quality-warning);
  stroke-width: 1.25;
  stroke-dasharray: 4 3;
}
.hc-rule-label {
  fill: var(--quality-warning);
  font: 600 10px/1 var(--font-body);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

/* Per-region small multiples. */
.hc-cards {
  list-style: none;
  margin: 0 0 32px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
}
.methodology-doc .hc-cards li {
  margin: 0;
  padding: 12px 13px 10px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-raised);
}
.hc-card-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 8px;
}
.hc-card-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: var(--lh-ui);
}
.hc-card-peak {
  font: 500 10px/1.3 var(--font-mono);
  color: var(--ink-soft);
}
.hc-spark {
  display: block;
  width: 100%;
  height: 54px;
}
.hc-spark-area { fill: var(--data-renewable, var(--brand)); opacity: 0.28; stroke: none; }
.hc-spark-line { fill: none; stroke: var(--brand); stroke-width: 1.25; opacity: 0.85; }
.hc-card-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 8px;
  font: 500 10px/1.4 var(--font-mono);
  color: var(--ink-soft);
}
.hc-card-link { white-space: nowrap; }

/* Data tables. `.methodology-doc table` already sets the base; these only add
   what a figures table needs. */
.methodology-doc .hc-table { font-size: 13px; }
.methodology-doc .hc-table caption {
  caption-side: bottom;
  text-align: left;
  padding-top: 10px;
  font-size: 12px;
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.methodology-doc .hc-table td,
.methodology-doc .hc-table th { white-space: nowrap; }
.methodology-doc .hc-table tbody th { text-align: left; }
.methodology-doc .hc-table-change td,
.methodology-doc .hc-table-change th {
  border-top: 1px solid var(--hairline-strong);
  color: var(--ink-muted);
}

@media (max-width: 640px) {
  .hc-figure { padding: 14px 12px 10px; }
  .hc-cards { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
