html, body { margin: 0; padding: 0; background: #05070c; color: #dbe6f2; color-scheme: dark; text-wrap: pretty; -webkit-font-smoothing: antialiased; }
* { box-sizing: border-box; }
a { color: #a8f2ff; text-decoration: none; }
a:hover { color: #5ee7ff; }
img, svg { max-width: 100%; }

/* ── The container-query shell ─────────────────────────────────────────────────────────
   A container cannot query itself, so 'container-type' sits here and the grid sits on the
   <article> inside. In the design prototype this was a harness div; here it is the page. */
body { container-type: inline-size; container-name: page; }
/* The family is part of this rule, not the reset: the design carries it on the <article>
   alongside the tabular-nums and the line-height, and dropping it silently fell the whole
   document back to the UA serif — every metric below is authored against system-ui. */
article { width: 100%; max-width: 1180px; margin: 0 auto; font-family: system-ui, -apple-system, 'Segoe UI', sans-serif; font-variant-numeric: tabular-nums; line-height: 1.5; }

[data-pad] { padding-inline: 18px; }
[data-cta] { margin-inline: 18px; }
[data-h1] { font-size: 29px; line-height: 1.15; letter-spacing: -.015em; margin: 0; color: #eaf6ff; font-weight: 600; }
[data-hero] { font-size: 56px; font-weight: 700; letter-spacing: -.035em; color: #ffb45c; line-height: 1; }
[data-tech] { grid-template-columns: 1fr 1fr; }
[data-split] { display: block; }
[data-sec] { padding-block: 26px 0; }
[data-h2] { font-size: 20px; font-weight: 600; color: #eaf6ff; margin: 0; }
/* '.row' is the same row without a link: a city's table lists eclipses it has no page for,
   and those used to be anchors back to the page they were already on. */
[data-list] a, [data-list] .row { display: flex; align-items: center; gap: 14px; padding-block: 12px; }
/* The value is pushed to the end of the row by '.spacer', which is right in a narrow column
   and wrong in a wide one: at 550px the date and its duration end up a quarter of the screen
   apart with nothing between them. Capping the row keeps the pair readable as a pair. */
[data-list] a, [data-list] .row { max-width: 30rem; }
/* The verdict's own block sits below the container queries, with the rest of the vocabulary.
   Everything in it is a property no tier changes — except the gap, which the 620 tier widens
   to 28px and which a later rule of equal specificity would therefore silently win back. So
   the phone value lives up here, in front of the queries, where the cascade means what it
   looks like it means. The rest of that rule can stay where it reads best. */
[data-verdict] { gap: 18px; }
[data-rail] { display: contents; }
[data-scroll] { overflow-x: auto; overscroll-behavior-inline: contain; }
[data-scroll]::-webkit-scrollbar { height: 6px; }
[data-scroll]::-webkit-scrollbar-thumb { background: rgba(94,231,255,.22); }

@container page (min-width: 620px) {
  [data-verdict] { grid-template-columns: 132px 1fr; gap: 28px; align-items: center; }
  [data-hero] { font-size: 72px; }
  [data-split] { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: start; }
  [data-pad] { padding-inline: 32px; }
  [data-cta] { margin-inline: 32px; }
  [data-h1] { font-size: 38px; }
  [data-tech] { grid-template-columns: repeat(4, 1fr); }
  [data-sec] { padding-block: 40px 0; }
  [data-h2] { font-size: 25px; }
  [data-pad] > p { max-width: 66ch; }
  [data-hz] { max-width: 560px; }
  [data-list] { display: grid; grid-template-columns: 1fr 1fr; column-gap: 40px; }
  [data-list] a, [data-list] .row { padding-block: 14px; }
}

@container page (min-width: 940px) {
  [data-layout="rail"] {
    display: grid; align-items: start;
    grid-template-columns: minmax(0,1fr) 384px;
    grid-template-areas: "head head" "nav nav" "title title" "verdict verdict" "a rail" "b rail" "c rail" "d rail" "e rail" "f rail" "foot foot";
  }
  [data-area="head"] { grid-area: head; } [data-area="nav"] { grid-area: nav; }
  [data-area="title"] { grid-area: title; } [data-area="verdict"] { grid-area: verdict; }
  [data-area="a"] { grid-area: a; } [data-area="b"] { grid-area: b; } [data-area="c"] { grid-area: c; }
  [data-area="d"] { grid-area: d; } [data-area="e"] { grid-area: e; } [data-area="f"] { grid-area: f; }
  [data-area="foot"] { grid-area: foot; }
  /* Without this, grid items refuse to shrink and overflow the 384px rail. */
  [data-area], [data-rail] { min-width: 0; }
  [data-rail] {
    display: flex; flex-direction: column; grid-area: rail; align-self: stretch;
    padding: 40px 32px 0; margin-block-end: 26px;
    border-inline-start: 1px solid rgba(94,231,255,.14);
  }
  [data-rail] [data-pad] { padding-inline: 0; }
  [data-rail] [data-sec] { padding-block: 0 0; }
  [data-rail] [data-cta] { margin-inline: 0; margin-block-start: 22px; }
  [data-rail] [data-split] { display: block; }
  [data-rail] [data-tech] { grid-template-columns: 1fr 1fr; }
  [data-rail] [data-h2] { font-size: 20px; }
  [data-rail] > div:last-child { margin-block-start: 22px; }
  /* The handoff's 160px, restored. It was briefly 'auto' on the grounds that a fixed column
     left 48px of slack between the 112px disc and the number — but an 'auto' track *stretches*
     to eat the free space when justify-content is normal, and there is 376px of it at 1180px.
     So the column grew to 488px and the hero number sat a third of the page from the figure it
     belongs to, which is the fault the slack was meant to avoid, an order of magnitude worse.
     If the 48px is ever revisited, 'max-content' is the shrink-to-fit that does not stretch. */
  [data-verdict] { grid-template-columns: 160px minmax(0,600px); }
  /* The front page only: the track rides in the band's third column, which was empty at
     this width. The deep page's verdict keeps the handoff's two, so the two page types
     are not quietly sharing a layout that only one of them was designed for. */
  [data-verdict="wide"] { grid-template-columns: auto minmax(0,440px) minmax(0,1fr); align-items: center; column-gap: 36px; }
  [data-verdict="wide"] .strip { margin: 0; }
  /* The figure is the widest thing in the band and was carrying the band's whole height;
     capping it lets the three columns settle against each other instead. */
  [data-verdict="wide"] figure { margin: 0; align-self: center; }
  [data-list] { column-gap: 56px; }
  [data-h1] { font-size: 44px; }
  [data-hero] { font-size: 80px; }
}

/* ── Chrome ───────────────────────────────────────────────────────────────────────────── */
.top { display: flex; align-items: center; gap: 9px; padding-block: 11px; border-block-end: 1px solid rgba(94,231,255,.14); }
.mark { position: relative; width: 20px; height: 20px; flex: none; }
.mark i { position: absolute; border-radius: 50%; border: 1.5px solid; }
.mark i:first-child { inset-inline-start: 0; top: 1px; width: 16px; height: 16px; border-color: #ffb45c; }
.mark i:last-child { inset-inline-start: 4px; top: 3px; width: 14px; height: 14px; border-color: #5ee7ff; background: #05070c; }
.brand { font-size: 15px; font-weight: 700; color: #eaf6ff; }
.brand span { color: #5ee7ff; }
.spacer { flex: 1; min-width: 0; }

/* The Explore link's mark: four corner brackets and an amber dot. Built from
   'border-top' plus 'border-inline-*' rather than 'border-left'/'right' so the
   bracket turns with the page in Arabic instead of pointing the wrong way. */
.explore { display: flex; align-items: center; gap: 6px; font-size: 13px; color: #a8f2ff; white-space: nowrap; }
.frame { position: relative; width: 15px; height: 13px; flex: none; }
.frame i { position: absolute; width: 4px; height: 4px; }
.frame i:nth-child(1) { inset-inline-start: 0; top: 0; border-top: 1px solid rgba(94,231,255,.55); border-inline-start: 1px solid rgba(94,231,255,.55); }
.frame i:nth-child(2) { inset-inline-end: 0; top: 0; border-top: 1px solid rgba(94,231,255,.55); border-inline-end: 1px solid rgba(94,231,255,.55); }
.frame i:nth-child(3) { inset-inline-start: 0; bottom: 0; border-bottom: 1px solid rgba(94,231,255,.55); border-inline-start: 1px solid rgba(94,231,255,.55); }
.frame i:nth-child(4) { inset-inline-end: 0; bottom: 0; border-bottom: 1px solid rgba(94,231,255,.55); border-inline-end: 1px solid rgba(94,231,255,.55); }
.frame i:nth-child(5) { inset-inline-start: 6px; top: 5px; width: 3px; height: 3px; border-radius: 50%; background: #ffb45c; }

/* The language dropdown. <details> is an element, not a widget: it opens with
   zero script, keeps eight real <a href> in the markup for the crawler, and
   still works with scripting off. Everything directional is logical so the
   panel hangs off the correct edge in Arabic. */
.lang { position: relative; flex: none; }
.lang > summary { font-size: 11px; letter-spacing: .14em; color: #8fa3b8; white-space: nowrap; cursor: pointer; list-style: none; }
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary:hover { color: #a8f2ff; }
.lang[open] > summary { color: #a8f2ff; }
.lang > div {
  position: absolute; inset-inline-end: 0; top: calc(100% + 7px); z-index: 20;
  display: flex; flex-direction: column; min-width: 132px; padding: 5px 0;
  background: #0b1220; border: 1px solid rgba(94,231,255,.24); border-radius: 2px;
}
.lang > div a { padding: 6px 12px; font-size: 12px; color: #dbe6f2; letter-spacing: normal; }
.lang > div a:hover { background: rgba(94,231,255,.09); color: #5ee7ff; }
.lang > div a[aria-current] { color: #a8f2ff; }

.rule { width: 1px; height: 16px; background: rgba(94,231,255,.18); flex: none; }
.crumb { padding-block: 9px; border-block-end: 1px solid rgba(94,231,255,.14); font-size: 11px; letter-spacing: .1em; color: #6f8296; white-space: nowrap; }
.crumb a { color: #6f8296; }
.foot { padding-block: 18px 26px; margin-block-start: 26px; border-block-start: 1px solid rgba(94,231,255,.14); font-size: 10.5px; letter-spacing: .1em; color: #6f8296; }

/* ── The vocabulary the pages are written in ───────────────────────────────────────────
   These are the declarations the prototype repeats inline. Ported inline they would be
   ~17KB per page and ~135MB across the corpus; as classes they are a few hundred bytes,
   once. Only style that *encodes a page's data* — a wedge apex, a bar width, the Sun's
   position on the horizon — stays inline. */
/* The kicker and the sub-line live *inside* the <h1> on every item page, so both carry the
   four properties they used to inherit from <article> and would otherwise inherit from the
   heading: display, line-height, weight and tracking. They were <p> siblings until the
   heading was found to be saying almost nothing — "London, United Kingdom", identical on all
   fifteen of that city's pages and on the city index above them, with the eclipse and the
   date sitting just outside it in these two lines. Folding them in makes one heading that
   names the page; the four declarations are what keep it looking exactly as it did. */
.kick, .sub { display: block; line-height: 1.5; }
.kick { font-size: 11px; font-weight: 700; letter-spacing: .2em; color: #ffb45c; margin: 0 0 10px; }
.kick.off { color: #8fa3b8; }
.sub { font-size: 14px; font-weight: 400; letter-spacing: normal; color: #8fa3b8; margin: 10px 0 0; }
.eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .2em; color: #8fa3b8; margin: 0 0 8px; }
/* The rail's REFERENCE FIGURES label, which is quieter than a section eyebrow and carries the
   hairline separating the numbers from the CTA above them. Not '.rule' — that is already the
   header's 1px vertical divider, and the collision sized this label to a single pixel. */
.eyebrow.ruled { font-size: 10px; color: #6f8296; margin: 0; padding-block-end: 8px; border-block-end: 1px solid rgba(94,231,255,.14); }
.lbl { font-size: 9.5px; letter-spacing: .14em; color: #6f8296; }
.cap { font-size: 11.5px; color: #6f8296; margin: 10px 0 0; }
.ans { margin: 8px 0 0; font-size: 15px; color: #dbe6f2; }
.val { margin: 7px 0 0; font-weight: 600; color: #eaf6ff; }
.gloss { display: block; font-size: 12px; color: #8fa3b8; }
.strong { display: block; font-size: 15px; color: #eaf6ff; }
.hero-label { font-size: 11px; font-weight: 700; letter-spacing: .2em; color: #ffb45c; margin: 6px 0 0; }
.hero-unit { font-size: .5em; }
.say { font-size: 16px; line-height: 1.55; color: #eaf6ff; margin: 0; }
.note { border: 1px solid rgba(94,231,255,.14); background: rgba(12,23,38,.6); padding: 12px 14px; font-size: 13.5px; color: #dbe6f2; }
.note h3 { font-size: 11px; font-weight: 700; letter-spacing: .18em; color: #a8f2ff; margin: 0 0 6px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 0; }
.chip { font-size: 11px; letter-spacing: .1em; color: #a8f2ff; border: 1px solid rgba(94,231,255,.26); padding: 4px 8px; }
.safety { font-size: 13.5px; color: #a8f2ff; display: inline-flex; align-items: center; gap: 8px; margin-block-start: 14px; }
.safety i { width: 13px; height: 13px; border-radius: 50%; border: 1px solid rgba(94,231,255,.5); flex: none; }

/* When the filter comes off. 'min-width' rather than the design's flat 96px: the label is a
   translated string, and FILTER ON is the shortest of the eight — a fixed track would have the
   Arabic and Japanese spill over the time beside them. */
.filters { margin-block-start: 16px; }
.filters div { display: flex; align-items: baseline; gap: 12px; padding-block: 11px; border-block-start: 1px solid rgba(94,231,255,.07); }
.filters b { flex: none; min-width: 96px; font-size: 11px; font-weight: 700; letter-spacing: .14em; color: #ffb45c; }
.filters b.off { color: #5ee7ff; }
.filters span { flex: 1; font-size: 14px; color: #dbe6f2; }

/* ── The verdict ──────────────────────────────────────────────────────────────────────── */
[data-verdict] {
  display: grid; padding-block: 22px 24px; margin-block-start: 20px;
  border-block: 1px solid rgba(94,231,255,.26);
  background: linear-gradient(rgba(12,23,38,.55), rgba(5,7,12,0));
}

/* ── Tables ───────────────────────────────────────────────────────────────────────────── */
table { width: 100%; min-width: 328px; border-collapse: collapse; text-align: start; }
thead th { font-size: 10px; font-weight: 700; letter-spacing: .16em; color: #8fa3b8; text-align: start; padding-block-end: 8px; border-block-end: 1px solid rgba(94,231,255,.26); }
tbody tr { border-block-end: 1px solid rgba(94,231,255,.07); }
tbody td { padding: 11px 10px 11px 0; font-size: 14px; color: #eaf6ff; vertical-align: top; }
td.t { text-align: end; font-size: 17px; white-space: nowrap; padding-inline-end: 0; }
td.s { text-align: end; padding-inline-start: 14px; font-size: 13px; color: #8fa3b8; white-space: nowrap; }
/* Totality: the rows a reader is looking for. */
tr.tot { background: rgba(255,180,92,.07); }
tr.tot td { color: #ffb45c; }
tr.tot td:first-child { border-inline-start: 2px solid #ffb45c; padding-inline-start: 8px; }

/* ── Below the horizon ────────────────────────────────────────────────────────────────
   Never a negative altitude. The horizon becomes a drawn object: rows that happen after it
   are hatched and demoted, and a divider says where the line falls. */
.hatch, tr.under, table.under { background: repeating-linear-gradient(135deg, rgba(12,23,38,.5) 0 6px, rgba(5,7,12,.5) 6px 12px); }
tr.under td { color: #8fa3b8; }
tr.under .gloss { color: #6f8296; }
.under-lbl { font-size: 11px; font-weight: 700; letter-spacing: .1em; color: #8fa3b8; }
.under-dep { font-size: 11px; color: #6f8296; }
tr.divider { border-block-end: 1px solid rgba(94,231,255,.26); }
tr.divider td { padding: 9px 0; }
.divider-row { display: flex; align-items: center; gap: 10px; }
.divider-row b { font-size: 10px; font-weight: 700; letter-spacing: .18em; color: #a8f2ff; white-space: nowrap; }
.divider-row i { flex: 1; border-block-start: 1px solid rgba(94,231,255,.45); }
.divider-row span { font-size: 10px; letter-spacing: .14em; color: #6f8296; white-space: nowrap; }

/* ── Figures ──────────────────────────────────────────────────────────────────────────
   Drawn server-side as SVG. They carry dir="ltr" and must never mirror — east is east. */
figure { margin: 16px 0 0; }
.disc { position: relative; width: 112px; height: 112px; overflow: hidden; flex: none; }
/* The wedge spans its container, because the start/MAX/end row beneath it does: drawn at its
   intrinsic 328px it ended two fifths of the way along a label row that ran the full width,
   and the max marker no longer sat over the maximum. 'min-width' matches the table it scrolls
   with, so the two stay the same width inside [data-scroll] on a phone. */
.wedge { display: block; width: 100%; min-width: 328px; height: 56px; }
[data-hz] { margin-block-start: 16px; border: 1px solid rgba(94,231,255,.14); background: linear-gradient(rgba(12,23,38,.5), rgba(5,7,12,.9)); }
.globe { display: block; width: 100%; height: auto; border: 1px solid rgba(94,231,255,.14); background: #070c14; }
.strip { display: block; width: 100%; height: auto; border: 1px solid rgba(94,231,255,.14); background: #070c14; }

/* ── Reference figures and lists ──────────────────────────────────────────────────────── */
[data-tech] { display: grid; gap: 14px 18px; margin: 14px 0 0; }
[data-tech] dt { font-size: 9.5px; letter-spacing: .14em; color: #6f8296; }
[data-tech] dd { margin: 2px 0 0; font-size: 14px; color: #eaf6ff; }
[data-tech] dd.quiet { color: #8fa3b8; }
[data-list] { list-style: none; margin: 8px 0 0; padding: 0; }
[data-list] li { border-block-end: 1px solid rgba(94,231,255,.07); }
.pct { width: 92px; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.bar { display: block; width: 100%; height: 3px; background: rgba(94,231,255,.12); }
.bar i { display: block; height: 100%; background: #ffb45c; }
.cta { display: block; border: 1px solid rgba(94,231,255,.26); padding: 12px 14px; }
.cta b { display: block; font-size: 14px; color: #a8f2ff; font-weight: 600; }
.cta span { display: block; font-size: 12px; color: #8fa3b8; margin-block-start: 3px; }
.dl { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 18px; margin: 12px 0 0; }
.dl dt { font-size: 9.5px; letter-spacing: .14em; color: #6f8296; }
.dl dd { margin: 2px 0 0; font-size: 15px; color: #eaf6ff; }

/* The location form. A plain GET, because no script runs here — the Worker reads the query
   and redirects. See FIND_URL in apps/web/worker/index.js. */
/* Available to a screen reader, absent to everyone else. */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.find { margin: 12px 0 0; }
.find span { display: flex; gap: 8px; margin-block-start: 8px; }
.find input { flex: 1; min-width: 0; padding: 10px 12px; background: #0b1220; color: #dbe6f2; border: 1px solid rgba(94,231,255,.24); border-radius: 2px; font: inherit; font-size: 14px; }
.find input:focus-visible { outline: 1px solid #5ee7ff; outline-offset: 1px; }
.find button { flex: none; padding: 10px 16px; background: #5ee7ff; color: #05070c; border: 0; border-radius: 2px; font: inherit; font-size: 13px; font-weight: 600; letter-spacing: .06em; cursor: pointer; }

/* ── Prose the authored reference pages need ──────────────────────────────────────────── */
p { margin: 0 0 14px; color: #dbe6f2; }
h3 { font-size: 14px; margin: 26px 0 8px; color: #dbe6f2; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92em; color: #a8f2ff; }
main ul:not([data-list]):not(.cols), main ol { margin: 0 0 14px; padding-inline-start: 22px; color: #dbe6f2; }
main li { margin: 0 0 6px; }
.muted { color: #8fa3b8; font-size: 13px; }
.lede { font-size: 17px; color: #dbe6f2; }
ul.cols { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 2px 16px; }
ul.cols li { padding: 3px 0; font-size: 14px; }
/* The cities index groups its 411 rows under their country. The heading is a link to that
   country's page, which is most of what stops those pages having one inbound link each. */
h2.group { font-size: 13px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #8fa3b8; margin: 22px 0 8px; }
h2.group:first-of-type { margin-block-start: 8px; }
/* A glossary link on a label row. Quieter than a body link on purpose: eleven cyan words down
   the side of a page of numbers would be the loudest thing on it. */
.term { color: inherit; border-block-end: 1px dotted rgba(94,231,255,.35); }
.term:hover { color: #a8f2ff; border-block-end-color: #5ee7ff; }
ul.terms { list-style: none; padding: 0; margin: 0; }
ul.terms li { padding: 7px 0; font-size: 15px; border-block-end: 1px solid rgba(94,231,255,.07); }
ul.terms .muted { font-size: 14px; }
input.filter { width: 100%; max-width: 26rem; margin: 6px 0 8px; padding: 10px 12px; background: #0b1220; color: #dbe6f2; border: 1px solid rgba(94,231,255,.18); border-radius: 2px; font: inherit; font-size: 15px; }
input.filter:focus-visible { outline: 1px solid #5ee7ff; outline-offset: 1px; }
[data-letter] > h2 { margin: 26px 0 4px; }

/* ── The field card ───────────────────────────────────────────────────────────────────
   People stand in a desert with no signal. What prints is the identity of the page and the
   numbers: city, date, verdict, contact table, bearing. Everything else goes. */
@media print {
  body { background: #fff !important; container-type: normal; }
  article { display: block !important; max-width: none !important; background: #fff !important; color: #000 !important; }
  article * { color: #000 !important; background: transparent !important; border-color: #bbb !important; }
  [data-area="nav"], [data-rail], [data-area="c"], [data-area="d"], [data-area="e"], [data-area="f"],
  [data-cta], article footer, [data-verdict] > div:first-child, [data-hz], [data-print-drop] { display: none !important; }
  article header a { display: none !important; }
  [data-verdict] { border-block-end: 2px solid #000 !important; }
  article a { text-decoration: none !important; }
  [data-hero] { font-size: 34px !important; }
  [data-h1] { font-size: 24px !important; }
  [data-h2] { font-size: 16px !important; }
}