/* Braided — the site's ground. One file, no build step.
 *
 * The palette is the app's own (the dark theme, unchanged) and is not re-invented here: the same teal, the same
 * six river hues, the same three text weights. A visitor who downloads the app should not meet a new colour
 * scheme on the other side of the badge. The one discipline carried over matters most:
 * **a hue on a datum means a condition, and nothing else.** Teal is chrome only where no datum is involved.
 */

/* The type, self-hosted — no third party is asked for a font on a page that asks for nothing else. Familjen
 * Grotesk (OFL) carries the display line and Switzer (Fontshare's free licence) everything else, the same two
 * faces as the app. Switzer's licence forbids subsetting and format conversion, so these are the foundry's own
 * woff2 files, shipped whole and with the licences beside them. `swap`: the copy is the page, and a face that
 * arrives late must not hold it back. */
@font-face { font-family: "Familjen Grotesk"; src: url(fonts/FamiljenGrotesk-SemiBold.woff2) format("woff2");
  font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: Switzer; src: url(fonts/Switzer-Regular.woff2) format("woff2");
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: Switzer; src: url(fonts/Switzer-Medium.woff2) format("woff2");
  font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: Switzer; src: url(fonts/Switzer-Semibold.woff2) format("woff2");
  font-weight: 600; font-style: normal; font-display: swap; }

:root {
  color-scheme: dark;

  /* ground */
  --bg:      #0B0F14;
  --land:    #141B23;
  --surface: rgba(17,22,29,0.78);
  --solid:   #11161D;
  --border:  rgba(255,255,255,0.07);
  --border2: rgba(255,255,255,0.12);
  --fill:    rgba(255,255,255,0.05);
  --fill2:   rgba(255,255,255,0.09);

  /* type */
  --text:  #E8ECF1;
  --text2: #98A2B3;
  --text3: #5C6673;

  /* the river scale, dry to flood — hue means condition */
  --accent:    #45D4C8;
  --very-low:  #F58A3C;
  --low:       #E9C63C;
  --normal:    #45D4C8;
  --high:      #5FAEFF;
  --very-high: #A98BFF;
  --flood:     #FF5CB8;
  --closed:    #FF6B7A;
  /* An alert is caution and a closure is red — the app's own two, so the map and the cards agree. */
  --good:      #45D4C8;
  --caution:   #F5B93C;
  --stale:     #98A2B3;

  --display: "Familjen Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --body: Switzer, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* The percentile scale, dry to wet. The stops sit at each band's CENTRE — 5, 17.5, 50, 82.5, 95 — the same
     numbers `rivers.js` uses to place a status carrying no percentile, so the hue under any point on the bar is
     the hue of the band that point belongs to. A gradient and not six blocks because a percentile is
     continuous: a hard edge at 25 would say something changes there that does not. It stops at "High" — there
     is no flood end to this scale, and `#limits` says why. */
  --ramp: linear-gradient(90deg,
    var(--very-low) 0%, var(--very-low) 5%, var(--low) 17.5%,
    var(--normal) 50%, var(--high) 82.5%, var(--very-high) 95%, var(--very-high) 100%);

  --gutter: 24px;
  --measure: 1200px;
  --r-card: 16px;
  --r-tile: 14px;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text2);
  font: 400 17px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 { font-family: var(--display); color: var(--text); font-weight: 600; letter-spacing: -0.02em; margin: 0; }
p { margin: 0 0 14px; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.wrap { max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); }

/* THE PERCENTILE RAMP IS A VALUE AND NEVER AN ELEMENT. `--ramp` up in `:root`, painted straight onto whatever
 * needs it. It was an absolutely positioned `<i class="ramp">` in both the map key and the gauge card until
 * 2026-09-15, and Safari painted neither: a gradient on an abs-positioned child of a short, rounded,
 * `overflow: hidden` box is not reliable in WebKit. Rather than find out which ingredient it disliked, the
 * mechanism is gone from both — the key paints the gradient on its own span, the card's bar paints it under a
 * scrim in a second background layer. Do not reintroduce a `.ramp` element. */

.mono { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.dim { color: var(--text3); font-size: 15.5px; }

/* ── nav ──────────────────────────────────────────────────────────────────────────────────────────────── */

.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 40;
  display: flex; align-items: center; gap: 16px;
  padding: 14px var(--gutter);
  background: linear-gradient(to bottom, rgba(11,15,20,0.94), rgba(11,15,20,0));
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.nav .brand { display: flex; align-items: center; gap: 10px; color: var(--text); font-family: var(--display); font-weight: 600; font-size: 19px; letter-spacing: -0.02em; }
.nav .brand:hover { text-decoration: none; }
.nav .brand img { width: 28px; height: 28px; border-radius: 8px; display: block; }
.nav nav { margin-left: auto; display: flex; align-items: center; gap: 22px; }
.nav nav a { color: var(--text2); font-size: 15px; }
.nav nav a:hover { color: var(--text); text-decoration: none; }
.nav .ghost {
  border: 1px solid var(--border); background: var(--fill); color: var(--text);
  padding: 7px 14px; border-radius: 999px; font-size: 14px; font-weight: 500;
}
.nav .ghost:hover { background: var(--fill2); text-decoration: none; }
@media (max-width: 860px) { .nav nav a.hide-sm { display: none; } }

/* ── hero ─────────────────────────────────────────────────────────────────────────────────────────────── */

/* Two columns, not a scrim over a full-bleed map. The picture is portrait — the country is — so it wants a
 * column of its own rather than a rectangle with the copy dimming half of it. */
.hero { padding: 116px 0 clamp(48px, 6vw, 88px); min-height: 100svh; display: flex; align-items: center; }
.hero-grid { display: grid; grid-template-columns: 1fr 0.96fr; gap: clamp(24px, 4.5vw, 68px); align-items: center; width: 100%; }
@media (max-width: 940px) {
  .hero { padding-top: 104px; }
  .hero-grid { grid-template-columns: 1fr; gap: 40px; }
  .hero-map { order: -1; }
}

.hero h1 {
  font-size: clamp(42px, 7vw, 88px);
  line-height: 0.96; letter-spacing: -0.04em; font-weight: 600;
  margin-bottom: 22px;
}
.hero .lede { color: var(--text); font-size: clamp(17px, 1.85vw, 20px); line-height: 1.5; max-width: 45ch; margin-bottom: 8px; }
.hero .terms { color: var(--text2); font-size: clamp(15px, 1.7vw, 17px); margin-bottom: 26px; }
.hero .terms b { color: var(--text); font-weight: 500; }
.fallback { color: var(--text3); font-size: 14px; margin-top: 16px; max-width: 48ch; }

/* live counts, read from the same manifest the app reads */
.ticker { display: flex; flex-wrap: wrap; gap: 0 30px; margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--border); }
.ticker div { padding: 6px 0; }
.ticker .n { display: block; font-family: var(--display); font-size: 25px; font-weight: 600; color: var(--text); letter-spacing: -0.02em; line-height: 1.15; }
.ticker .l { font-size: 12.5px; color: var(--text3); letter-spacing: 0.02em; }
.ticker .fresh .n { color: var(--accent); }

/* ── the country, drawn in its rivers ─────────────────────────────────────────────────────────────────── */

.hero-map { position: relative; }
/* The readout sits OVER the picture, in the ocean at the bottom left — which is empty on every frame of this
 * map — rather than under it. Stacked, the column ran past the fold on a laptop. */
.nzwrap { position: relative; }
.nzwrap .nzloading { height: 68svh; max-height: 760px; min-height: 400px; }
.nzwrap.ready .nzloading { display: none; }

svg.nz {
  display: block; width: 100%; height: 68svh; max-height: 760px; min-height: 400px;
  margin: 0 auto; overflow: visible;
}
.nz .land { fill: var(--land); stroke: #1E2833; stroke-width: 1.2; stroke-linejoin: round; }
/* The places, in the colour of what they are doing. One path per colour, each a run of zero-length round-capped
 * subpaths — so `stroke-width` IS the dot diameter, and ten elements carry ~2,900 dots. Every hue here is one
 * the rivers can also take, because it is the same claim about the same country. */
.nz .places path { fill: none; stroke-width: 4.4; stroke-linecap: round; stroke-opacity: 0.62; }
.nz[data-active] .places path { stroke-opacity: 0.3; }
/* Nothing to report is most of the country most days, so it is drawn quietly and the exceptions are not. */
.nz .d-good, .nz .d-normal { stroke: var(--good); stroke-opacity: 0.4; }
.nz .d-stale    { stroke: var(--stale); stroke-opacity: 0.22; }
.nz .d-veryLow  { stroke: var(--very-low); }
.nz .d-low      { stroke: var(--low); }
.nz .d-high     { stroke: var(--high); }
.nz .d-veryHigh { stroke: var(--very-high); }
.nz .d-caution  { stroke: var(--caution); stroke-opacity: 0.85; stroke-width: 4.8; }
.nz .d-flood    { stroke: var(--flood); stroke-opacity: 0.9; stroke-width: 5; }
.nz .d-closed   { stroke: var(--closed); stroke-opacity: 0.95; stroke-width: 5.2; }
.nz .ungauged { fill: none; stroke: var(--stale); stroke-opacity: 0.38; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.nz .rivers { fill: none; stroke-linecap: round; stroke-linejoin: round; transition: opacity .35s ease; }
.nz .glow path { stroke-width: 13; opacity: 0.12; }
.nz .core path { stroke-width: 3.1; opacity: 0.8; }

/* The flow. One animated path per rank, each carrying every river of that rank — so the browser animates seven
 * dash offsets, not 108. `animation-duration` is set per rank from the app's own FLOW_MS. */
.nz .flow path { stroke: #F4FFFE; stroke-width: 1.9; stroke-dasharray: 3 9; opacity: 0.7; animation: march linear infinite; }
@keyframes march { to { stroke-dashoffset: -12; } }
.nz.paused .flow path { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .nz .flow path { animation: none; } }

.nz .r-very_low  { stroke: var(--very-low); }
.nz .r-low       { stroke: var(--low); }
.nz .r-normal    { stroke: var(--normal); }
.nz .r-high      { stroke: var(--high); }
.nz .r-very_high { stroke: var(--very-high); }
.nz .r-flood, .nz .r-flood_major { stroke: var(--flood); }

/* Reading one river dims the rest rather than brightening it: the picture stays the same brightness, and the
 * eye goes to the one thing that did not change. */
.nz[data-active] .rivers { opacity: 0.5; }
.nz[data-active] .ungauged { stroke-opacity: 0.22; }
.nz .active { fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 4.4; opacity: 0; transition: opacity .2s ease; }
.nz[data-active] .active { opacity: 1; }
.nz .active-glow { stroke-width: 20; opacity: 0; }
.nz[data-active] .active-glow { opacity: 0.22; }
.nz .marks circle { stroke: var(--bg); stroke-width: 1.6; }

/* Invisible, fat, and last. A river drawn 2 units wide is one CSS pixel on a phone; a pointer needs sixteen. */
.nz .hits path { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* CLICKING A RIVER MUST NOT RING IT. These are `tabindex="0"` `role="button"` paths, and a mouse click focuses
 * one WITHOUT matching `:focus-visible` — so the rule below never fired and the UA's own ring was left to draw.
 * On an SVG path that ring is a rectangle around the bounding box, which on a diagonal river is a box the width
 * of the South Island. Chrome only rings `:focus-visible` and so never showed it; Safari rings plain `:focus`,
 * which is where this was seen, and is the second Safari-only break on this page — see the README.
 * Keyboard focus keeps its affordance: the `:focus-visible` rule follows this one and wins, lighting the stroke. */
.nz .hits path:focus { outline: none; }
.nz .hits path:focus-visible { stroke: rgba(255,255,255,0.22); outline: none; }

/* The readout: what the hero says about the river under the pointer, and what it says to itself when nobody
 * is pointing at anything. */
.readout {
  position: absolute; left: 0; bottom: 26px; z-index: 2; width: min(370px, 86%);
  padding: 13px 15px; pointer-events: none;
  border: 1px solid var(--border); border-radius: var(--r-tile); background: var(--surface);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  opacity: 0; transform: translateY(6px); transition: opacity .28s ease, transform .28s ease;
}

.readout.on { opacity: 1; transform: none; }
.readout .rname { font-family: var(--display); font-weight: 600; font-size: 19px; color: var(--text); letter-spacing: -0.02em; }
.readout .rstate { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 14.5px; color: var(--hue, var(--accent)); }
.readout .rstate b { font-weight: 600; }
.readout .rstate.grey { color: var(--stale); }
.readout .rstate i { width: 8px; height: 8px; border-radius: 999px; background: currentColor; flex: none; }
.readout .rwhat { margin-top: 5px; font-size: 14px; color: var(--text2); }
.hint { position: absolute; left: 2px; bottom: 2px; margin: 0; font-size: 12.5px; color: var(--text3); letter-spacing: 0.02em; transition: opacity .3s ease; }
.readout.on ~ .hint { opacity: 0; }
/* "Hover" is a lie on a phone and "tap" is a lie on a laptop, and the page knows which one it is on. */
.hint .on-touch { display: none; }
@media (hover: none) { .hint .on-hover { display: none; } .hint .on-touch { display: inline; } }

.legend { position: absolute; left: 0; top: 0; z-index: 2; width: min(238px, 56%); display: flex; flex-direction: column; gap: 7px; }
/* The same ramp the gauge card draws, from the same declaration — one scale, so the map's key cannot disagree
 * with the card's. Painted on the span itself; see the note on `--ramp`. */
.legend .scale { display: block; height: 5px; border-radius: 999px; background: var(--ramp); opacity: 0.85; }
.legend .ends { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; color: var(--text3); }
/* Two labels, because the key describes two different marks making two different claims: a line is a river
 * measured against its own record, a dot is a place reporting what it is doing. Naming only one of them left
 * the other to be guessed at. */
.legend .lab { font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text3); opacity: .75; }
.legend .lab + .scale { margin-top: -2px; }
.legend .ends + .lab { margin-top: 6px; }
/* The place key. The ramp above it is the river scale; these three are what a dot can say that a river cannot. */
.legend .dots { display: flex; flex-wrap: wrap; gap: 3px 12px; margin-top: 1px; }
.legend .dots[hidden] { display: none; }
.legend .dots .k { display: inline-flex; align-items: center; gap: 6px; font-size: 10.5px; line-height: 1.25; color: var(--text3); }
/* The dot carries the hue; the label does not. Four lines of coloured type beside a coloured map is two things
 * shouting the same word. */
.legend .dots .k i { width: 5px; height: 5px; flex: none; border-radius: 999px; }
.legend .dots .k-good    i { background: var(--good); }
.legend .dots .k-caution i { background: var(--caution); }
.legend .dots .k-closed  i { background: var(--closed); }
@media (max-width: 480px) { .legend { display: none; } }

/* ── sections ─────────────────────────────────────────────────────────────────────────────────────────── */

section.band { padding: clamp(76px, 11vw, 140px) 0; border-top: 1px solid var(--border); position: relative; }
.eyebrow { font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0 0 16px; font-weight: 500; }
section.band h2 { font-size: clamp(30px, 4.4vw, 50px); line-height: 1.05; letter-spacing: -0.03em; max-width: 21ch; margin-bottom: 22px; }
section.band .say { max-width: 58ch; font-size: 17.5px; }
section.band .say b { color: var(--text); font-weight: 500; }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 80px); align-items: start; }
@media (max-width: 920px) { .split { grid-template-columns: 1fr; } }
.caption { color: var(--text3); font-size: 13px; line-height: 1.55; margin: 14px 0 0; }

/* ── the braid (why this exists) ──────────────────────────────────────────────────────────────────────── */

/* THE BRAID IS THE SECTION'S GROUND. Thirty-one strands running the full width and converging past the copy —
 * the name of the thing, drawn at the size of a wall rather than the size of a diagram. The copy sits over the
 * calm left half where the strands are parallel and far apart; the mask below is what keeps that half readable,
 * so the fan is at full strength exactly where there is nothing on top of it. */
#braid { overflow: hidden; }
#braid .wrap { position: relative; z-index: 1; }
.braid-copy { max-width: 56ch; }
.braid-copy .big { font-size: 20px; color: var(--text); line-height: 1.45; margin-top: 26px; }
.braid-copy p.big b { color: var(--accent); font-weight: 600; }

.braid-bg { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 0; pointer-events: none; }
.braid-bg svg { display: block; width: 100%; height: 100%; }
/* Clear under the text, full strength in the empty right half. ONE mask layer on purpose: two would need
 * `mask-composite`, whose standard keywords and WebKit's prefixed ones disagree, and the fan's top and bottom
 * are already handled by the section's own `overflow: hidden`. */
.braid-bg {
  -webkit-mask-image: linear-gradient(90deg, transparent 22%, rgba(0,0,0,0.12) 46%, #000 72%);
  mask-image: linear-gradient(90deg, transparent 22%, rgba(0,0,0,0.12) 46%, #000 72%);
}
.braid-bg .strand { fill: none; stroke: var(--accent); stroke-linecap: round; stroke-width: 1.9; opacity: 0.42; vector-effect: non-scaling-stroke; }
.braid-bg .out { fill: none; stroke: var(--accent); stroke-width: 4.5; opacity: .9; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.braid-bg .outglow { fill: none; stroke: var(--accent); stroke-width: 18; opacity: .13; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.braid-bg .flowline { fill: none; stroke: var(--accent); stroke-width: 2.1; stroke-dasharray: 2 10; opacity: .95; vector-effect: non-scaling-stroke; animation: march 2.4s linear infinite; }
.braid-bg .terminus { fill: var(--accent); }
.braid-bg .halo { fill: var(--accent); opacity: .12; }
@media (prefers-reduced-motion: reduce) { .braid-bg .flowline { animation: none; } }
/* On a phone the copy runs the full width, so there is no empty half for the fan to live in. */
@media (max-width: 860px) {
  .braid-bg { opacity: 0.16; -webkit-mask-image: none; mask-image: none; }
}


/* ── the live place card ──────────────────────────────────────────────────────────────────────────────── */

.demo { margin-top: 44px; }
.tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
.tab {
  display: inline-flex; align-items: baseline; gap: 9px;
  border: 1px solid var(--border); background: transparent; color: var(--text2);
  border-radius: 999px; padding: 9px 17px; font: 500 15px var(--body); cursor: pointer;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.tab:hover { color: var(--text); border-color: var(--border2); }
.tab small { font-size: 12.5px; color: var(--text3); font-weight: 400; }
.tab[aria-selected="true"] { background: var(--text); color: var(--bg); border-color: var(--text); }
.tab[aria-selected="true"] small { color: rgba(11,15,20,0.62); }

.stage { display: grid; grid-template-columns: minmax(0, 480px) minmax(0, 1fr); gap: clamp(24px, 4vw, 56px); align-items: start; min-height: 420px; }
@media (max-width: 920px) { .stage { grid-template-columns: 1fr; } }

.card {
  background: var(--solid); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 20px; box-shadow: 0 24px 60px rgba(0,0,0,0.5); overflow: hidden;
}
.card.wide { max-width: none; }
.card .band-strip { margin: -20px -20px 16px; padding: 10px 20px; font-size: 13.5px; font-weight: 500; display: flex; align-items: center; gap: 8px; }
.card .head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 16px; }
.card .kicker { font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text3); margin-bottom: 5px; }
.card .name { color: var(--text); font-family: var(--display); font-weight: 600; font-size: 21px; line-height: 1.2; letter-spacing: -0.02em; }
.card .region { color: var(--text3); font-size: 13px; margin-top: 4px; line-height: 1.45; }
/* Full-bleed to the card's edges. `max-width: none` is load-bearing: the base `img { max-width: 100% }` would
 * otherwise clamp the width back inside the padding and leave the height to the photo's own proportions. */
.card .shot { margin: -20px -20px 16px; display: block; width: calc(100% + 40px); max-width: none; height: 210px; object-fit: cover; background: var(--land); }

.chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 500; white-space: nowrap; background: var(--fill); }
.chip i { width: 6px; height: 6px; border-radius: 999px; background: currentColor; display: block; flex: none; }

.reading { display: flex; align-items: baseline; gap: 10px; }
.reading .v { font-family: var(--display); font-size: 50px; font-weight: 600; letter-spacing: -0.04em; color: var(--text); line-height: 1; }
.reading .u { font-size: 17px; color: var(--text2); }

.trend { display: flex; align-items: center; gap: 7px; font-size: 14px; color: var(--text2); margin-top: 12px; }
.trend svg { flex: none; }
.trend b { color: var(--text); font-weight: 500; }

.bands { margin-top: 20px; }
/* TWO BACKGROUND LAYERS, NOT A CHILD ELEMENT. The ramp used to be an absolutely positioned `<i>` inside this
 * box and Safari painted nothing — the same failure as the map key, and the second half of the same lesson: a
 * gradient on an abs-positioned child of a short `overflow: hidden` rounded box is not reliable in WebKit. The
 * bar cannot simply take `opacity`, because the pin is its child and would fade with it, so the softening is a
 * flat scrim of the card's own `--solid` laid over the ramp in one `background-image`. Multiple background
 * layers are as old as CSS3 and cannot fail. */
.bands .track {
  position: relative; height: 8px; border-radius: 999px; overflow: hidden;
  background-image: linear-gradient(rgba(17, 22, 29, 0.56), rgba(17, 22, 29, 0.56)), var(--ramp);
}
.bands .pin { position: absolute; top: -5px; width: 3px; height: 18px; border-radius: 2px; background: var(--text); box-shadow: 0 0 0 3px var(--solid); transform: translateX(-1.5px); }
.bands .axis { display: flex; justify-content: space-between; margin-top: 8px; font-size: 11.5px; color: var(--text3); letter-spacing: 0.02em; }
.bands .verdict { margin-top: 12px; color: var(--text2); font-size: 14.5px; line-height: 1.5; }
.bands .verdict b { color: var(--text); font-weight: 500; }

/* the seven-day trace off the site's own history file */
.spark { margin-top: 18px; }
.spark svg { display: block; width: 100%; height: 66px; overflow: visible; }
.spark .fillpath { stroke: none; opacity: 0.16; }
.spark .line { fill: none; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
.spark .axis { display: flex; justify-content: space-between; margin-top: 6px; font-size: 11.5px; color: var(--text3); }

/* the rows that make a card a place rather than a reading */
.rows { list-style: none; margin: 18px 0 0; padding: 0; }
.rows li { display: flex; gap: 14px; align-items: baseline; padding: 11px 0; border-top: 1px solid var(--border); font-size: 14.5px; color: var(--text2); }
.rows .k { color: var(--text3); font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; flex: none; width: 94px; }
.rows .v { color: var(--text); flex: 1; }
.rows .v small { display: block; color: var(--text3); font-size: 12.5px; margin-top: 2px; letter-spacing: 0; text-transform: none; line-height: 1.45; }
.rows li.absent .v { color: var(--text3); }

.facilities { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.facilities span { font-size: 12px; padding: 3px 9px; border-radius: 999px; background: var(--fill); color: var(--text2); }

.meta { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 12px; font-size: 12.5px; color: var(--text3); }

/* the annotation rail beside the card */
.annot { list-style: none; margin: 34px 0 0; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 44px; }
.annot li { display: flex; gap: 14px; padding: 13px 0; border-top: 1px solid var(--border); font-size: 15.5px; }
.annot li span { color: var(--text3); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; flex: none; width: 86px; padding-top: 3px; }
.annot li b { color: var(--text); font-weight: 500; }
@media (max-width: 760px) { .annot { grid-template-columns: 1fr; } }

/* what the card is reading, spelled out beside it */
.explain { position: sticky; top: 90px; }
.explain h3 { font-size: 19px; margin-bottom: 10px; letter-spacing: -0.02em; }
.explain p { font-size: 15.5px; line-height: 1.6; max-width: 46ch; }
.explain .lineage { list-style: none; margin: 22px 0 0; padding: 0; }
.explain .lineage li { display: flex; gap: 12px; align-items: baseline; padding: 10px 0; border-top: 1px solid var(--border); font-size: 14px; }
.explain .lineage i { width: 7px; height: 7px; border-radius: 999px; background: var(--accent); flex: none; position: relative; top: -1px; }
.explain .lineage b { color: var(--text); font-weight: 500; }
.explain .lineage em { font-style: normal; color: var(--text3); margin-left: auto; padding-left: 12px; white-space: nowrap; font-size: 12.5px; }

.skeleton { border: 1px solid var(--border); border-radius: var(--r-card); min-height: 380px; display: flex; align-items: center; justify-content: center; color: var(--text3); font-size: 14px; }

/* ── same number, opposite day ────────────────────────────────────────────────────────────────────────── */

.versus { display: grid; grid-template-columns: 1fr auto 1fr; gap: clamp(14px, 3vw, 34px); align-items: center; margin: 40px 0 0; }
.versus-lede { margin: 26px 0 0; font-size: 16.5px; color: var(--text2); max-width: 62ch; }
.versus-lede b { color: var(--text); font-weight: 500; }
.versus .vs { font-family: var(--display); font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text3); }
@media (max-width: 760px) { .versus { grid-template-columns: 1fr; justify-items: stretch; } .versus .vs { justify-self: center; } }

/* ── the regions you can carry in ─────────────────────────────────────────────────────────────────────── */

.regions { border: 1px solid var(--border); border-radius: var(--r-card); overflow: hidden; background: var(--solid); }
.regions .rhead, .regions .rfoot { display: flex; justify-content: space-between; gap: 12px; padding: 13px 18px; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text3); }
.regions .rhead { border-bottom: 1px solid var(--border); }
.regions .rfoot { border-top: 1px solid var(--border); text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--text2); }
.regions .rfoot b { color: var(--text); font-weight: 500; }
.regions ul { list-style: none; margin: 0; padding: 0; }
.regions li { display: grid; grid-template-columns: 1fr 76px 58px; align-items: center; gap: 12px; padding: 9px 18px; font-size: 14.5px; }
.regions li + li { border-top: 1px solid var(--border); }
.regions .rn { color: var(--text); }
.regions .rn small { display: block; color: var(--text3); font-size: 12px; margin-top: 1px; }
.regions .rb { color: var(--text2); font-variant-numeric: tabular-nums; font-size: 13px; text-align: right; }
.regions .bar { height: 3px; border-radius: 999px; background: var(--fill2); }
.regions .bar i { display: block; height: 100%; border-radius: 999px; background: var(--accent); opacity: .5; }
@media (max-width: 420px) { .regions li { grid-template-columns: 1fr 56px; } .regions .bar { display: none; } }

/* ── download ─────────────────────────────────────────────────────────────────────────────────────────── */

.stores { display: flex; flex-wrap: wrap; gap: 12px; }
.store {
  display: inline-flex; align-items: center; gap: 11px;
  padding: 11px 18px 11px 15px; border-radius: 12px;
  background: var(--text); color: var(--bg);
  font-family: var(--body); font-weight: 500; line-height: 1.15;
  border: 1px solid var(--text);
}
.store:hover { text-decoration: none; opacity: 0.9; }
.store svg { flex: none; }
.store span { display: block; font-size: 10.5px; letter-spacing: 0.04em; opacity: 0.72; font-weight: 400; }
.store b { display: block; font-size: 16.5px; font-weight: 600; letter-spacing: -0.01em; }
.store[aria-disabled="true"] { background: transparent; color: var(--text2); border-color: var(--border); cursor: default; }
.store[aria-disabled="true"]:hover { opacity: 1; }

/* The official badge carries its own black tile, its own type and its own corner radius, so the site's tile has
 * to get out of the way entirely — a badge sitting on our button would be the badge on a background it is not
 * allowed to have. Padding is Apple's required clear space (a tenth of the badge height, absent from their
 * file); Google's is baked into its PNG, which is why only the Apple badge needs it. `height` is set and
 * `width:auto` follows, so a stylesheet can never stretch either one out of proportion. */
.store--badge { padding: 0; background: none; border: none; border-radius: 0; }
.store--badge:hover { opacity: 0.85; }
.store--badge img { display: block; height: 40px; width: auto; max-width: none; }
.store--badge[data-store="ios"] { padding: 4px; }
.store--badge[data-store="android"] img { height: 59px; }

.cta { text-align: center; }
.cta .wrap { display: flex; flex-direction: column; align-items: center; }
.cta h2 { max-width: 20ch; }
.cta .say { text-align: center; max-width: 60ch; }
.cta .stores { justify-content: center; margin-top: 26px; }
.cta img.appicon { width: 84px; height: 84px; border-radius: 20px; margin-bottom: 26px; box-shadow: 0 18px 50px rgba(0,0,0,0.5); }
.cta .free { margin-top: 20px; color: var(--text3); font-size: 14px; }
/* Teal, not red: on this site a hue on a datum means a condition, and the brand colour is what chrome wears
 * when no datum is involved. A sentence in the footer is as chrome as it gets. */
.cta .heart { color: var(--accent); vertical-align: -1px; margin: 0 1px; }

/* ── footer ───────────────────────────────────────────────────────────────────────────────────────────── */

footer.site { border-top: 1px solid var(--border); padding: 56px 0 72px; font-size: 14.5px; }
footer.site .cols { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: 40px; }
@media (max-width: 760px) { footer.site .cols { grid-template-columns: 1fr 1fr; } footer.site .cols > :first-child { grid-column: 1 / -1; } }
footer.site h4 { font-size: 13px; letter-spacing: 0.02em; margin: 0 0 12px; font-weight: 600; }
footer.site ul { list-style: none; margin: 0; padding: 0; }
footer.site li { margin-bottom: 9px; }
footer.site a { color: var(--text2); }
footer.site a:hover { color: var(--text); text-decoration: none; }
footer.site .attrib { color: var(--text3); font-size: 13px; line-height: 1.65; max-width: 56ch; }
footer.site .rule { margin-top: 44px; padding-top: 20px; border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; gap: 12px 24px; color: var(--text3); font-size: 13px; }

/* ── document pages (help, support-us, and the generated legal pair) ──────────────────────────────────── */

.doc { max-width: 680px; margin: 0 auto; padding: 132px var(--gutter) 100px; }
.doc h1 { font-size: clamp(34px, 5.5vw, 48px); line-height: 1.05; margin-bottom: 8px; }
.doc .updated { color: var(--text3); font-size: 12px; letter-spacing: 0.09em; text-transform: uppercase; margin: 0 0 24px; }
.doc .lede { color: var(--text); font-size: 19px; line-height: 1.55; margin-bottom: 10px; }
.doc h2 { font-size: 21px; line-height: 1.3; margin: 44px 0 12px; }
.doc h3 { font-size: 17px; margin: 28px 0 8px; }
.doc ul { margin: 0 0 14px; padding-left: 20px; }
.doc li { margin-bottom: 7px; }
.doc .note { padding: 18px 20px; border: 1px solid var(--border); border-radius: var(--r-tile); background: var(--fill); margin: 24px 0; }
.doc .note p:last-child { margin-bottom: 0; }

/* ── the koha panel ───────────────────────────────────────────────────────────────────────────────────── */

/* The ask, on the one page that is allowed to make it. It is a panel rather than a link in a paragraph because
 * the in-app button lands here and a page that answers a tap with a wall of prose has changed the subject.
 *
 * TEAL, NOT RED. The app has a warm `koha` hue for this and the site deliberately does not: here a hue on a
 * datum means a condition, and a red panel on a site whose reds mean "closed" is a false alarm. The accent is
 * what chrome wears when no datum is involved, and the give button is the same solid `--text` as the store
 * badges — one primary action, one look, wherever it appears.
 */
.koha {
  margin: 26px 0 10px; padding: 22px;
  border: 1px solid var(--border2); border-radius: var(--r-card);
  background: radial-gradient(130% 150% at 0% 0%, rgba(69,212,200,0.10), rgba(69,212,200,0) 62%), var(--solid);
  box-shadow: 0 24px 60px rgba(0,0,0,0.45);
}
.koha .keyebrow { font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0 0 10px; font-weight: 500; }
.koha .kline { color: var(--text); font-size: 18.5px; line-height: 1.45; margin: 0 0 16px; }
.koha .kline b { font-weight: 600; }
/* The chips are the page's own `.tab`, unchanged — a selected chip looks the same here as it does on the home
 * page's card, and nothing new has to be learned to use it. */
.koha .tabs { margin-bottom: 12px; }
.koha .covers { margin: 0 0 16px; font-size: 15.5px; color: var(--text2); }
.koha .covers b { color: var(--text); font-weight: 500; }

.give {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 22px; border-radius: 12px;
  background: var(--text); color: var(--bg); border: 1px solid var(--text);
  font-family: var(--body); font-weight: 600; font-size: 17px; letter-spacing: -0.01em;
}
.give:hover { text-decoration: none; opacity: 0.9; }
.give svg { flex: none; }
.koha .fine { margin: 12px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--text3); }

/* What the bill is, itemised. The prose already says "not much"; this is the part a sceptic can check. */
.ledger { list-style: none; margin: 20px 0 10px; padding: 0; border: 1px solid var(--border); border-radius: var(--r-tile); overflow: hidden; background: var(--solid); }
.ledger li { display: flex; align-items: baseline; gap: 14px; padding: 11px 16px; font-size: 14.5px; color: var(--text2); }
.ledger li + li { border-top: 1px solid var(--border); }
.ledger .amt { margin-left: auto; flex: none; color: var(--text); font-variant-numeric: tabular-nums; }
.ledger .amt small { color: var(--text3); font-size: 12.5px; }
.ledger .nil .amt { color: var(--accent); }
.ledger .sum { background: var(--fill); color: var(--text); }
.ledger .sum b, .ledger .sum .amt { font-weight: 600; color: var(--text); }
/* The chips are toggles, not tabs — `aria-selected` is not a button's attribute — so the selected look is
 * asserted again for `aria-pressed`. Same two declarations as `.tab[aria-selected="true"]`, deliberately. */
.koha .tab[aria-pressed="true"] { background: var(--text); color: var(--bg); border-color: var(--text); }

/* The second button. The page is long by the time it has itemised a bill and named four charities, and the ask
 * is at the top where the tap lands — this is for the reader who got to the bottom and had to scroll back. */
.koha-end { margin: 40px 0 0; padding-top: 26px; border-top: 1px solid var(--border); text-align: center; }
.koha-end p { color: var(--text2); font-size: 15.5px; margin-bottom: 16px; }
.koha-end .give { display: inline-flex; width: auto; padding: 13px 26px; font-size: 16px; }
