/* Mangru — BIST project page
   ===========================
   Self-contained. No JavaScript.

   Palette and typefaces are Mangru's own, lifted from mangru.live: a cold
   sensing planet (--accent) with one small warm lookout on it (--ember,
   --candle). Warm colour is spent only on the lamp, the wordmark and the
   one link we want followed. */

:root {
  --bg:           #07070d;
  --bg-deep:      #04040a;
  --panel:        #14131a;
  --panel-2:      #171620;
  --border:       rgba(190, 178, 168, 0.10);
  --text:         #ece8de;
  --body:         rgba(236, 232, 222, .84);
  --dim:          #9a9388;
  --dimmer:       #5e574e;
  --accent:       #22d3ee;   /* cool — the data */
  --ember:        #f5b878;   /* warm — the tower lamp */
  --candle:       #ffd9a8;

  --mono:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --brand: 'Gugi', var(--mono);

  /* The page is wide; the COLUMN is what stays readable. --shell is the
     outer bound, and text inside it splits into two columns rather than
     running to 150 characters a line. */
  --shell: 82rem;
  --pad:   clamp(24px, 5vw, 60px);
  --label: 12rem;   /* the section-label gutter on wide screens */

  color-scheme: dark;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--body);
  font-family: var(--mono);
  /* 13px is Mangru's size on the map — too tight for paragraphs. Larger,
     with plenty of leading, keeps the character without the cost. */
  font-size: 15px;
  font-weight: 300;
  line-height: 1.95;
  letter-spacing: .01em;
  -webkit-font-smoothing: antialiased;
}

/* ── Language ─────────────────────────────────────────────────
   Both languages are in the markup and one is hidden here, so the page is
   correct before any script runs — no flash of the wrong language, and it
   still reads if the script never loads. The toggle only flips this one
   attribute. */
[data-lang="en"] .ko,
[data-lang="ko"] .en { display: none; }

/* JetBrains Mono carries no Hangul. Leaving it first in the stack means the
   spaces and punctuation come from the mono face while the Hangul falls back
   to another, and the two rhythms fight — the words end up separated by
   uneven gaps. Korean prose gets one face for the whole run instead. The
   mono is kept for the Latin-and-numerals furniture, where it belongs. */
[data-lang="ko"] body,
[data-lang="ko"] h2 {
  font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR',
               'Nanum Gothic', system-ui, sans-serif;
  line-height: 1.9;
  letter-spacing: 0;
}
[data-lang="ko"] .body > p { font-size: 15.5px; }
[data-lang="ko"] .w-note { line-height: 1.85; }

/* Korean wraps between syllables by default, which breaks words in half
   mid-line. keep-all makes it break at word boundaries like the English. */
[data-lang="ko"] body,
[data-lang="ko"] .question,
[data-lang="ko"] .visit-lede { word-break: keep-all; }

/* Wide tracking is a Latin device. On Hangul it pulls the syllables of one
   word apart and the word stops reading as a unit, so every tracked style
   gets a much smaller value in Korean. */
[data-lang="ko"] .kicker,
[data-lang="ko"] h2,
[data-lang="ko"] .counts dd,
[data-lang="ko"] .ml-hint,
[data-lang="ko"] .foot-back,
[data-lang="ko"] .visit-btn { letter-spacing: .04em; }
[data-lang="ko"] h2,
[data-lang="ko"] .counts dd,
[data-lang="ko"] .ml-hint,
[data-lang="ko"] .foot-back { text-transform: none; }

/* Instrument Serif carries no Hangul, so the display lines would fall back
   to an arbitrary face at a size tuned for a different one. Give Korean its
   own stack and its own measure. */
[data-lang="ko"] .question {
  font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR',
               system-ui, sans-serif;
  font-size: clamp(24px, 3.6vw, 40px);
  line-height: 1.5;
  max-width: 18ch;
  font-weight: 300;
}
[data-lang="ko"] .visit-lede {
  font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR',
               system-ui, sans-serif;
  font-size: clamp(19px, 2.4vw, 25px);
}

a { color: var(--ember); text-decoration: none; }
a:hover { color: var(--candle); text-decoration: underline; text-underline-offset: 3px; }
strong { color: var(--text); font-weight: 500; }
:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; }

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: 12px; top: 12px; z-index: 10;
  background: var(--ember); color: var(--bg-deep); padding: 10px 16px;
}

/* ── Top bar ──────────────────────────────────────────────────
   The only way back into the lab site for someone arriving from search. */
/* Sticky: the logo is the only way back into the lab site and the toggle is
   the only way to change language, so neither should scroll out of reach on a
   page this long. Opaque rather than translucent — content passing under a
   blur behind the mark would make it hard to read. */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  padding: 14px var(--pad);
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
}
.topbar-home { color: var(--dimmer); display: inline-block; }
.topbar-home:hover { color: var(--ember); text-decoration: none; }

/* Sized and weighted like the rest of the chrome so it reads as part of the
   bar rather than as a control bolted onto it. */
.lang-toggle {
  flex: 0 0 auto;
  font: inherit; font-size: 11px; letter-spacing: .18em;
  font-family: var(--mono);
  background: none; color: var(--dim);
  border: 1px solid var(--border); border-radius: 3px;
  padding: 7px 14px; cursor: pointer;
}
.lang-toggle:hover { color: var(--ember); border-color: var(--ember); }
/* The Korean label needs its own face and no tracking to stay legible. */
.lang-toggle .en {
  font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif;
  letter-spacing: .06em;
}

/* The lab mark. White artwork on a near-black page would sit brighter than
   anything else here, so it is held back to match the rest of the chrome and
   comes up to full strength on hover. Width/height are on the element too,
   so the bar does not jump while it loads. */
.bist-logo {
  display: block;
  /* Tall enough for the Korean sub-line to be readable — this mark carries
     three lines of type, so it cannot be sized like a plain wordmark. */
  height: 34px; width: auto;
  opacity: .72;
}
.topbar a:hover .bist-logo { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .bist-logo { transition: opacity .18s ease; }
}

/* ── Shell ───────────────────────────────────────────────────
   Everything shares one outer width so figures and text line up on the
   left edge all the way down the page. */
.hero, .sec, .fig, .visit, .foot {
  max-width: var(--shell); margin-inline: auto; padding-inline: var(--pad);
}

/* ── Hero ─────────────────────────────────────────────────────
   Wordmark and question on the left, the turning globe on the right. Below
   980px the globe drops under the text rather than shrinking to a marble. */
.hero {
  padding-top: clamp(40px, 6vw, 80px);
  padding-bottom: clamp(20px, 4vw, 44px);
  display: grid; gap: clamp(28px, 5vw, 64px);
  align-items: center;
}
@media (min-width: 980px) {
  .hero { grid-template-columns: minmax(0, 1fr) minmax(320px, 520px); }
}

/* The globe capture. Hidden until it loads (see js/main.js), so a missing
   file costs nothing and the hero falls back to one column. */
/* The wordmark column. Named so the hero grid reads as two halves rather
   than as a figure floated beside loose text. */
.hero-text { min-width: 0; }

.hero-media { margin: 0; }
.hero-media[hidden] { display: none; }
.hero-media video, .hero-media img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: 4px;
  background: var(--bg-deep);
}
.hero-media figcaption {
  margin: 10px 0 0;
  font-size: 11.5px; line-height: 1.65; color: var(--dimmer);
}
/* Mark and wordmark are one link to mangru.live. inline-block, not block:
   as a block it stretched the full column and lit the lamp when the pointer
   was nowhere near it. */
.wordmark { display: inline-block; color: inherit; text-decoration: none; }
.wordmark:hover { text-decoration: none; }

.glyph { display: block; width: 64px; height: 64px; margin: 0 0 28px; }
.glyph .frame {
  fill: none; stroke: var(--dim); stroke-width: 1.3;
  stroke-linecap: round; stroke-linejoin: round;
}
.glyph .halo { fill: var(--ember); opacity: 0; }
.glyph .glow { fill: var(--ember); opacity: .22; }
.glyph .lamp { fill: var(--candle); }

/* Hovering the link lights the lamp: the halo comes up, the inner glow
   strengthens, and the flame itself gains a small bloom. The wordmark warms
   toward the same colour, so the whole thing reads as one gesture rather
   than two unrelated hover effects. */
.wordmark:hover .glyph .halo,
.wordmark:focus-visible .glyph .halo { opacity: .16; }
.wordmark:hover .glyph .glow,
.wordmark:focus-visible .glyph .glow { opacity: .45; }
.wordmark:hover .glyph .lamp,
.wordmark:focus-visible .glyph .lamp {
  filter: drop-shadow(0 0 2.5px var(--candle));
}
.wordmark:hover .glyph .frame,
.wordmark:focus-visible .glyph .frame { stroke: var(--paper, #ece8de); }
.wordmark:hover h1,
.wordmark:focus-visible h1 { color: var(--candle); }

@media (prefers-reduced-motion: no-preference) {
  .glyph .halo, .glyph .glow, .glyph .lamp, .glyph .frame, .wordmark h1 {
    transition: opacity .25s ease, filter .25s ease,
                stroke .25s ease, color .25s ease;
  }
}

h1 {
  margin: 0 0 14px;
  font-family: var(--brand); font-weight: 400;
  font-size: clamp(46px, 8vw, 88px); line-height: 1;
  letter-spacing: .01em; color: var(--text);
}
.kicker {
  margin: 0 0 36px;
  font-size: 11.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--dimmer);
}
.kicker .han {
  font-family: system-ui, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif;
  letter-spacing: .1em; color: var(--ember); margin-right: 6px;
}
/* The one line allowed to be large and slow. Capped independently of the
   shell so it never stretches into a banner. */
.question {
  margin: 0; max-width: 22ch;
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(28px, 5vw, 54px); line-height: 1.22;
  color: var(--text); text-wrap: balance;
}

/* ── Sections ─────────────────────────────────────────────────
   Label in a left gutter, prose in the rest. Past 1180px the prose splits
   into two columns: on a wide monitor a single column would either run to
   an unreadable line length or leave two thirds of the screen empty. */
.sec { padding-block: clamp(30px, 4vw, 54px); }

h2 {
  margin: 0 0 20px;
  font-family: var(--mono); font-weight: 400;
  font-size: 11.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--dim);
}
h2::before {
  content: ""; display: inline-block;
  width: 18px; height: 1px; margin-right: 12px; vertical-align: middle;
  background: var(--dimmer);
}

.body > p { margin: 0 0 1.45em; color: var(--body); }
.body > p:last-child { margin-bottom: 0; }
.lede { color: var(--text); }

@media (min-width: 900px) {
  .sec {
    display: grid; grid-template-columns: var(--label) minmax(0, 1fr);
    column-gap: 40px; align-items: start;
  }
  h2 { margin-bottom: 0; padding-top: .55em; }
  /* The rule reads as a tick in the margin once the label has its own
     column, so it can go. */
  h2::before { display: none; }
}

@media (min-width: 1180px) {
  .body { columns: 2; column-gap: 56px; }
  /* Let a paragraph break across the gutter — forcing whole paragraphs
     leaves the two columns badly uneven — but never on a single line. */
  .body > p { orphans: 2; widows: 2; }
  .body > p:first-child { margin-top: 0; }
}

/* ── Figures ──────────────────────────────────────────────────
   Caption returns to a readable measure and sits under the figure's left
   edge, so it belongs to the figure rather than to the page. */
.fig { margin-block: clamp(20px, 3.5vw, 40px); }
/* A footnote inside the caption: same voice, quieter, and set apart so the
   caption's headline numbers stay the thing you read first. */
.fn {
  display: block; margin-top: 9px; padding-top: 9px;
  border-top: 1px solid var(--border);
  color: var(--dimmer); font-size: 11.5px; line-height: 1.65;
}

.fig figcaption {
  max-width: 46rem; margin: 16px 0 0;
  font-size: 12.5px; line-height: 1.7; color: var(--dimmer);
}
.fig img, .fig video {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: 4px;
}

/* Counts */
.counts {
  display: grid; gap: 26px 20px; margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  padding: clamp(26px, 3vw, 38px) clamp(22px, 3vw, 34px);
  background: var(--panel); border: 1px solid var(--border); border-radius: 4px;
}
.counts dt {
  font-family: var(--mono); font-weight: 300;
  font-size: clamp(30px, 3.4vw, 42px); line-height: 1;
  color: var(--accent); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.counts dd {
  margin: 10px 0 0; font-size: 11.5px; letter-spacing: .12em;
  text-transform: uppercase; line-height: 1.5; color: var(--dim);
}

/* What it watches — descriptions, so a list rather than a table. Two up on
   a wide screen, since each entry is short. */
.watch { list-style: none; margin: 0; padding: 0; }
.watch li {
  display: grid; gap: 4px 28px; padding: 18px 0;
  border-bottom: 1px solid var(--border);
}
.watch li:first-child { padding-top: 0; }
.watch li:last-child { border-bottom: none; padding-bottom: 0; }
/* flex-start, not center: when the name wraps to two lines, centring drops
   the icon into the gap between them instead of leaving it on the first. */
.w-head { display: flex; align-items: flex-start; gap: 11px; min-width: 0; }
.w-name { color: var(--text); }
.w-note { color: var(--dim); font-size: 14px; line-height: 1.8; }

/* Drawn the same way as the watchtower glyph in the hero — thin even
   strokes, round joins, no fill — so the two read as one hand. Decorative:
   the name beside each carries the meaning. */
.w-ico {
  /* 26px against 15px text: at 22 the strokes thinned to about one device
     pixel and read as scratches rather than drawings. */
  flex: 0 0 auto; width: 26px; height: 26px;
  margin-top: 1px;          /* optical centring on the first line of the name */
  fill: none; stroke: var(--dim); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}

@media (min-width: 720px) {
  .watch li { grid-template-columns: 15rem minmax(0, 1fr); align-items: baseline; }
}
@media (min-width: 1180px) {
  .watch { columns: 2; column-gap: 56px; }
  .watch li {
    grid-template-columns: minmax(0, 1fr);
    break-inside: avoid;   /* an entry split across the gutter is unreadable */
  }
  /* Stacked, the note hangs under the name rather than under the icon. */
  .watch li .w-note { padding-left: 37px; }
  .watch li:first-child { padding-top: 18px; }
  .watch li:last-child { border-bottom: 1px solid var(--border); }
}

/* Cadence bars */
.bars { list-style: none; margin: 0; padding: 0; }
.bars li {
  display: grid; grid-template-columns: 13rem minmax(0, 1fr) 3rem;
  align-items: center; gap: 18px; padding: 11px 0;
}
.b-lab { color: var(--dim); font-size: 13.5px; }
.b-track {
  height: 8px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 2px; overflow: hidden;
}
.b-fill { display: block; height: 100%; background: var(--accent); opacity: .55; }
.b-val {
  text-align: right; color: var(--accent);
  font-variant-numeric: tabular-nums; font-size: 14px;
}
@media (max-width: 620px) {
  .bars li { grid-template-columns: minmax(0, 1fr) 3rem; }
  .b-lab { grid-column: 1 / -1; }
}

/* ── Coverage map ─────────────────────────────────────────────
   Inline SVG built from the collector's own country list — no image file to
   lose, sharp at any size, and every country carries its own answer in data
   attributes so the hover needs no network request. */
.map-fig { }
.map-wrap { position: relative; }
.mapfig {
  display: block; width: 100%; height: auto;
  background: var(--bg-deep);
  border: 1px solid var(--border); border-radius: 4px;
}

/* Five steps, because the real distribution spans four orders of magnitude:
   the United States has 57,890 stations and the median country has seven. A
   two-colour map would flatten exactly the thing worth seeing. */
.c   { fill: #16151d; stroke: #23222e; stroke-width: .5; }
/* Hatched, not just dark: an empty country should read as a measured zero
   rather than as a country the map forgot to fill in. */
.c.b0 { fill: url(#nodata); stroke: #3a3446; }
.c.b1 { fill: rgba(34, 211, 238, .08); stroke: rgba(34, 211, 238, .20); }
.c.b2 { fill: rgba(34, 211, 238, .18); stroke: rgba(34, 211, 238, .34); }
.c.b3 { fill: rgba(34, 211, 238, .34); stroke: rgba(34, 211, 238, .55); }
.c.b4 { fill: rgba(34, 211, 238, .62); stroke: var(--accent); stroke-width: .6; }
.c.dot { stroke: var(--accent); }
/* Hovering has to answer even where the value is zero — silence reads as a
   broken map rather than as "nothing here". */
.c.hot { fill: #2a2636; }
.c.b0.hot { fill: url(#nodata); stroke: #6a5f7e; stroke-width: .9; }
.c.b1.hot { fill: rgba(34, 211, 238, .26); }
.c.b2.hot { fill: rgba(34, 211, 238, .38); }
.c.b3.hot { fill: rgba(34, 211, 238, .55); }
.c.b4.hot { fill: rgba(34, 211, 238, .85); }
@media (prefers-reduced-motion: no-preference) {
  .c { transition: fill .12s ease; }
}

.map-tip {
  position: absolute; z-index: 3; pointer-events: none;
  max-width: 22rem; padding: 9px 12px;
  background: rgba(10, 9, 14, .95);
  border: 1px solid var(--border); border-radius: 3px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, .55);
}
.map-tip[hidden] { display: none; }
.mt-name { color: var(--text); font-size: 13px; line-height: 1.5; }
.mt-count { color: var(--accent); font-size: 12px; line-height: 1.5; }
.mt-nets {
  margin-top: 3px; color: var(--accent);
  font-size: 11.5px; line-height: 1.6;
}
.mt-nets.mt-none { color: var(--dimmer); }
.mt-also { margin-top: 2px; color: var(--dimmer); font-size: 11px; }

.map-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  margin-top: 14px; font-size: 11.5px; color: var(--dim);
}
.ml-cap { color: var(--dim); margin-right: 4px; }
.ml-step { display: inline-flex; align-items: center; gap: 6px; color: var(--dimmer); }
.ml-step i {
  width: 13px; height: 13px; border-radius: 2px;
  border: 1px solid rgba(34, 211, 238, .25);
}
.ml-step i.b0 {
  border-color: #3a3446;
  background: repeating-linear-gradient(45deg, #131219 0 2px, #3a3446 2px 3px);
}
.ml-step i.b1 { background: rgba(34, 211, 238, .08); }
.ml-step i.b2 { background: rgba(34, 211, 238, .18); }
.ml-step i.b3 { background: rgba(34, 211, 238, .34); }
.ml-step i.b4 { background: rgba(34, 211, 238, .62); border-color: var(--accent); }
.ml-hint {
  margin-left: auto; color: var(--dimmer);
  letter-spacing: .14em; text-transform: uppercase; font-size: 10.5px;
}

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ── Visit ────────────────────────────────────────────────── */
.visit {
  margin-top: clamp(30px, 5vw, 56px);
  padding-block: clamp(56px, 8vw, 92px);
  border-top: 1px solid var(--border);
  text-align: center;
}
.visit-lede {
  margin: 0 0 26px;
  font-family: var(--serif); font-size: clamp(22px, 3vw, 30px);
  line-height: 1.4; color: var(--dim);
}
.visit-btn {
  display: inline-block; padding: 15px 42px;
  border: 1px solid var(--ember); border-radius: 3px; color: var(--candle);
  font-size: 13px; letter-spacing: .16em; text-transform: uppercase;
}
.visit-btn:hover { background: var(--ember); color: var(--bg-deep); text-decoration: none; }
.visit-note { margin: 18px 0 0; font-size: 11.5px; letter-spacing: .1em; color: var(--dimmer); }

/* ── Footer ───────────────────────────────────────────────── */
.foot {
  padding-block: 30px 56px; border-top: 1px solid var(--border);
  font-size: 12.5px; line-height: 1.8; color: var(--dim);
}
.credits { max-width: 46rem; }
.credits p { margin: 0 0 .9em; }
.credits .thin { color: var(--dimmer); }
.foot-back {
  display: inline-block; margin-top: 14px;
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--dimmer);
}
.foot-back:hover { color: var(--ember); text-decoration: none; }