/* ==========================================================================
   newton-liu.com — the globe landing (index.html), on top of site.css.

   Only g-* classes, plus the three site pieces the landing reshapes
   (.masthead, .masthead-inner, .footer), always under
   body[data-page="globe"]. Colours, type and motion are site.css tokens,
   or, for what is drawn over the map, the --g-* colours just below.
   The bare numbers are geometry globe.js repeats (the 312px panel
   allowance; the free area's 64px top and 108px bottom): change one, check
   the other.

   "App" layout (≥1024 wide, ≥620 tall): nothing scrolls, the globe fills
   the window, the panel floats on the left. "Stacked" (anything smaller):
   the globe is a sticky stage and the list scrolls up beneath it.
   ========================================================================== */

body[data-page="globe"] { background: var(--space); --F: calc(var(--edge) + 312px); --stage-h: min(56vh, 560px); }
@supports (height: 1svh) { body[data-page="globe"] { --stage-h: min(56svh, 560px); } }
@media (max-height: 519px) { body[data-page="globe"] { --stage-h: 100vh; } }
@supports (height: 1svh) { @media (max-height: 519px) { body[data-page="globe"] { --stage-h: 100svh; } } }
/* Sideways in ?edit, the stage scrolls in below the edit bar, so it is that much shorter. */
@media (max-height: 519px) { body.is-editing[data-page="globe"] { --stage-h: calc(100vh - var(--nl-bar-h, 46px)); } }
@supports (height: 1svh) { @media (max-height: 519px) { body.is-editing[data-page="globe"] { --stage-h: calc(100svh - var(--nl-bar-h, 46px)); } } }

/* What is drawn over the map, on each ground: Black (the default) and White,
   a paper atlas (data-theme="light" on <html>). The map's own colours are
   PALETTE in globe.js, and the two must agree. Out at the globe, where both
   grounds show the same day and night, the pins take the inks under "Day
   and night" at the end of this file instead. */
body[data-page="globe"] {
  --g-ink:        #fff;                    /* full strength: a pin or row mark lit, the open row's title */
  --g-pin:        rgba(242,242,242,.85);   /* a pin's crosshair */
  --g-pin-seen:   rgba(242,242,242,.45);   /* ...once its collection has been opened */
  --g-pin-stack:  rgba(242,242,242,.6);    /* the circle round a stacked pin */
  --g-pin-intro:  rgba(255,255,255,.55);   /* the one ring each pin arrives with */
  --g-ring:       rgba(255,255,255,.1);    /* the globe's rim */
  --g-ring-glow:  rgba(255,255,255,.04);
  --g-wire:       rgba(255,255,255,.28);   /* pin to plate, pin to card */
  --g-card-bk:    rgba(255,255,255,.55);   /* the card's corner brackets */
  --g-mark:       #5a5a58;                 /* a row's crosshair */
  --g-row-wash:   rgba(255,255,255,.04);   /* a lit row */
  --g-veil:       5,5,5;                   /* --space as r,g,b: the header's fade over the map */
  --g-label-bg:   rgba(5,5,5,.7);          /* behind a place label */
  --g-attrib-bg:  rgba(5,5,5,.78);         /* behind the map credits */
  --g-dial-tick:  rgba(255,255,255,.16);   /* the dial: a tick every 10° */
  --g-dial-major: rgba(255,255,255,.32);   /* ...every 60°, under a number */
}
:root[data-theme="light"] body[data-page="globe"] {
  --g-ink:        #000;
  --g-pin:        rgba(27,28,32,.85);
  --g-pin-seen:   rgba(27,28,32,.6);       /* dark ink fades faster on paper: these keep Black's contrast */
  --g-pin-stack:  rgba(27,28,32,.6);
  --g-pin-intro:  rgba(27,28,32,.45);
  --g-ring:       rgba(0,0,0,.14);
  --g-ring-glow:  rgba(0,0,0,.06);
  --g-wire:       rgba(0,0,0,.3);
  --g-card-bk:    rgba(0,0,0,.45);
  --g-mark:       #96989c;
  --g-row-wash:   rgba(0,0,0,.035);
  --g-veil:       244,244,242;
  --g-label-bg:   rgba(244,244,242,.8);
  --g-attrib-bg:  rgba(244,244,242,.85);
  --g-dial-tick:  rgba(0,0,0,.18);
  --g-dial-major: rgba(0,0,0,.36);
}

/* The bar's 1px rule is kept (unseen) so the nav, the ground switch at its
   end included, sits exactly where it does on every other page. */
body[data-page="globe"] .masthead { position: static; background: var(--space); border-bottom-color: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
.g-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Shared: the mono labels, and the glass surfaces. */
.g-readout, .g-pin-label, .g-plate-where, .g-card-where, .g-card-date, .g-card-go, .g-list-title,
.g-index-link, .g-list-status, .g-fallback p, .g-load,
.g-stage .maplibregl-ctrl-attrib, .g-stage .maplibregl-cooperative-gesture-screen {
  margin: 0; font: 400 var(--t-label)/16px var(--mono); letter-spacing: .14em; text-transform: uppercase;
}
.g-card, .g-plate, .g-console {
  background-color: var(--panel); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border: 1px solid var(--hairline);
}

/* ---------- Stage -------------------------------------------------------
   --cx/--cy/--d: the overview globe's centre and diameter, as globe.js
   works them out, so the ring sits where the globe will land before any of
   the map has arrived. */

.g-stage {
  position: sticky; top: 0; z-index: 5; height: var(--stage-h); overflow: hidden; background: var(--space);
  --cx: 50%; --cy: calc(16px + (var(--stage-h) - 88px) / 2); --d: calc(.96 * min(100% - 32px, var(--stage-h) - 88px));
}
.g-stars, .g-map, .g-wire { position: absolute; inset: 0; width: 100%; height: 100%; }
.g-map { opacity: 0; transition: opacity .6s var(--ease); }
.g-stage.is-ready .g-map { opacity: 1; }
.g-ring {
  position: absolute; left: var(--cx); top: var(--cy); width: var(--d); aspect-ratio: 1; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none;
  box-shadow: 0 0 0 1px var(--g-ring), 0 0 120px var(--g-ring-glow);
}
.g-wire { z-index: 2; overflow: visible; pointer-events: none; }
.g-wire line { stroke: var(--g-wire); }
.g-wire rect { fill: var(--bracket); }
.g-wire :not(.is-on) { display: none; }

/* ---------- Pins: camera focus points -----------------------------------
   A crosshair (1px arms round a 4px gap, a 2px dot) in a 15px box, in a
   28px hit area. MapLibre owns the root's position and transform, so the
   drawing lives in children placed round --c, the hit area's centre.
   Active is autofocus acquisition: amber brackets close in, the dot turns
   amber, a slow ring pulses. Only the active pin pulses. */

.g-pin { width: 28px; height: 28px; cursor: pointer; --c: 13.5px; }
@media (pointer: coarse) { .g-pin { width: 44px; height: 44px; --c: 21.5px; } }
.g-pin i { position: absolute; display: block; pointer-events: none; }
.g-pin-in { inset: 0; transition: opacity var(--d-base) var(--ease); }
.g-pin-x {
  left: calc(var(--c) - 7.5px); top: calc(var(--c) - 7.5px); width: 15px; height: 15px;
  --k: var(--g-pin); --dot: var(--k); --a: 3.5px;
  background: linear-gradient(var(--k) 0 0) 7px calc(5.5px - var(--a)) / 1px var(--a),
    linear-gradient(var(--k) 0 0) 7px 9.5px / 1px var(--a), linear-gradient(var(--k) 0 0) calc(5.5px - var(--a)) 7px / var(--a) 1px,
    linear-gradient(var(--k) 0 0) 9.5px 7px / var(--a) 1px, linear-gradient(var(--dot) 0 0) 6.5px 6.5px / 2px 2px;
  background-repeat: no-repeat;
}
.g-pin.is-visited .g-pin-x { --k: var(--g-pin-seen); --dot: transparent; }
.g-pin:hover .g-pin-x, .g-pin.is-lit .g-pin-x, .g-pin.is-passing .g-pin-x, .g-pin.is-active .g-pin-x { --k: var(--g-ink); --a: 5px; }
.g-pin.is-active .g-pin-x { --dot: var(--accent); }
.g-pin.is-off { pointer-events: none; }
.g-pin.is-off .g-pin-in { opacity: 0; }
.g-pin.is-lit { z-index: 1; }
.g-pin.is-active { z-index: 2; }
.g-pin.is-hover { z-index: 3; }      /* the pin under the pointer stays on top of the siblings it reveals */
.maplibregl-marker.maplibregl-marker-covered { visibility: hidden; pointer-events: none; }
.g-pin.is-stack .g-pin-in::after {      /* several collections here: the crosshair in a circle */
  content: ""; position: absolute; left: calc(var(--c) - 7.5px); top: calc(var(--c) - 7.5px);
  width: 15px; height: 15px; border: 1px solid var(--g-pin-stack); border-radius: 50%;
}
.g-pin-ring {
  left: var(--c); top: var(--c); width: 9px; height: 9px; border: 1px solid var(--accent); border-radius: 50%;
  opacity: 0; transform: translate(-50%, -50%);
}
.g-pin.is-active .g-pin-ring { animation: g-pulse 4s .3s var(--ease-out) infinite; }
@keyframes g-pulse { 0% { width: 9px; height: 9px; opacity: .5; } 40%, 100% { width: 36px; height: 36px; opacity: 0; } }

/* Corner brackets, site.css's .bk drawing at pin scale (and the card's). */
.g-pin-af, .g-card::after {
  --l: 6px; --w: 1.5px; --bc: var(--accent);
  background: linear-gradient(var(--bc) 0 0) 0 0 / var(--l) var(--w), linear-gradient(var(--bc) 0 0) 0 0 / var(--w) var(--l),
    linear-gradient(var(--bc) 0 0) 100% 0 / var(--l) var(--w), linear-gradient(var(--bc) 0 0) 100% 0 / var(--w) var(--l),
    linear-gradient(var(--bc) 0 0) 0 100% / var(--l) var(--w), linear-gradient(var(--bc) 0 0) 0 100% / var(--w) var(--l),
    linear-gradient(var(--bc) 0 0) 100% 100% / var(--l) var(--w), linear-gradient(var(--bc) 0 0) 100% 100% / var(--w) var(--l);
  background-repeat: no-repeat;
}
.g-pin-af { left: calc(var(--c) - 10px); top: calc(var(--c) - 10px); width: 20px; height: 20px; opacity: 0; }
.g-pin.is-active .g-pin-af { opacity: 1; animation: g-af var(--d-base) var(--ease-out) both; }
@keyframes g-af { from { left: calc(var(--c) - 18px); top: calc(var(--c) - 18px); width: 36px; height: 36px; opacity: 0; } }

/* Intro: each pin scales in with one soft ring. */
.g-stage:not(.has-pins) .g-pin { visibility: hidden; }
.g-pin.is-intro .g-pin-in { animation-delay: inherit; }
.g-pin.is-intro .g-pin-x { animation: g-in var(--d-base) var(--ease-out) both; animation-delay: inherit; }
.g-pin.is-intro .g-pin-ring { border-color: var(--g-pin-intro); animation: g-pulse 1.8s var(--ease-out) forwards; animation-delay: inherit; }
@keyframes g-in { from { transform: scale(.6); opacity: 0; } }

.g-pin-label {
  left: calc(var(--c) + 16px); top: var(--c); transform: translateY(-50%); padding: 2px 6px; font-style: normal;
  white-space: nowrap; background: var(--g-label-bg); color: var(--text-dim);
  visibility: hidden; opacity: 0; transition: opacity var(--d-base) var(--ease);
}
.g-pin.has-label .g-pin-label { visibility: visible; opacity: 1; }
.g-pin.is-left .g-pin-label { left: auto; right: calc(100% - var(--c) + 16px); }
.g-pin.is-up .g-pin-label, .g-pin.is-down .g-pin-label { left: calc(var(--c) + var(--dx, 0px)); text-align: center; }
.g-pin.is-up .g-pin-label { top: calc(var(--c) - 12px); transform: translate(-50%, -100%); }
.g-pin.is-down .g-pin-label { top: calc(var(--c) + 12px); transform: translateX(-50%); }
/* A long name on two lines, where one line has no room (globe.js measureLabel). */
.g-pin.is-wrap .g-pin-label { white-space: normal; width: max-content; max-width: var(--wrap, 160px); }
.g-pin.is-wrap.is-left .g-pin-label { text-align: right; }

/* ---------- Plate: the hover preview (app layout, fine pointers) ------- */

.g-plate {
  position: absolute; left: 0; top: 0; z-index: 3; width: 250px; padding-bottom: 12px; pointer-events: none;
  opacity: 0; clip-path: inset(0 0 100% 0); transition: opacity var(--d-fast) var(--ease), clip-path 0s var(--d-fast);
}
.g-plate.is-live { pointer-events: auto; cursor: pointer; }   /* the passing card: click to fly there */
.g-plate.is-on { opacity: 1; clip-path: inset(0); transition: opacity .28s var(--ease-out), clip-path .28s var(--ease-out); }
.g-plate img { display: block; width: 100%; height: auto; background: var(--bg-raised); }
/* 250px wide, between the first 200 and a 300 that was too big (Newton,
   2026-10-16). */
.g-plate p { margin: 0; padding: 0 12px; }
.g-plate p:first-of-type { padding-top: 10px; }
.g-plate-title { font: 500 15px/20px var(--sans); color: var(--text); }
.g-plate-where { margin-top: 2px !important; font-size: 12px; letter-spacing: .12em; color: var(--text-faint); }
.g-plate.is-text { width: max-content; max-width: 290px; }      /* a stack: titles only, set apart */
.g-plate.is-text .g-plate-title + .g-plate-title { margin: 7px 12px 0; padding: 7px 0 0; border-top: 1px solid var(--hairline-soft); }

/* ---------- Card ---------------------------------------------------------
   Presentation only (aria-hidden, nothing focusable): the list is the
   accessible way to the same thing. The opener whole, never cropped. */

.g-card {
  position: absolute; z-index: 5; opacity: 0; visibility: hidden; transform: translateX(12px);
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility 0s .22s;
}
.g-card.is-open { opacity: 1; visibility: visible; transform: none; transition: opacity var(--d-slow) var(--ease-out), transform var(--d-slow) var(--ease-out); }
.g-card.is-leaving { transform: translateY(8px); }
.g-card.is-quick { transition-duration: .16s; }
.g-card::after { content: ""; position: absolute; inset: -1px; pointer-events: none; --l: var(--bk-len); --w: 1px; --bc: var(--g-card-bk); }
.g-card p { margin: 0; }
.g-card-media { display: block; background: var(--bg-raised); }
.g-card-media img { display: block; width: 100%; height: auto; object-fit: contain; opacity: 0; transition: opacity .4s var(--ease); }
.g-card-media img.is-loaded { opacity: 1; }
.g-card-title { font: 500 28px/1.1 var(--sans); letter-spacing: -.015em; color: var(--text); }
.g-card .g-card-where { margin-top: 10px; color: var(--text-dim); }
.g-card .g-card-date { margin-top: 4px; color: var(--text-faint); }
.g-card .g-card-sub { margin-top: 12px; font: 400 15px/1.5 var(--sans); color: var(--text-dim); }
.g-card-actions { display: flex; gap: 8px; margin-top: 20px; }
.g-card-go {
  flex: 1; display: flex; align-items: center; justify-content: space-between; height: 44px; padding: 0 16px;
  border: 1px solid var(--hairline-strong); color: var(--text); text-decoration: none; letter-spacing: .16em; white-space: nowrap;
}
.g-card-go::after { --bk-c: var(--accent); }
.g-card-go-arrow { transition: transform var(--d-fast) var(--ease); }
.g-card button {
  flex: none; width: 44px; height: 44px; padding: 0 0 3px; border: 1px solid var(--hairline-strong); background: none;
  color: var(--text-dim); font: 300 22px/1 var(--sans); cursor: pointer;
}
.g-card-go, .g-card button, .g-btn { transition: color var(--d-fast) var(--ease), background-color var(--d-fast) var(--ease); }
@media (hover: hover) {
  .g-card-go:hover, .g-card button:hover, .g-btn:hover { color: var(--text); background-color: var(--wash); }
  .g-card-go:hover .g-card-go-arrow { transform: translateX(4px); }
  .g-row:hover { background-color: var(--g-row-wash); }
  .g-row:hover .g-row-mark { --k: var(--g-ink); }
}
.g-card button.is-end { opacity: .3; pointer-events: none; }
.g-card.is-waiting .g-card-go { visibility: hidden; }      /* no gallery yet, and no photograph */
.g-card.is-waiting .g-card-media { display: none; }
.g-card-progress { position: absolute; left: 0; right: 0; bottom: -1px; z-index: 1; height: 1px; background: var(--accent); transform-origin: 0; transform: scaleX(0); opacity: 0; }
.g-card.is-touring .g-card-progress { opacity: 1; }
/* The travel journal (places.json `journal`; globe.js fillCard). A place
   with no gallery yet shows "Journal →" in the gallery's slot (.is-journal);
   a collection with both has it as a quieter line under the buttons. */
.g-card.is-waiting.is-journal .g-card-go { visibility: visible; display: flex; }
.g-card-journal {
  display: inline-flex; gap: 8px; margin-top: 14px; color: var(--text-dim); text-decoration: none;
  font: 400 var(--t-label)/16px var(--mono); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
  transition: color var(--d-fast) var(--ease);
}
.g-card-journal[hidden] { display: none; }
.g-card-journal-arrow { transition: transform var(--d-fast) var(--ease); }
@media (hover: hover) {
  .g-card-journal:hover { color: var(--text); }
  .g-card-journal:hover .g-card-journal-arrow { transform: translateX(4px); }
}
@media not all and (min-width: 1024px) and (min-height: 620px) { .g-card-journal { margin-top: 4px; } }

/* ---------- Console: tour · readout · overview -------------------------- */

.g-console { position: absolute; left: 16px; right: 16px; bottom: 12px; z-index: 4; display: flex; transition: opacity var(--d-base) var(--ease); }
.g-stage:not(.is-ready):not(.is-deferred):not(.is-failed) .g-console { opacity: 0; visibility: hidden; }   /* in with the globe, not before */
.g-btn { flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: none; color: var(--text-dim); cursor: pointer; }
.g-btn:focus-visible { outline-offset: -2px; }
.g-btn + .g-readout, .g-readout + .g-btn, .g-btn + .g-btn { border-left: 1px solid var(--hairline); }
.g-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.25; }
.g-btn .g-on, .g-btn[aria-pressed="true"] .g-off { display: none; }
.g-btn[aria-pressed="true"] .g-on { display: block; }
.g-tour[aria-pressed="true"] { color: var(--accent); }
.g-readout {
  flex: 1; min-width: 0; padding: 0 14px; line-height: 44px; text-align: center; font-variant-numeric: tabular-nums;
  color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.g-readout b { font-weight: inherit; color: var(--accent); }
body.is-editing .g-tour { display: none; }
body.is-editing .g-tour + .g-readout { border: 0; }

/* ---------- Failure and Save-Data -------------------------------------- */

.g-fallback { position: absolute; left: var(--cx); top: var(--cy); z-index: 3; width: max-content; max-width: 80%; transform: translate(-50%, -50%); text-align: center; }
.g-fallback p { margin-bottom: 12px; letter-spacing: 0; text-transform: none; color: var(--text-faint); }
.g-load { height: 44px; padding: 0 20px; border: 1px solid var(--hairline-strong); background: none; color: var(--text); letter-spacing: .16em; cursor: pointer; }
.g-stage.is-failed .g-console, .g-stage.is-failed .g-map, .g-stage.is-failed .g-card, .g-stage.is-deferred .g-fallback p { display: none; }
.g-stage.is-deferred .g-btn { visibility: hidden; }

/* ---------- Attribution: always shown, never collapsed -----------------
   On a backing of the space colour, so no map label or relief can print
   through it (over open space it doesn't show). */

.g-stage .maplibregl-ctrl-attrib {
  margin: 0 !important; padding: 2px 8px; letter-spacing: 0; text-transform: none; color: var(--text-faint);
  background: var(--g-attrib-bg); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.g-stage .maplibregl-ctrl-attrib a { color: inherit; text-decoration: none; white-space: nowrap; }
.g-stage .maplibregl-ctrl-attrib a:hover { color: var(--text-dim); text-decoration: underline; }
.g-stage .maplibregl-cooperative-gesture-screen { background: var(--panel); color: var(--text); }

/* ---------- Panel: the list ------------------------------------------- */

.g-list-head { display: flex; align-items: center; justify-content: space-between; }
.g-list-title { letter-spacing: .16em; color: var(--text-faint); }
.g-index-link { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--text-dim); text-decoration: none; transition: color var(--d-fast) var(--ease); }
.g-index-link:hover { color: var(--text); }
.g-list, .g-rows { list-style: none; margin: 0; padding: 0; }
.g-list.is-new li { animation: g-fade .16s var(--ease) both; }
@keyframes g-fade { from { opacity: 0; } }
.g-list-status { padding: 14px 20px; color: var(--text-faint); }

.g-row {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr); align-content: center;
  min-height: 44px; padding: 10px 16px 10px 36px; color: var(--text); text-decoration: none;
  transition: background-color var(--d-fast) var(--ease);
}
.g-row.is-lit { background-color: var(--g-row-wash); }
.g-row:focus-visible { outline-offset: -2px; }
.g-row-mark {     /* a small crosshair, mirroring the pin */
  position: absolute; left: 16px; top: calc(50% - 4.5px); width: 9px; height: 9px; --k: var(--g-mark); --dot: var(--k);
  background: linear-gradient(var(--k) 0 0) 4px 0 / 1px 3px, linear-gradient(var(--k) 0 0) 4px 6px / 1px 3px,
    linear-gradient(var(--k) 0 0) 0 4px / 3px 1px, linear-gradient(var(--k) 0 0) 6px 4px / 3px 1px,
    linear-gradient(var(--dot) 0 0) 4px 4px / 1px 1px;
  background-repeat: no-repeat;
}
.g-row.is-visited .g-row-mark { --dot: transparent; }
.g-row.is-lit .g-row-mark { --k: var(--g-ink); }
.g-row[aria-current="true"] { background-color: color-mix(in srgb, var(--accent) 8%, transparent); box-shadow: inset 2px 0 0 var(--accent); }
.g-row[aria-current="true"] .g-row-mark { --k: var(--accent); --dot: var(--accent); }
.g-row[aria-current="true"] .g-row-title { color: var(--g-ink); }
.g-row.is-recent { animation: g-recent 2.4s var(--ease) both; }
@keyframes g-recent { from { box-shadow: inset 2px 0 0 var(--accent); } to { box-shadow: inset 2px 0 0 transparent; } }
.g-row-title { font: 500 var(--t-row)/20px var(--sans); }
/* The note mark (globe.js noteMark): a collection with Newton's writing.
   Beside its name in the list; at the far right of its name on the plate
   and the card, over the local time. */
.g-note { display: inline-flex; flex: none; color: var(--text-faint); transition: color var(--d-base) var(--ease); }
.g-note svg { display: block; width: 13px; height: 13px; }
.g-row-title .g-note { margin-left: 9px; }
.g-row.is-lit .g-note, .g-row.is-passing .g-note, .g-row[aria-current="true"] .g-note { color: var(--text-dim); }
/* On a card the name and the mark share a line: the mark at its right end,
   sitting on the name's baseline, a hair lower to centre on the capitals. */
.g-plate-title, .g-card-title { display: flex; align-items: baseline; gap: 10px; }
.g-plate-title .g-note, .g-card-title .g-note { margin-left: auto; transform: translateY(1px); }
.g-card-title .g-note { transform: translateY(-3px); }
.g-card-title .g-note svg { width: 16px; height: 16px; }
.g-row[role="button"] { cursor: pointer; }      /* a place waiting for its photographs: flies there, no gallery */

/* A region: a mono caps heading with the stacked pin's mark (a crosshair in
   a ring: several collections here) and a hairline on to the panel's edge.
   It answers its rows: lit while one of them is pointed at, passing or open. */
.g-region-head {
  display: flex; align-items: center; gap: 9px; height: 32px; margin: 0; padding: 0 16px 0 14px;
  font: 400 var(--t-label)/16px var(--mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-faint); transition: color var(--d-fast) var(--ease);
}
.g-region-mark {
  flex: none; position: relative; width: 13px; height: 13px; box-sizing: border-box;
  border: 1px solid var(--k); border-radius: 50%; --k: var(--g-mark);
  transition: border-color var(--d-fast) var(--ease);
}
.g-region-mark::after {
  content: ""; position: absolute; left: 1px; top: 1px; width: 9px; height: 9px;
  background: linear-gradient(var(--k) 0 0) 4px 1px / 1px 2px, linear-gradient(var(--k) 0 0) 4px 6px / 1px 2px,
    linear-gradient(var(--k) 0 0) 1px 4px / 2px 1px, linear-gradient(var(--k) 0 0) 6px 4px / 2px 1px,
    linear-gradient(var(--k) 0 0) 4px 4px / 1px 1px;
  background-repeat: no-repeat;
}
.g-region-name { flex: none; }
.g-region-rule { flex: 1; height: 1px; margin-left: 3px; background: var(--hairline); }
.g-region:has(.g-row:hover, .g-row.is-lit, .g-row.is-passing, .g-row[aria-current="true"]) .g-region-head { color: var(--text-dim); }
.g-region:has(.g-row:hover, .g-row.is-lit, .g-row.is-passing, .g-row[aria-current="true"]) .g-region-mark { --k: var(--g-ink); }

/* The row of the collection whose passing card is up lights the way its pin
   does on the globe: the crosshair's arms reach out (in amber), the name goes
   to full ink, and an amber wire runs from the name out to the panel's edge,
   toward the globe, as the white wire runs from a pin to its card, with a
   faint amber light gathering there. Distinct from pointing at a row
   (.is-lit: white mark, grey wash) and from the open one (amber wash, bar). */
.g-row::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent 35%, color-mix(in srgb, var(--accent) 7%, transparent));
  transition: opacity .3s var(--ease);
}
.g-row-title { position: relative; display: flex; align-items: center; min-width: 0; transition: color var(--d-base) var(--ease); }
.g-row-title::after {                 /* the wire: always there, at no length */
  content: ""; flex: 1 1 0; min-width: 0; height: 4px; margin: 0 -16px 0 14px;
  background:
    linear-gradient(var(--accent) 0 0) 100% 50% / 4px 4px no-repeat,
    linear-gradient(90deg, color-mix(in srgb, var(--accent) 12%, transparent), var(--accent)) 0 50% / calc(100% - 4px) 1px no-repeat;
  transform: scaleX(0); transform-origin: 0 50%; opacity: 0;
  transition: transform .2s var(--ease), opacity .2s var(--ease);
}
.g-row.is-passing::before { opacity: 1; transition-duration: .6s; }
.g-row.is-passing .g-row-title { color: var(--g-ink); }
.g-row.is-passing .g-row-title::after { transform: none; opacity: 1; transition: transform .6s .08s var(--ease-out), opacity .2s var(--ease); }
.g-row.is-passing .g-row-mark {      /* the arms reach out, 3px to 5px, as a passing pin's do */
  --k: var(--accent); --dot: var(--accent);
  top: calc(50% - 6.5px); width: 13px; height: 13px; margin-left: -2px;
  background: linear-gradient(var(--k) 0 0) 6px 0 / 1px 5px, linear-gradient(var(--k) 0 0) 6px 8px / 1px 5px,
    linear-gradient(var(--k) 0 0) 0 6px / 5px 1px, linear-gradient(var(--k) 0 0) 8px 6px / 5px 1px,
    linear-gradient(var(--dot) 0 0) 6px 6px / 1px 1px;
  background-repeat: no-repeat;
}
@media (forced-colors: active) { .g-row::before { display: none; } }

/* ==========================================================================
   App layout: the globe fills the window, nothing scrolls
   ========================================================================== */

@media (min-width: 1024px) and (min-height: 620px) {
  body[data-page="globe"] { height: 100%; overflow: hidden; }
  body[data-page="globe"] .masthead { position: fixed; inset: 0 0 auto; z-index: var(--z-masthead); background: transparent; pointer-events: none; }
  body[data-page="globe"] .masthead a, body[data-page="globe"] .masthead button { pointer-events: auto; }
  body[data-page="globe"] .masthead-inner { min-height: 64px; }
  body.is-editing[data-page="globe"] .masthead { top: var(--nl-bar-h); }
  .g-stage {
    position: fixed; inset: 0; z-index: 0; height: auto;
    --cx: calc(var(--F) + (100% - var(--F) - var(--edge)) / 2); --cy: calc(64px + (100% - 172px) / 2);
    --d: calc(.8 * min(100% - var(--F) - var(--edge), 100vh - 172px));
  }
  .g-stage::after {      /* keeps the header legible over a map that has flown in close */
    content: ""; position: absolute; inset: 0 0 auto; z-index: 1; height: 128px; pointer-events: none;
    background: linear-gradient(rgba(var(--g-veil),.94), rgba(var(--g-veil),.88) 56px, rgba(var(--g-veil),0));
  }

  .g-panel {
    position: fixed; left: var(--edge); top: 80px; bottom: 24px; z-index: var(--z-panel); width: 288px;
    display: flex; flex-direction: column; padding-bottom: 52px;
    background-color: var(--panel); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border: 1px solid var(--hairline);
  }
  body.is-editing .g-panel { top: calc(80px + var(--nl-bar-h)); }
  .g-atlas { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .g-list-head { flex: none; padding: 0 16px 0 20px; }
  .g-index-link { min-height: 40px; }
  /* Tight rows, so every region reads at once; when the window is short
     enough to scroll, the region stays named at the top, on the panel's own
     glass laid over the ground (opaque, the panel's tone, so it only shows
     as a band once rows pass under it). */
  .g-row { min-height: 27px; padding-top: 3.5px; padding-bottom: 3.5px; }
  .g-region:first-child { padding-top: 6px; }
  .g-region + .g-region { margin-top: 6px; }
  .g-region-head { position: sticky; top: 0; z-index: 1; height: 30px; background: linear-gradient(var(--panel) 0 0), var(--space); }
  .g-list { padding: 0 0 8px; border-top: 1px solid var(--hairline-soft); scroll-padding: 30px 0 24px; }   /* a focused row clears the heading and the fade */
  .g-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--hairline-strong) transparent; }
  .g-list.is-overflowing { -webkit-mask-image: linear-gradient(var(--mask-solid) calc(100% - 24px), transparent); mask-image: linear-gradient(var(--mask-solid) calc(100% - 24px), transparent); }

  body[data-page="globe"] .footer {
    position: fixed; left: calc(var(--edge) + 1px); bottom: 25px; z-index: calc(var(--z-panel) + 1); width: 286px; min-height: 52px;
    display: flex; align-items: center; margin: 0; padding: 0 20px; border-top: 1px solid var(--hairline);
  }
  body[data-page="globe"] .footer .wrap { padding: 0; }
  body[data-page="globe"] .footer p { font: 400 var(--t-label)/16px var(--mono); text-wrap: balance; }
  body[data-page="globe"] .footer .footer-links { display: none; }

  .g-console { left: var(--cx); right: auto; bottom: 48px; width: clamp(420px, 40vw, 600px); transform: translateX(-50%); }
  /* One button left of the readout, two right of it: 44px more padding on
     the left centres its text on the console, and so on the globe's axis
     (88px when ?edit hides the Tour button). */
  .g-readout { padding-left: 58px; }
  body.is-editing .g-readout { padding-left: 102px; }
  .g-card { right: var(--edge); top: calc(50% - 14px); translate: 0 -50%; width: clamp(360px, 34vw, 520px); max-height: calc(100% - 188px); }
  .g-card-media img { max-height: calc(100vh - 384px); }
  .g-card-body { padding: 20px 24px 24px; }
  .g-stage .maplibregl-ctrl-bottom-right { right: var(--edge); bottom: 12px; }
}
@media (min-width: 1024px) and (min-height: 620px) and (pointer: coarse) { .g-index-link, .g-row { min-height: 44px; } }
@media (min-width: 1024px) and (max-width: 1235px) and (min-height: 620px) {   /* the card at its narrowest */
  .g-card-body { padding: 20px; }
  .g-card-go { padding: 0 12px; letter-spacing: .12em; }
}

/* ==========================================================================
   Stacked layout: a sticky stage over a scrolling list
   ========================================================================== */

@media not all and (min-width: 1024px) and (min-height: 620px) {
  .g-panel { padding: 0 var(--edge); background: var(--space); }
  .g-list { margin: 0 calc(-1 * var(--edge)); }
  .g-list-status { padding-inline: var(--edge); }
  .g-rows > li { border-top: 1px solid var(--hairline-soft); }
  .g-region-head { height: 44px; margin-top: 12px; padding: 0 var(--edge) 0 calc(var(--edge) - 2px); }
  .g-row { min-height: 56px; padding: 12px var(--edge) 12px calc(var(--edge) + 20px); }
  .g-row-mark { left: var(--edge); }
  .g-row-title::after { margin-right: calc(-1 * var(--edge)); }
  .g-card.is-waiting { cursor: auto; }
  .g-card.is-waiting .g-card-go { display: none; }
  #collections { scroll-margin-top: var(--stage-h); }
  body.is-editing .g-stage { scroll-margin-top: var(--nl-bar-h); }    /* scrolled into view below the ?edit bar */

  .g-plate { display: none; }
  /* The console makes way for the card, except during the tour (its Stop
     is there) and while one of its buttons has focus; then the card sits
     above it instead. */
  .g-stage.has-card:not(.is-touring) .g-console { opacity: 0; visibility: hidden; transition: opacity var(--d-fast) var(--ease), visibility 0s var(--d-fast); }
  .g-stage.has-card .g-console:focus-within { opacity: 1; visibility: visible; transition: none; }
  .g-stage.is-touring .g-card, .g-stage.has-card:has(.g-console:focus-within) .g-card { bottom: 64px; }

  /* The card leads with the photograph: whole, the card's full width, below
     it the title, date and the way in. Tapping it anywhere but × opens the
     gallery. */
  .g-card { left: 16px; right: 16px; bottom: 12px; max-width: 440px; margin: 0 auto; cursor: pointer; }
  .g-card-media img { max-height: max(96px, min(30svh, 210px, var(--stage-h) - 320px)); }   /* and leave the map a band to show the place in */
  .g-card-body { position: relative; padding: 10px 48px 12px 12px; }
  .g-card-title { font-size: 16px; line-height: 1.25; letter-spacing: -.005em; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .g-card .g-card-where, .g-card .g-card-sub, .g-card-prev, .g-card-next { display: none; }
  .g-card .g-card-date { margin-top: 2px; }
  .g-card-actions { margin-top: 6px; }
  .g-card-go { flex: none; gap: 8px; height: auto; padding: 0; border: 0; justify-content: flex-start; }
  .g-card-go::after { display: none; }
  .g-card .g-card-close { position: absolute; top: 0; right: 0; border: 0; }
  /* Its title is clamped to two lines, so the note mark is set at the end
     of the title's line, left of the close button, the title kept clear. */
  .g-card-title .g-note { position: absolute; right: 46px; top: 14px; margin: 0; transform: none; }
  .g-card-title .g-note svg { width: 13px; height: 13px; }
  .g-card.is-written .g-card-body { padding-right: 68px; }

  /* Two lines at most, in the sans so they fit, each credit kept whole. */
  .g-stage .maplibregl-ctrl-top-right { right: 16px; top: 8px; max-width: 72%; text-align: right; }
  .g-stage .maplibregl-ctrl-attrib { font-family: var(--sans); }

  /* The rows and footer links scroll up under the sticky globe: a row that
     takes focus stops just below it, never behind it. */
  @media (min-height: 520px) {
    body.is-editing .g-stage { top: var(--nl-bar-h); }
    .g-row, .g-index-link, .g-list-title, body[data-page="globe"] .footer a { scroll-margin-top: calc(var(--stage-h) + 8px); }
    body.is-editing .g-row, body.is-editing .g-index-link, body.is-editing .g-list-title,
    body.is-editing[data-page="globe"] .footer a { scroll-margin-top: calc(var(--stage-h) + var(--nl-bar-h) + 8px); }
    body.is-editing #collections { scroll-margin-top: calc(var(--stage-h) + var(--nl-bar-h)); }
  }
}
/* A phone held sideways: the stage is the whole screen and doesn't stick,
   and the card goes back to a photograph beside its title. */
@media (max-height: 519px) {
  .g-stage { position: relative; }
  .g-card { display: grid; grid-template-columns: 168px minmax(0, 1fr); align-items: center; max-width: 520px; }
  .g-card.is-waiting { grid-template-columns: minmax(0, 1fr); }
  .g-card-media { height: 112px; }
  .g-card-media img { height: 100%; max-height: none; }
}

/* Reduced motion: final states, and a short fade for the card. */
@media (prefers-reduced-motion: reduce) {
  body[data-page="globe"] .g-card { transform: none !important; transition: opacity .15s !important, visibility 0s .15s !important; }
  body[data-page="globe"] .g-card.is-open { transition: opacity .15s !important; }
  .g-pin * { animation: none !important; }
}
@media (forced-colors: active) { .g-pin-x, .g-pin-af, .g-row-mark { forced-color-adjust: none; } }

/* ==========================================================================
   The dial: the ring round the globe as an instrument's bezel (globe.js,
   "THE DIAL"). Laptop layout only; it comes in with the pins. Ticks and
   numbers outside the rim, a dot per collection on it, an index at
   12 o'clock. Amber only for the collection passing.
   ========================================================================== */

.g-dial { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; overflow: visible; pointer-events: none; opacity: 0; transition: opacity .8s var(--ease); }
.g-stage.has-pins .g-dial { opacity: 1; }
.g-dial-tick { fill: none; stroke: var(--g-dial-tick); }
.g-dial-tick.is-major { stroke: var(--g-dial-major); }
.g-dial-num { fill: var(--text-faint); font: 400 var(--t-label) var(--mono); letter-spacing: .14em; text-transform: uppercase; font-variant-numeric: tabular-nums; transition: opacity var(--d-slow) var(--ease); }
.g-dial-num.is-gone { opacity: 0; }       /* round the far side, or stepping aside for the plate, the panel, the masthead */
/* A collection's square, 4px, shown at half that, the row marks' grey; it
   grows back when it is the one: full ink pointed at or open, amber passing. */
.g-dial-dot { fill: var(--g-mark); transform-box: fill-box; transform-origin: center; transform: scale(.5); transition: fill var(--d-base) var(--ease), transform var(--d-base) var(--ease-out); }
.g-dial-mark.is-lit .g-dial-dot { fill: var(--g-ink); transform: none; }
.g-dial-mark.is-passing .g-dial-dot { fill: var(--accent); transform: none; }
.g-dial-index { fill: none; stroke: var(--text-dim); }
@media not all and (min-width: 1024px) and (min-height: 620px) { .g-dial { display: none; } }
@media (forced-colors: active) { .g-dial { display: none; } }

/* ==========================================================================
   The local time (globe.js, "the local time"): one per collection, in its
   place's zone, on the plate and the card.
   ========================================================================== */

/* The plate: the time floats right after the place, so it closes its last
   line (or has one of its own when that line is full). */
.g-plate .g-plate-where { display: flow-root; }
.g-plate .g-plate-time { float: right; margin-left: 10px; font-variant-numeric: tabular-nums; }
/* The card: the place on the left, the time on the right. On a phone the
   place is hidden, and the time sits at the card's bottom right, level
   with the way in. */
.g-card-foot { display: flex; align-items: flex-end; gap: 16px; margin-top: 10px; }
.g-card-foot[hidden] { display: none; }   /* no place and no time */
.g-card .g-card-foot .g-card-where { margin-top: 0; flex: 1 1 auto; min-width: 0; }
.g-card .g-card-time {
  margin: 0 0 0 auto; flex: none; color: var(--text-dim);
  font: 400 var(--t-label)/16px var(--mono); letter-spacing: .12em; font-variant-numeric: tabular-nums;
}
@media not all and (min-width: 1024px) and (min-height: 620px) {
  .g-card-foot { position: absolute; right: 12px; bottom: 12px; margin: 0; }
}

/* ==========================================================================
   Day and night (globe.js, "THE SKY"). Out at the globe (globe.js adds
   .is-paper-globe while the sky is on) the globe is the same on both
   grounds: the Black map by night, paper on a slate sea by day. Each pin
   takes the ink of the ground under it (.is-sunlit, from the sun's height
   at the pin and how much of the ground round it is land): light on the
   night and the slate, as on Black, and the paper's own ink on the paper,
   as on White. Written out here, not taken from the two blocks at the
   top, because a pin once seen differs: a touch stronger on the night
   (.5 against Black's .45), a touch fainter on the paper (.55 against
   White's .6), as approved.
   ========================================================================== */

.g-stage.is-paper-globe .g-pin {
  --g-ink: #fff; --g-pin: rgba(242,242,242,.85); --g-pin-seen: rgba(242,242,242,.5);
  --g-pin-stack: rgba(242,242,242,.6); --g-pin-intro: rgba(255,255,255,.55);
}
.g-stage.is-paper-globe .g-pin.is-sunlit {
  --g-ink: #000; --g-pin: rgba(27,28,32,.85); --g-pin-seen: rgba(27,28,32,.55);
  --g-pin-stack: rgba(27,28,32,.6); --g-pin-intro: rgba(27,28,32,.45);
}
/* The wire from a pin to its plate starts on the globe, night or paper,
   and ends on the page, black or white: one grey reads on all four (as
   Black's on the black, a graphite line on the paper). */
.g-stage.is-paper-globe { --g-wire: rgba(140,140,140,.56); }
