/* Forecast Africa — highway signage design system, continental cut
 *
 * Sibling to Forecast Eagle, Forecast Canada, Forecast Mexico, Forecast American and
 * weather.city, and deliberately readable as one network: the same warm paper ground,
 * the same Overpass / Overpass Mono, the same guide-sign panel, exit chips, section
 * rules and card grid. What changes site to site is which colour holds the panel, and
 * what the roadway vocabulary is.
 *
 * The panel colour, and why it is brown
 * -------------------------------------
 * The network's palette is the U.S. MUTCD's, where colour is a job rather than a
 * decoration:
 *
 *     GREEN  #04663d  guide and wayfinding      — where you are, where you can go
 *     BLUE   #0a5ca8  services                  — what is available here
 *     BROWN  #6b4b2f  recreation and culture    — the land itself
 *     RED    #b0242e  regulatory and warning    — stop, and severe weather
 *
 * Green is Forecast Eagle's and Forecast Mexico's. Red is Forecast Canada's. Blue is
 * Forecast American's and Forecast Euro's. Brown is the one panel colour in the set
 * nothing on this network has taken, and it is the right one left: in the MUTCD it
 * signs parks, forests, deserts and national landmarks — *the land itself* — which is
 * the correct register for a continent whose weather is written by its geography more
 * than by its politics. It is also the only one of the four that reads as earth rather
 * than as institution, and at large panel size it is warm rather than loud.
 *
 * Guide green stays exactly where it is — the section rules, the live badge, the West
 * African accent — so nothing in the network's grammar moves. Only the panel.
 *
 * The regions are the beautiful part
 * ----------------------------------
 * Five accents sit alongside the MUTCD set, one per region, and they are what make a
 * continent legible at a glance:
 *
 *     --nf  #b5551f  copper           Northern Africa
 *     --wf  #04663d  guide green      Western Africa
 *     --mf  #0d8d9c  turquoise        Middle Africa
 *     --ef  #6d4aa8  amethyst         Eastern Africa
 *     --sf  #0a5ca8  service blue     Southern Africa
 *
 * Four of those five are the accents Forecast American already uses, deliberately
 * reassigned rather than reinvented: a reader who knows turquoise as "the wet
 * equatorial middle" on that site reads it the same way here, because the Congo basin
 * is the same kind of place as the Caribbean on a rainfall map. Copper goes to the
 * Sahara for the obvious reason.
 *
 * A region's accent is carried all the way down — the front-page card, the map fill,
 * the region page's rules, the chip on a country masthead — so the colour tells you
 * where you are before the words do.
 *
 * There is no yellow anywhere on this site, including the amber Forecast Canada uses
 * for a watch. Copper does that job here instead.
 *
 * Roadway vocabulary, replacing the Interstate set:
 *   - the route marker is a Trans-African Highway one. Unlike the Pan-American — which
 *     Forecast American had to fudge, because Peru signs it PE-1 and Chile Ruta 5 —
 *     the TAH network is genuinely numbered 1 to 9 across the whole continent by the
 *     AU, UNECA and AfDB, so the marker carries a real scheme rather than a count
 *   - exit chips are labelled EXITS · SORTIES · SAÍDAS, the three languages that
 *     actually appear on African road signage across the most ground, the way Forecast
 *     Canada labels its own bilingually. Arabic and Swahili are AU working languages
 *     too and are not on the chip for a mechanical reason: the chip is a 60 px
 *     monospace slot, and a right-to-left run inside a left-to-right one is a
 *     bidirectional-isolation problem that is not worth solving for decoration
 *   - distances and resolutions are km, and temperatures are °C, because that is what
 *     every country on this map uses
 */
:root {
  --paper: #e7e2d8;
  --paper2: #f3efe7;
  --card: #ffffff;
  --ink: #14181b;
  --ink2: #474339;

  /* Recreation brown — the guide-sign panel, and the site's primary note. */
  --sign: #6b4b2f;
  --sign-dk: #4a3320;
  --sign-tx: #ffffff;
  --sign-sub: #e6d8c7;

  /* Guide green — section rules, the live badge, anything that does wayfinding. */
  --green: #04663d;
  --green-dk: #02452a;
  --green-sub: #bdebcf;

  --blue: #0a5ca8;
  --navy: #103e7e;
  --blue-sub: #cfe2f6;

  --brown: #6b4b2f;
  --brown-dk: #4a3320;
  --brown-sub: #e6d8c7;

  --red: #b0242e;
  --red-dk: #7d1620;
  --red-sub: #f7d6d9;

  /* the five regions */
  --nf: #b5551f;  --nf-dk: #7d3812;  --nf-sub: #f3ddce;
  --wf: #04663d;  --wf-dk: #02452a;  --wf-sub: #d6e6d3;
  --mf: #0d8d9c;  --mf-dk: #075a65;  --mf-sub: #cfe9ec;
  --ef: #6d4aa8;  --ef-dk: #452c6f;  --ef-sub: #e0d7f0;
  --sf: #0a5ca8;  --sf-dk: #103e7e;  --sf-sub: #cfe2f6;

  --line: #c9c5bc;
  --line2: #e4e1d9;
  --mut: #8b877d;

  /* The sea. One value, used by the hero and by every country outline, so the
     hemisphere and the close-up are recognisably the same map. */
  --sea: #c3d8e2;
  --sea-dk: #a9c5d3;

  --font: 'Overpass', Helvetica, Arial, sans-serif;
  --mono-font: 'Overpass Mono', ui-monospace, monospace;
  --maxw: 1140px;
}

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

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }
img, svg { max-width: 100%; }

.mono { font-family: var(--mono-font); font-variant-numeric: tabular-nums; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 18px; }
.dim { color: var(--ink2); }
.faint { color: var(--mut); }
[hidden] { display: none !important; }

/* ── thin utility bar ─────────────────────────────────── */
.util {
  background: var(--ink); color: #cfccc4; border-bottom: 3px solid var(--sign);
  position: sticky; top: 0; z-index: 100; box-shadow: 0 1px 8px rgba(0, 0, 0, .22);
}
.util .bar {
  max-width: 1560px; margin: 0 auto; padding: 0 18px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 34px; flex-wrap: wrap;
}
.util .mono { font-size: 11px; letter-spacing: .06em; }
.util .lnks { display: flex; gap: 16px; flex-wrap: wrap; }
.util a { color: #e9e7e0; font-weight: 700; font-size: 11px; letter-spacing: .06em; }
.util a:hover { color: var(--sign-sub); text-decoration: none; }
.util a[aria-current="page"] { color: var(--sign-sub); }

/* ── region strip ─────────────────────────────────────────
   The second tier of the masthead, and the site's real navigation: four regions is a
   short enough list to sit permanently on every page, and a reader who wants the
   Caribbean wants it from wherever they happen to be. Each carries its own accent as
   a left rule, so the strip is also the colour key for the whole site. */
.regbar {
  background: var(--sign-dk); color: var(--sign-sub);
  border-bottom: 1px solid rgba(0, 0, 0, .25);
}
.regbar .bar {
  max-width: 1560px; margin: 0 auto; padding: 5px 18px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.regbar .lbl {
  font: 700 9px var(--mono-font); letter-spacing: .14em;
  color: rgba(255, 255, 255, .55); white-space: nowrap;
}
.regbar .lnks { display: flex; gap: 5px; flex-wrap: wrap; }
.regbar a {
  font: 800 11px var(--font); letter-spacing: .02em; color: #fff;
  padding: 2px 8px 2px 7px; border-radius: 3px; white-space: nowrap;
  border-left: 3px solid transparent;
}
.regbar a.nf { border-left-color: #64b78d; }
.regbar a.wf { border-left-color: #64b78d; }
.regbar a.mf { border-left-color: #64b78d; }
.regbar a.ef { border-left-color: #64b78d; }
.regbar a.sf { border-left-color: #64b78d; }
.regbar a:hover { background: rgba(255, 255, 255, .18); text-decoration: none; }
.regbar a[aria-current="page"] { background: #fff; color: var(--sign-dk); }

/* ── guide sign panel ─────────────────────────────────── */
.sign {
  background: var(--sign); border-radius: 10px; color: var(--sign-tx);
  padding: 26px 24px 24px; position: relative;
  box-shadow: inset 0 0 0 4px var(--sign), inset 0 0 0 6px rgba(255, 255, 255, .9),
              0 10px 30px rgba(0, 0, 0, .16);
}
.sign a { color: #fff; }
.signhead { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.signhead > img, .signhead > svg { width: 62px; height: 62px; flex: none; display: block; }
.word {
  font-weight: 900; font-size: clamp(28px, 5.4vw, 50px); line-height: .92;
  letter-spacing: -.02em; margin: 0;
}
.word .yl { color: var(--sign-sub); }
.tag {
  margin: 8px 0 0; font-weight: 700; font-size: clamp(13px, 2.2vw, 16px);
  color: var(--sign-sub); letter-spacing: .01em;
}

/* The route marker. There is no one Pan-American Highway shield — Peru signs it as
   PE-1, Chile as Ruta 5, Argentina as RN3 — so this is the network's own blank in the
   guide-sign idiom rather than a transcription of a real one, and it carries a count
   instead of a route number. White on the panel, the way the Trans-Canada marker is
   on Forecast Canada. */
.shield {
  background: #fff; color: var(--green); border-radius: 4px 4px 10px 10px;
  padding: 5px 11px 7px; text-align: center; line-height: 1; flex: none;
  display: inline-block; box-shadow: 0 2px 0 rgba(0, 0, 0, .18);
}
.shield .a { font-size: 8px; font-weight: 700; letter-spacing: .14em; color: var(--green); display: block; }
.shield .b { font-size: 22px; font-weight: 900; letter-spacing: .02em; display: block; color: var(--green-dk); }
.shield .c { font-size: 8px; font-weight: 700; letter-spacing: .12em; color: var(--green); display: block; }

/* Exit-style chips. Three languages, because the road runs through all three. */
.exits { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; align-items: center; }
.exits .lbl { font-size: 11px; font-weight: 700; letter-spacing: .12em; color: var(--sign-sub); }
.mm {
  background: rgba(255, 255, 255, .12); border: 1.5px solid rgba(255, 255, 255, .6);
  border-radius: 5px; padding: 6px 12px; font-family: inherit; font-weight: 700;
  font-size: 12px; letter-spacing: .03em; cursor: pointer; color: #fff;
}
.mm:hover { background: #fff; color: var(--sign); text-decoration: none; }

/* A flag riding in the masthead, on a country page. Given a white keyline so a flag
   with a white field — Honduras, Argentina, Guatemala — still reads as an object on
   the blue rather than bleeding into the panel. */
.signflag {
  width: 84px; height: 63px; flex: none; display: block; border-radius: 3px;
  object-fit: cover; box-shadow: 0 0 0 2px rgba(255, 255, 255, .95),
                                 0 3px 10px rgba(0, 0, 0, .3);
}

/* ── section rule header ──────────────────────────────── */
section { padding: 26px 0 4px; }
.rule { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.rule .ln {
  height: 3px; flex: 1; color: var(--green); opacity: .6;
  background: repeating-linear-gradient(90deg, currentColor 0 18px, transparent 18px 34px);
}
.rule h2 {
  margin: 0; color: var(--green); font-size: 15px; font-weight: 900;
  text-transform: uppercase; letter-spacing: .12em; white-space: nowrap;
}
.rule .sub { color: var(--mut); font-size: 11px; font-weight: 700; letter-spacing: .06em;
  font-family: var(--mono-font); text-transform: uppercase; }
.rule.blue h2, .rule.blue .ln { color: var(--blue); }
.rule.brown h2, .rule.brown .ln { color: var(--brown); }
.rule.red h2, .rule.red .ln { color: var(--red); }
.rule.nf h2, .rule.nf .ln { color: var(--nf); }
.rule.wf h2, .rule.wf .ln { color: var(--wf); }
.rule.mf h2, .rule.mf .ln { color: var(--mf); }
.rule.ef h2, .rule.ef .ln { color: var(--ef); }
.rule.sf h2, .rule.sf .ln { color: var(--sf); }

/* ── cards ────────────────────────────────────────────── */
.card-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 0; overflow: hidden; display: block; color: inherit;
  box-shadow: 0 6px 22px rgba(0, 0, 0, .08); transition: transform .14s, box-shadow .14s;
}
a.card:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0, 0, 0, .13); text-decoration: none; }
.card .chead {
  background: var(--green); color: #fff; padding: 9px 14px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .35);
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  font-weight: 900; letter-spacing: .02em;
}
.card .chead.blue { background: var(--blue); }
.card .chead.red { background: var(--red); }
.card .chead.brown { background: var(--brown); }
.card .chead.nf { background: var(--nf); }
.card .chead.wf { background: var(--wf); }
.card .chead.mf { background: var(--mf); }
.card .chead.ef { background: var(--ef); }
.card .chead.sf { background: var(--sf); }
.card .chead .k { font-size: 10px; font-weight: 700; letter-spacing: .1em;
  color: rgba(255, 255, 255, .78); font-family: var(--mono-font); }
.card .cbody { padding: 14px; }
.card h3 { margin: 0 0 5px; font-size: 17px; font-weight: 900; letter-spacing: -.01em; }
.card p { margin: 0; color: var(--ink2); font-size: 13.5px; font-weight: 600; line-height: 1.5; }

.panel {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 16px; box-shadow: 0 6px 22px rgba(0, 0, 0, .08);
}
.panel p { font-size: 14px; font-weight: 600; color: var(--ink2); }
.panel p:first-child { margin-top: 0; }
.panel p:last-child { margin-bottom: 0; }

/* ── the country grid ─────────────────────────────────────
   The heart of the site: fifty-five flags, each one a way in. The flag is the whole
   left column rather than an icon beside the name, because at this size a flag is
   recognised faster than any label — which is the entire reason for showing them.
   The region's accent runs down the left edge as a five-pixel rule, so a grid sorted
   by region reads as four blocks without needing four headings. */
.countrygrid { display: grid; gap: 11px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.cty {
  display: flex; align-items: stretch; gap: 0; background: var(--card);
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden; color: inherit;
  box-shadow: 0 5px 16px rgba(0, 0, 0, .06);
  transition: transform .13s, box-shadow .13s, border-color .13s;
  position: relative;
}
a.cty:hover { transform: translateY(-2px); box-shadow: 0 11px 24px rgba(0, 0, 0, .13);
  text-decoration: none; }
.cty .edge { width: 5px; flex: none; background: var(--line); }
.cty.nf .edge { background: var(--nf); } .cty.nf:hover { border-color: var(--nf); }
.cty.wf .edge { background: var(--wf); } .cty.wf:hover { border-color: var(--wf); }
.cty.mf .edge { background: var(--mf); } .cty.mf:hover { border-color: var(--mf); }
.cty.ef .edge { background: var(--ef); } .cty.ef:hover { border-color: var(--ef); }
.cty.sf .edge { background: var(--sf); } .cty.sf:hover { border-color: var(--sf); }
.cty .fl {
  width: 52px; height: 39px; flex: none; margin: 12px 0 12px 11px; border-radius: 2px;
  object-fit: cover; background: var(--line2);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .16), 0 1px 3px rgba(0, 0, 0, .18);
}
.cty .txt { padding: 11px 12px 11px 11px; min-width: 0; flex: 1 1 auto; }
.cty .nm { display: block; font-size: 14.5px; font-weight: 900; letter-spacing: -.01em;
  line-height: 1.2; }
.cty .sub { display: block; font-family: var(--mono-font); font-size: 9.5px;
  font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--mut);
  margin-top: 3px; }
.cty .tm { display: flex; align-items: center; gap: 5px; font-size: 19px; font-weight: 900;
  letter-spacing: -.02em; margin-top: 5px; line-height: 1; min-height: 21px; }
.cty .tm .un { font-size: 11px; font-weight: 800; color: var(--mut); }

/* A country with a site of its own is not a page here, and the card says so before it
   is clicked: an outbound arrow, and the sibling's name where the capital would be. */
.cty .out { position: absolute; top: 7px; right: 9px; font-size: 11px; font-weight: 900;
  color: var(--mut); }
a.cty:hover .out { color: var(--sign); }
.cty.linked { background: linear-gradient(180deg, #fff 0%, var(--paper2) 100%); }

/* ── the weather symbols ──────────────────────────────────
   Drawn by assets/wxicons.js as inline SVG rather than set as emoji. The cloud takes
   `currentColor`, so a symbol sitting in muted text is muted and one in body text is
   not; the sun, the rain and the bolt carry their own colour, because a grey sun is
   not a sun and the whole job of the symbol is to separate "cloudy" from "raining"
   before the word underneath is read. */
.wxi { display: inline-block; vertical-align: -.16em; flex: none;
  color: var(--ink2); }
.placetile .gl .wxi { color: var(--mut); }
.cty .tm .wxi { color: var(--mut); }
.nowcond .wxi { color: var(--ink2); margin-right: 9px; vertical-align: -.22em; }

/* ── flags elsewhere ──────────────────────────────────── */
.flagchip { display: inline-flex; align-items: center; gap: 7px; }
.flagchip img { width: 22px; height: 16.5px; border-radius: 1px; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .18); }

/* ── controls ─────────────────────────────────────────── */
.btn {
  cursor: pointer; border: 1px solid var(--line); background: #fff; color: var(--ink2);
  border-radius: 3px; font-family: var(--font); font-weight: 700; font-size: 11.5px;
  letter-spacing: .02em; padding: 7px 12px; line-height: 1.3;
}
.btn:hover { border-color: var(--green); color: var(--ink); }
.btn:disabled { opacity: .5; cursor: default; }
select, input[type="text"], input[type="search"] {
  background: #fff; border: 1px solid var(--line); color: var(--ink);
  border-radius: 3px; padding: 6px 9px; font-family: var(--font);
  font-weight: 700; font-size: 12px;
}
select:focus, input:focus, .btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
label { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--mut); }

.seg { display: flex; }
.seg button { font: 700 11px var(--mono-font); background: var(--card); color: var(--ink2);
  border: 1px solid var(--line); border-left-width: 0; padding: 5px 9px; cursor: pointer; }
.seg button:first-child { border-left-width: 1px; border-radius: 4px 0 0 4px; }
.seg button:last-child { border-radius: 0 4px 4px 0; }
.seg button:hover { color: var(--ink); }
.seg button.on { background: var(--sign); color: #fff; border-color: var(--sign-dk); }
.seg button:disabled { cursor: not-allowed; }
/* A segment the active model cannot drive at all — GFS publishes no pressure field, so
   it has no isobars to draw. Greyed as a block rather than hidden, for the same reason
   the field picker greys instead of removing: "this model does not have that" is
   information, and a control strip that changes length as you switch models is
   disorienting. */
/* A field that a model publishes over part of the globe on purpose — GFS's
   ocean-only MSLP. Set apart from the description rather than run into it, because it
   is a caveat about *this* model rather than a fact about the field. */
.xp-masknote { color: var(--sign); font-style: italic; }

.seg.unavailable { opacity: .35; }
.seg.unavailable button { cursor: not-allowed; text-decoration: line-through;
  text-decoration-thickness: 1px; }

.unitrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.unitrow .lbl { font-family: var(--mono-font); font-size: 10.5px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--mut); }

/* ── badges ───────────────────────────────────────────── */
.badge { display: inline-block; padding: 3px 9px; border-radius: 3px;
  font-size: 10px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; }
.badge-live { background: var(--green); color: #fff; }
.badge-new { background: var(--sign); color: #fff; }
.badge-soon { background: #efece5; color: var(--mut); border: 1px solid var(--line); }

.stamp { font-family: var(--mono-font); font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--mut); }

/* ── breadcrumbs ──────────────────────────────────────── */
.crumbs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-family: var(--mono-font); font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--mut); margin: 0 0 12px; }
.crumbs a { color: var(--green); }
.crumbs .sep { color: var(--line); }

/* ══════════════════════════════════════════════════════════════════════════
   The hemisphere map
   ------------------------------------------------------------------------
   Flat colour, not relief. The whole point of this map is that a country is a
   thing you click, and a photographic basemap fights that — Forecast Canada's
   front page makes the same call for the same reason. Land is the region's
   accent at low saturation, sea is one flat value, and the accent at full
   strength is reserved for the two things that are live: a hovered country and
   its outline.
   ══════════════════════════════════════════════════════════════════════════ */
.herostage { position: relative; margin: 16px auto 0; max-width: 900px;
  background: linear-gradient(180deg, #d3e3ea 0%, var(--sea) 55%, var(--sea-dk) 100%);
  border: 1px solid var(--line); border-radius: 10px; padding: 10px;
  box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .55), 0 10px 28px rgba(0, 0, 0, .10); }
.herostage svg { display: block; width: 100%; height: auto;
  opacity: 0; transition: opacity .5s ease; }
.herostage svg.in { opacity: 1; }

#heroMap .cn path { stroke: rgba(255, 255, 255, .85); stroke-width: 1.1;
  stroke-linejoin: round; transition: fill .13s ease, stroke-width .13s ease;
  cursor: pointer; }
/* The resting fills. These five are the `tint` values in tools/roster.py, and the
   front page's map legend is generated from that table — so if one of these changes
   here and not there, the legend stops matching the map. The roster is the source. */
#heroMap .cn.nf path { fill: #f0d8c8; }
#heroMap .cn.wf path { fill: #cfe0cd; }
#heroMap .cn.mf path { fill: #c9e5e8; }
#heroMap .cn.ef path { fill: #ddd4ec; }
#heroMap .cn.sf path { fill: #cddfef; }
/* A country with a site of its own is drawn a shade back, the way Forecast Canada
   ghosts the United States: still land, plainly not this site's subject. */
#heroMap .cn.linked path { fill: #cfcdc4; }
#heroMap .cn a:hover path, #heroMap .cn path.on { stroke: #fff; stroke-width: 2.2; }
#heroMap .cn.nf a:hover path, #heroMap .cn.nf path.on { fill: var(--nf); }
#heroMap .cn.wf a:hover path, #heroMap .cn.wf path.on { fill: var(--wf); }
#heroMap .cn.mf a:hover path, #heroMap .cn.mf path.on { fill: var(--mf); }
#heroMap .cn.ef a:hover path, #heroMap .cn.ef path.on { fill: var(--ef); }
#heroMap .cn.sf a:hover path, #heroMap .cn.sf path.on { fill: var(--sf); }
#heroMap .cn.linked a:hover path { fill: var(--sign); }
#heroMap .cn a:focus path { outline: none; stroke: #fff; stroke-width: 2.6; }

/* Hovering a region — in the strip at the top or on its card — lights every country
   in it at once. It is the answer to the question a reader who has never had to place
   Curaçao actually has, which is not "where is Curaçao" but "which of these is the
   Caribbean". */
#heroMap .cn.lit path { stroke: #fff; stroke-width: 2; }
#heroMap .cn.nf.lit path { fill: var(--nf); }
#heroMap .cn.wf.lit path { fill: var(--wf); }
#heroMap .cn.mf.lit path { fill: var(--mf); }
#heroMap .cn.ef.lit path { fill: var(--ef); }
#heroMap .cn.sf.lit path { fill: var(--sf); }

/* The invisible disc a speck is clicked by. It has to be in the flow to take a
   pointer, so it is filled transparent rather than hidden. */
#heroMap .hit { fill: transparent; cursor: pointer; }
#heroMap .cn a:hover .hit { fill: rgba(13, 141, 156, .22); }

/* Equator and the two tropics. Dashed, thin, and under everything — they are a
   reference, not a feature, and on this map they are also the reason half the
   forecasts on it look the way they do. */
#heroMap .lines path { fill: none; stroke: rgba(30, 70, 92, .3); stroke-width: 1;
  stroke-dasharray: 7 7; pointer-events: none; }
#heroMap .lines path.major { stroke-width: 1.8; stroke: rgba(30, 70, 92, .42); }
#heroMap .lines text { font-family: var(--mono-font); font-size: 11px; font-weight: 700;
  fill: rgba(20, 55, 74, .55); letter-spacing: .1em; pointer-events: none; }

#heroMap .lead { stroke: rgba(30, 45, 55, .5); stroke-width: .9; fill: none;
  pointer-events: none; }
#heroMap .lbl text { font-family: var(--mono-font); font-size: 15px; font-weight: 700;
  letter-spacing: .06em; fill: #1c2a33; paint-order: stroke;
  stroke: rgba(255, 255, 255, .8); stroke-width: 3.2; stroke-linejoin: round;
  pointer-events: none; }

.herohint { position: absolute; transform: translate(-50%, -190%); pointer-events: none;
  background: var(--ink); color: #fff; border-radius: 5px; padding: 5px 10px;
  font-family: var(--mono-font); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
  opacity: 0; transition: opacity .12s ease; z-index: 3; }
.herohint.show { opacity: 1; }

.herolegend { display: flex; gap: 16px; flex-wrap: wrap; align-items: center;
  justify-content: center; margin-top: 11px; }
.herolegend .lg { display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono-font); font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--mut); }
.herolegend .sw { width: 13px; height: 13px; border-radius: 3px; border: 1px solid rgba(0,0,0,.15); }

/* ── the island strip ─────────────────────────────────────
   Twenty-eight Caribbean entries cannot be labelled on a hemisphere map and cannot be
   left off the site, so they get a strip of their own directly under it: flag, name,
   nothing else. It is the same solution an atlas uses for the Lesser Antilles, and it
   doubles as the answer to "which of these am I looking at". */
.islands { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px;
  justify-content: center; }
.isl { display: inline-flex; align-items: center; gap: 6px; background: var(--card);
  border: 1px solid var(--line); border-radius: 20px; padding: 4px 11px 4px 5px;
  font-size: 12px; font-weight: 800; color: inherit; transition: .12s; }
.isl img { width: 20px; height: 15px; border-radius: 1px; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .18); }
.isl:hover { border-color: var(--ef); color: var(--ef-dk); transform: translateY(-1px);
  text-decoration: none; }

/* ══════════════════════════════════════════════════════════════════════════
   Country pages
   ══════════════════════════════════════════════════════════════════════════ */

/* the live conditions headline.
   The place, the station and the raw report run the full width of the panel rather
   than sharing the temperature's column: the station line is the caveat that makes
   the number honest — which aerodrome, how far, how high — and it is a sentence, not
   a caption. Squeezed beside a 78 px numeral it wrapped four times and read as fine
   print, which is exactly the wrong weight for it. */
.nowplace { font-size: 20px; font-weight: 900; letter-spacing: -.01em; margin: 0 0 2px; }
.nowstation { font-family: var(--mono-font); font-size: 11.5px; font-weight: 700;
  color: var(--mut); letter-spacing: .02em; margin: 0 0 16px;
  padding-bottom: 13px; border-bottom: 1px solid var(--line2); }
.nowraw { font-size: 11.5px; color: var(--mut); word-break: break-word; margin: 0;
  background: var(--paper2); border: 1px solid var(--line2); border-radius: 5px;
  padding: 8px 10px; }
#nowstamp { margin: 15px 0 6px; }

.nowcard { display: grid; gap: 18px; grid-template-columns: minmax(210px, 300px) 1fr;
  align-items: center; }
@media (max-width: 660px) { .nowcard { grid-template-columns: 1fr; } }
.nowtemp { display: flex; align-items: baseline; gap: 10px; }
.nowtemp .deg { font-size: clamp(52px, 11vw, 78px); font-weight: 900; line-height: .95;
  letter-spacing: -.03em; color: var(--ink); }
.nowtemp .un { font-size: 17px; font-weight: 900; color: var(--mut); }
/* No reading. An em dash at 78 px is a black bar and reads as a redaction, so the
   empty state is set small and muted — it is an absence, and it should look like one. */
.nowtemp.none .deg { font-size: 40px; color: var(--mut); }
.nowtemp.none .un { display: none; }
.nowcond { font-size: 17px; font-weight: 800; margin: 9px 0 0;
  display: flex; align-items: center; }
.nowmeta { display: grid; gap: 10px 22px; grid-template-columns: repeat(auto-fit, minmax(126px, 1fr)); }
.nowmeta div { border-left: 3px solid var(--green); padding-left: 10px; }
.nowmeta .k { display: block; font-family: var(--mono-font); font-size: 10px;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--mut); }
.nowmeta .v { display: block; font-size: 17px; font-weight: 800; }

/* place tiles carrying a live reading */
.placegrid { display: grid; gap: 11px;
  grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); }
.placetile { background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 13px; display: block; color: inherit; position: relative;
  box-shadow: 0 5px 18px rgba(0, 0, 0, .07); transition: transform .14s, box-shadow .14s; }
a.placetile:hover { transform: translateY(-2px); box-shadow: 0 9px 22px rgba(0, 0, 0, .12);
  text-decoration: none; }
.placetile .nm { font-size: 15px; font-weight: 900; letter-spacing: -.01em; display: block; }
.placetile .sub { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--mut); }
.placetile .row { display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 9px; }
.placetile .tm { font-size: 27px; font-weight: 900; line-height: 1; letter-spacing: -.02em; }
.placetile .gl { font-size: 21px; line-height: 1; }
.placetile .cd { font-size: 12px; font-weight: 700; color: var(--ink2); margin-top: 4px;
  min-height: 1.2em; }
/* the capital, marked with a rule rather than a second colour or a glyph */
.placetile.cap { box-shadow: inset 3px 0 0 var(--sign), 0 5px 18px rgba(0, 0, 0, .07); }

/* The selected place — the one the headline is showing. It is the only state on this
   page that is not data, so it gets the panel colour and nothing else does. */
.placetile[aria-current="true"] { border-color: var(--sign);
  box-shadow: 0 0 0 2px var(--sign-sub), 0 8px 20px rgba(0, 0, 0, .12); }
.placetile[aria-current="true"].cap { box-shadow: inset 3px 0 0 var(--sign),
  0 0 0 2px var(--sign-sub), 0 8px 20px rgba(0, 0, 0, .12); }
.placetile { cursor: pointer; }
.placetile:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* A place whose station is silent, or which has none. Dimmed rather than hidden:
   that a country has gaps in its observing network is information, and in this
   hemisphere it is often the most interesting thing on the page. */
.placetile.quiet { opacity: .62; }
.placetile.quiet .tm { color: var(--mut); }
.ctymap .dot.quiet { fill: var(--mut); opacity: .55; }

/* the seven-day column set */
.fcstrip { display: grid; gap: 9px;
  grid-template-columns: repeat(auto-fill, minmax(122px, 1fr)); }
.fcday { background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 11px 12px; }
.fcday .d { font-family: var(--mono-font); font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--green); }
.fcday .g { font-size: 25px; line-height: 1.15; }
.fcday .t { font-size: 22px; font-weight: 900; letter-spacing: -.02em; }
.fcday .t .lo { color: var(--blue); }
.fcday .c { font-size: 12px; font-weight: 600; color: var(--ink2); line-height: 1.35; }
.fcday .p { font-family: var(--mono-font); font-size: 10.5px; font-weight: 700;
  color: var(--blue); letter-spacing: .05em; }

/* the 24-hour scroller */
.hrscroll { overflow-x: auto; padding-bottom: 4px; }
.hrrow { display: flex; gap: 8px; min-width: max-content; }
.hrcell { flex: 0 0 auto; width: 74px; text-align: center; background: var(--card);
  border: 1px solid var(--line); border-radius: 7px; padding: 9px 4px; }
.hrcell .h { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  color: var(--mut); letter-spacing: .05em; }
.hrcell .g { font-size: 17px; line-height: 1.3; }
.hrcell .t { font-size: 16px; font-weight: 900; }
.hrcell .p { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  color: var(--blue); }

/* the country outline map */
.ctymap { background: linear-gradient(180deg, #d8e6ec 0%, var(--sea) 100%);
  border: 1px solid var(--line); border-radius: 8px; padding: 8px; }
/* Chile is fourteen times taller than it is wide and Greenland is not far off. Left
   alone those render as a metre-long column, so the frame is capped and the outline
   letterboxes inside it — the shape stays honest, which a squashed viewBox would not. */
.ctymap svg { display: block; width: 100%; height: auto; max-height: 620px; }
.ctymap .ghost { fill: #cdc8bd; stroke: #b9b3a5; stroke-width: 1.2; }
.ctymap .home { fill: #f0ece2; stroke: var(--sign); stroke-width: 2.4; stroke-linejoin: round; }
.ctymap .road { fill: none; stroke: var(--brown); stroke-width: 1.1; opacity: .5;
  stroke-linecap: round; stroke-linejoin: round; }
.ctymap .dot { fill: var(--green); stroke: #fff; stroke-width: 2; cursor: pointer; }
.ctymap .dot.cap { fill: var(--red); stroke-width: 2.4; }
.ctymap text.lb { font-family: var(--font); font-weight: 800; fill: #fff;
  paint-order: stroke; stroke: rgba(12, 16, 20, .88); stroke-width: 4;
  stroke-linejoin: round; pointer-events: none; }
.ctymap text.gh { font-family: var(--mono-font); font-weight: 700; font-size: 15px;
  fill: rgba(255, 255, 255, .9); paint-order: stroke; stroke: rgba(60, 55, 45, .7);
  stroke-width: 3.4; stroke-linejoin: round; letter-spacing: .1em; }

/* the facts row under a country masthead */
.facts { display: grid; gap: 1px; background: var(--line);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.facts div { background: var(--card); padding: 11px 13px; }
.facts .k { display: block; font-family: var(--mono-font); font-size: 9.5px;
  font-weight: 700; letter-spacing: .11em; text-transform: uppercase; color: var(--mut); }
.facts .v { display: block; font-size: 16px; font-weight: 900; margin-top: 3px; }
.facts .v small { font-size: 11px; font-weight: 700; color: var(--mut); }

/* the neighbour compass */
.compass { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.compass .nb { display: inline-flex; align-items: center; gap: 7px; background: var(--card);
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 12px;
  font-size: 13.5px; font-weight: 800; color: inherit; }
.compass .nb:hover { border-color: var(--green); text-decoration: none; }
.compass .nb img { width: 20px; height: 15px; border-radius: 1px; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .18); }
.compass .nb .ar { color: var(--green); font-weight: 900; }

/* ── footer ───────────────────────────────────────────── */
.site-footer {
  border-top: 3px solid var(--sign); margin-top: 44px; padding: 20px 0 34px;
  color: var(--ink2); font-size: 12.5px; font-weight: 600; background: #ddd8ce;
}
.site-footer a { color: var(--navy); font-weight: 800; }
.site-footer .cols { display: flex; flex-wrap: wrap; gap: 22px 44px;
  justify-content: space-between; margin-bottom: 16px; }
.site-footer h4 { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--mut); margin: 0 0 7px; }
.site-footer .col a { display: block; padding: 2px 0; color: var(--ink2); font-weight: 700; }
.site-footer .col a:hover { color: var(--sign); }
.site-footer .fine { max-width: 720px; line-height: 1.55; }

/* the zero-station notice, and the stale-feed notice — the same element, in copper
   rather than red, because neither is a warning and this site keeps red for warnings */
#obswarn { background: var(--nf-sub); border: 1px solid #dda87f; border-radius: 7px;
  padding: 10px 13px; font-size: 13.5px; font-weight: 700; color: var(--nf-dk);
  margin: 0 0 13px; }

.skip {
  position: absolute; left: -9999px; top: 0; background: var(--sign); color: #fff;
  padding: 9px 14px; z-index: 200; font-weight: 800;
}
.skip:focus { left: 0; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media (max-width: 620px) {
  #heroMap .lbl text { font-size: 21px; }
  #heroMap .lines text { font-size: 15px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   The model explorer
   ------------------------------------------------------------------------
   The one dark component on a site that is otherwise paper throughout. That
   is deliberate and it is the same call weather.city makes for its national
   outlook figures: a model raster is a photograph of a field, it is dense and
   saturated, and a warm paper ground fights it. Framing it in a dark inset
   says "this is imagery" the way a mount says it around a print.

   Everything around the frame stays on paper, so the page still reads as part
   of the site rather than as a different application.
   ══════════════════════════════════════════════════════════════════════════ */

.wrap-wide { max-width: 1560px; margin: 0 auto; padding: 0 18px; }
.sign-tight { padding: 16px 20px 15px; }
.sign-tight .signhead > img { width: 52px; height: 52px; }

.xp { margin-top: 18px; }

/* ── the control bars ─────────────────────────────────── */
.xp-bar {
  display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-start;
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 15px; box-shadow: 0 6px 22px rgba(0, 0, 0, .07);
}
.xp-bar2 { margin-top: 9px; padding: 10px 15px; }
.xp-grp { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.xp-grow { flex: 1 1 320px; }
.xp-desc { margin: 2px 0 0; font-size: 12px; font-weight: 600; color: var(--mut);
  line-height: 1.4; }

/* The model picker. Three buttons, each carrying the centre that made the model and
   the resolution it runs at — because on this page "which model" and "whose model"
   are the same question, and the answer is the reason to click. */
.mdls { display: flex; gap: 7px; flex-wrap: wrap; }
.mdl {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  background: var(--card); border: 1.5px solid var(--line); border-radius: 7px;
  padding: 7px 13px 6px; cursor: pointer; font-family: var(--font); color: var(--ink2);
  transition: border-color .12s, background .12s, color .12s; line-height: 1.15;
}
.mdl .n { font-size: 15px; font-weight: 900; letter-spacing: -.01em; color: var(--ink); }
.mdl .c { font-family: var(--mono-font); font-size: 9px; font-weight: 700;
  letter-spacing: .1em; color: var(--mut); }
.mdl .r { font-family: var(--mono-font); font-size: 9px; font-weight: 700;
  letter-spacing: .06em; color: var(--mut); }
.mdl:hover:not(:disabled) { border-color: var(--sign); }
.mdl.on { background: var(--sign); border-color: var(--sign-dk); }
.mdl.on .n, .mdl.on .c, .mdl.on .r { color: #fff; }
.mdl.on .c, .mdl.on .r { color: var(--sign-sub); }
.mdl.dead { opacity: .4; cursor: not-allowed; }

/* The field picker. A field the active model does not publish is greyed rather than
   removed — see the note in explorer.js. */
.flds { display: flex; gap: 5px; flex-wrap: wrap; }
.fld {
  font: 800 11.5px var(--font); letter-spacing: .02em; background: var(--card);
  color: var(--ink2); border: 1px solid var(--line); border-radius: 5px;
  padding: 6px 11px; cursor: pointer; transition: .12s;
}
.fld:hover:not(:disabled) { border-color: var(--green); color: var(--ink); }
.fld.on { background: var(--green); border-color: var(--green-dk); color: #fff; }
.fld.off { opacity: .35; cursor: not-allowed; text-decoration: line-through;
  text-decoration-thickness: 1px; }

.rgns { display: flex; gap: 5px; flex-wrap: wrap; }
.rgn {
  font: 700 11px var(--mono-font); letter-spacing: .04em; text-transform: uppercase;
  background: var(--card); color: var(--ink2); border: 1px solid var(--line);
  border-radius: 20px; padding: 5px 12px; cursor: pointer; transition: .12s;
}
.rgn:hover { border-color: var(--mf); color: var(--mf-dk); }

#opacity { width: 150px; accent-color: var(--sign); }

/* ── the map stage ────────────────────────────────────── */
.xp-stage {
  position: relative; margin-top: 11px; border-radius: 10px; overflow: hidden;
  background: #0a0e14; border: 1px solid #223142;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .22);
}
#map { width: 100%; height: min(74vh, 820px); min-height: 420px; }

/* MapLibre's own chrome, re-dressed to the site rather than left as its default blue */
.maplibregl-ctrl-group { border-radius: 6px !important; box-shadow: 0 2px 8px rgba(0,0,0,.3) !important; }
.maplibregl-ctrl-scale { background: rgba(10,14,20,.6) !important; border-color: rgba(255,255,255,.4) !important;
  color: #dfe6ea !important; font-family: var(--mono-font) !important; font-size: 10px !important; }

.xp-hud {
  position: absolute; top: 12px; left: 12px; right: 12px; display: flex;
  justify-content: space-between; align-items: flex-start; gap: 12px;
  pointer-events: none; z-index: 2;
}
.xp-stamp {
  background: rgba(10, 14, 20, .82); border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 6px; padding: 7px 12px; color: #fff; line-height: 1.15;
}
.xp-stamp .sv { display: block; font: 900 17px var(--mono-font); letter-spacing: .02em; }
.xp-stamp .sf { display: block; font: 700 10.5px var(--mono-font); letter-spacing: .1em;
  color: #9fc4e0; margin-top: 2px; }

.xp-read {
  background: rgba(10, 14, 20, .82); border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 6px; padding: 7px 12px; text-align: right; min-width: 120px;
}
.xp-read:empty { display: none; }
.xp-read .pv { display: block; font: 900 19px var(--mono-font); color: #fff; }
.xp-read .pv.dim { color: #6f8496; }
.xp-read .pxy { display: block; font: 700 10px var(--mono-font); letter-spacing: .06em;
  color: #9fb3c4; margin-top: 2px; }

.xp-attrib {
  position: absolute; bottom: 0; right: 0; z-index: 2;
  background: rgba(10, 14, 20, .74); color: #b9c9d6; border-radius: 6px 0 0 0;
  padding: 5px 11px; font: 700 10px var(--mono-font); letter-spacing: .05em;
  text-transform: uppercase;
}
.xp-attrib a { color: #9fc4e0; }

/* The pinned point for the compare readout. A ring rather than a filled dot: whatever
   is under it is the thing being measured, and a solid marker hides it. */
.pinmark {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2.5px solid #fff; box-shadow: 0 0 0 2px rgba(10, 14, 20, .75);
  background: transparent; cursor: crosshair;
}

.xp-offset {
  margin: 9px 0 0; font: 700 12px var(--font); color: var(--nf-dk);
  background: var(--nf-sub); border: 1px solid #dda87f; border-radius: 6px;
  padding: 8px 12px;
}

/* ── legend and compare ───────────────────────────────── */
.xp-legend, .xp-compare {
  margin-top: 11px; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; padding: 12px 15px; box-shadow: 0 6px 22px rgba(0, 0, 0, .07);
}
.lg-head { display: flex; justify-content: space-between; align-items: baseline;
  gap: 14px; flex-wrap: wrap; margin-bottom: 9px; }
.lg-t { font-size: 14.5px; font-weight: 900; letter-spacing: -.01em; }
.lg-u { font-family: var(--mono-font); font-size: 11px; font-weight: 700;
  color: var(--mut); margin-left: 5px; }

.lg-bar { height: 15px; border-radius: 3px; border: 1px solid var(--line);
  overflow: hidden; }
/* A banded table draws hard steps and a continuous ramp draws a gradient, from the
   same stop array — the only thing that differs is whether the colour is allowed to
   interpolate, which is exactly the difference between the two products. */
.lg-bar.banded { display: flex; }
.lg-bar.banded span { flex: 1 1 0; }
.lg-ax { display: flex; justify-content: space-between; margin-top: 4px;
  font: 700 10px var(--mono-font); color: var(--mut); }

.cmp-rows { display: grid; gap: 9px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.cmp-empty { grid-column: 1 / -1; margin: 0; font-size: 13px; font-weight: 600;
  color: var(--mut); }
.cmp {
  border: 1px solid var(--line); border-radius: 7px; padding: 9px 12px;
  background: var(--paper2); display: flex; flex-direction: column; gap: 1px;
}
/* The model currently drawn on the map is marked, so the column you are reading is
   tied to the picture you are looking at. */
.cmp.on { border-color: var(--sign); background: #fff;
  box-shadow: inset 3px 0 0 var(--sign); }
.cmp .cm { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; color: var(--mut); }
.cmp .cv { font-size: 21px; font-weight: 900; letter-spacing: -.02em; line-height: 1.15; }
.cmp .cs { font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  color: var(--mut); }

/* ── the timeline, shared with the sibling sites ──────── */
.timeline {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  margin-top: 11px; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 14px 9px; box-shadow: 0 6px 22px rgba(0, 0, 0, .07);
}
.tl-side { display: flex; flex-direction: column; gap: 5px; }
.tl-lab { font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--mut); }
.tl-transport { display: flex; align-items: center; gap: 5px; }
.tl-track { flex: 1 1 340px; min-width: 240px; display: flex; flex-direction: column; }
.tl-track input[type="range"] { width: 100%; margin: 0; accent-color: var(--sign); }
.tl-ticks { position: relative; height: 23px; margin: 3px 9px 0; pointer-events: none; }
.tl-ticks .tk { position: absolute; top: 0; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; }
.tl-ticks .tk.at-start { transform: translateX(-2px); align-items: flex-start; }
.tl-ticks .tk.at-end { transform: translateX(calc(-100% + 2px)); align-items: flex-end; }
.tl-ticks .tk i { width: 1px; height: 5px; background: var(--line); display: block; }
.tl-ticks .tk span { font: 700 8.5px var(--mono-font); color: var(--mut);
  white-space: nowrap; line-height: 1; margin-top: 3px; letter-spacing: .02em; }
.tl-ticks .tk.day i { height: 9px; width: 2px; background: var(--sign); }
.tl-ticks .tk.day span { color: var(--ink2); font-weight: 800; }
.tl-buffer { height: 2px; margin: 2px 9px 0; border-radius: 2px; background: var(--line2);
  overflow: hidden; transition: opacity .4s ease .3s; }
.tl-buffer::before { content: ""; display: block; height: 100%; width: var(--pct, 0%);
  background: var(--sign); transition: width .15s linear; }
.tl-buffer.is-full { opacity: 0; }
.tl-ends { display: flex; justify-content: space-between; gap: 10px;
  font: 700 9.5px var(--mono-font); color: var(--mut); letter-spacing: .02em; }
.tl-count { font: 900 13px var(--mono-font); color: var(--ink); }

/* The explorer fades in once the catalogs are in and the first frame is placed —
   without it the page shows a working map with no field on it for a beat, which reads
   as broken rather than as loading. */
.xp-stage, .xp-legend, .xp-compare, .timeline { transition: opacity .3s ease; }
body:not(.ready) .xp-legend, body:not(.ready) .xp-compare { opacity: .45; }

@media (max-width: 700px) {
  #map { height: 62vh; }
  .xp-hud { top: 8px; left: 8px; right: 8px; }
  .xp-stamp .sv { font-size: 14px; }
}

/* The map's own failure state. MapLibre needs WebGL2 and some machines do not have it;
   the rest of the page is still worth reading, so the frame says what happened instead
   of sitting black and empty. */
.xp-nomap {
  margin: 0; padding: 40px 30px; text-align: center; color: #b9c9d6;
  font-size: 14px; font-weight: 700; line-height: 1.6; max-width: 560px;
  margin-inline: auto;
}

/* ── the explorer's second tier of controls ───────────────
   Everything above the fold is the reading instrument — model, field, run, time. The
   rest is how the map *looks*, which matters and is not what anyone opens the page
   for, so it folds away behind one summary. Open it and it is all there; leave it shut
   and the map is bigger. */
.xp-more {
  margin-top: 9px; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: 0 6px 22px rgba(0, 0, 0, .07); overflow: hidden;
}
.xp-more > summary {
  cursor: pointer; padding: 10px 15px; font-family: var(--mono-font);
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink2); list-style: none; display: flex; align-items: center; gap: 8px;
}
.xp-more > summary::-webkit-details-marker { display: none; }
.xp-more > summary::before { content: "▸"; color: var(--sign); font-size: 13px; }
.xp-more[open] > summary::before { content: "▾"; }
.xp-more > summary:hover { color: var(--sign); }
.xp-bar3 { border: 0; border-top: 1px solid var(--line2); border-radius: 0;
  box-shadow: none; gap: 24px; }

.xp-inline { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.xp-inline select { max-width: 168px; }

/* A checkbox and its word, as one target. Used for the boundary overlays and the
   Smooth switch — both are on/off facts about the picture rather than settings, so
   they read as a list of things that are or are not drawn. */
.switch {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-family: var(--font); font-size: 12px; font-weight: 700; color: var(--ink2);
  letter-spacing: 0; text-transform: none;
}
.switch input { accent-color: var(--sign); margin: 0; cursor: pointer; }
.switch:hover { color: var(--ink); }
.switch input:disabled { cursor: not-allowed; }
.switch:has(input:disabled) { opacity: .45; cursor: not-allowed; }

.overlay-box {
  display: grid; gap: 3px 14px; grid-template-columns: repeat(2, minmax(120px, 1fr));
}

/* Sub-controls of the wind mode segment, styled as subordinate to it: indented under
   a rule, smaller labels, and absent outright when the mode has nothing for them to
   change — barbs have no seeding and no animation speed. */
.wind-opts {
  display: flex; flex-direction: column; gap: 5px; margin-top: 6px;
  padding-left: 9px; border-left: 2px solid var(--line2);
}
.wind-opt { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.wind-opt label { font-size: 9px; letter-spacing: .09em; }
.wind-opt select { padding: 3px 5px; font-size: 11px; font-weight: 700; min-width: 92px; }

/* The wind overlay is a canvas of its own above the map, because a streamline
   animation composites frame to frame and must not be cleared by MapLibre's redraw.
   It takes no pointer events, so the map still drags and the probe still reads
   through it. */
#wind-overlay { position: absolute; inset: 0; z-index: 4; pointer-events: none; }

/* MapLibre's attribution, re-dressed to the site. It carries OpenStreetMap and
   whichever imagery basemap is on, and both of those are conditions of use. */
.maplibregl-ctrl-attrib {
  background: rgba(10, 14, 20, .74) !important; color: #b9c9d6 !important;
  font-family: var(--mono-font) !important; font-size: 10px !important;
}
.maplibregl-ctrl-attrib a { color: #9fc4e0 !important; }

@media (max-width: 860px) {
  .overlay-box { grid-template-columns: 1fr; }
  .xp-bar3 { gap: 16px; }
}
