/* Charted Voyages — visual language ported from the JourneyAtlas.dc.html design.
   Colour, type and spacing values are carried over unchanged; only the delivery
   mechanism differs (classes instead of inline style attributes). */

:root {
  --ink: #2b1d10;
  --ink-deep: #3a2a17;
  --ink-soft: #4a3521;
  --muted: #6b5334;
  --muted-light: #8a7250;
  --rust: #7a2318;
  --dark: #241608;
  --cream: #f6e8c6;
  --cream-dim: #f0dcb4;
  --gold: #e0b871;
  /* The design sizes the ledger at min(620, max(420, 44% of viewport)). */
  --panel-w: clamp(420px, 44vw, 620px);
  --topbar-h: 58px;
  --console-h: 92px;
}

html, body { margin: 0; padding: 0; background: var(--dark); }
body {
  font-family: "IM Fell English", Georgia, serif;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
* { box-sizing: border-box; }
a { color: var(--rust); text-decoration-color: rgba(122, 35, 24, 0.4); text-underline-offset: 3px; }
a:hover { color: #40281a; text-decoration-color: rgba(64, 40, 26, 0.8); }
::selection { background: rgba(122, 35, 24, 0.22); }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 99;
  background: #f8eed7; color: var(--ink); padding: 10px 14px;
  border: 1px solid var(--rust); border-radius: 2px; font-size: 14px;
  transition: top .15s ease;
}
.skip-link:focus { top: 8px; }

input[type=range] { -webkit-appearance: none; appearance: none; background: transparent; accent-color: #8a6626; }
input[type=range]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px;
  background: linear-gradient(#c9b384, #b39a68);
  box-shadow: inset 0 1px 2px rgba(43, 29, 16, .5);
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 26px; height: 26px; margin-top: -10px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #d8ae5e, #8a6626 70%, #5c4218);
  border: 1px solid #4a3517; box-shadow: 0 2px 5px rgba(20, 10, 0, .5); cursor: grab;
}
input[type=range]::-moz-range-track { height: 6px; border-radius: 3px; background: #bda474; }
input[type=range]::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #d8ae5e, #8a6626 70%); border: 1px solid #4a3517;
}

@keyframes drift { from { transform: translate3d(-6%,0,0) } to { transform: translate3d(6%,0,0) } }
@keyframes inkrise { from { opacity: 0; transform: translateY(14px) } to { opacity: 1; transform: none } }
@keyframes sealin { from { opacity: 0; transform: scale(.82) rotate(-9deg) } to { opacity: 1; transform: none } }

/* ── stage ─────────────────────────────────────────────────────────── */

.stage {
  position: relative; width: 100%; height: 100dvh; min-height: 560px;
  overflow: hidden; background: var(--dark); isolation: isolate;
}
/* Without dvh support the viewport unit falls back before the override above. */
@supports not (height: 100dvh) { .stage { height: 100vh; } }

.map-wrap { position: absolute; inset: 0; overflow: hidden; background: var(--dark); }
.map-wrap atlas-map, .map-wrap .map-fallback { position: absolute; inset: 0; width: 100%; height: 100%; }

/* The map element styles itself from here rather than from a cssText assignment,
   so style-src can stay strict. The element sets .style.opacity and .style.cursor
   at runtime — CSSOM property writes, which CSP does not treat as inline styles. */
atlas-map { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; touch-action: none; background: var(--dark); cursor: grab; }
atlas-map canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; transition: opacity .55s ease; }
atlas-map canvas[data-l="2d"] { opacity: 0; }
@media (prefers-reduced-motion: reduce) { atlas-map canvas { transition: none; } }

.veil { position: absolute; inset: 0; pointer-events: none; }
.veil-vignette { background: radial-gradient(120% 90% at 50% 45%, rgba(255,232,180,0) 40%, rgba(60,34,10,0.34) 78%, rgba(36,22,8,0.68) 100%); }
.veil-drift {
  inset: -10%; opacity: .5; mix-blend-mode: multiply;
  background: radial-gradient(38% 24% at 22% 30%, rgba(122,86,40,.18), transparent 70%),
              radial-gradient(30% 20% at 76% 66%, rgba(122,86,40,.15), transparent 70%);
  animation: drift 46s ease-in-out infinite alternate;
}

/* Static poster shown until the globe is asked for, and whenever WebGL is unavailable. */
.map-fallback {
  display: grid; place-items: center; text-align: center; padding: 24px;
  background: radial-gradient(circle at 42% 34%, #3c2712, #241608 70%);
}
/* Any author `display` beats the UA stylesheet's [hidden] rule, so every element
   we hide via the property needs to say so explicitly or the attribute is inert. */
.map-fallback[hidden] { display: none; }
.map-fallback p {
  max-width: 46ch; color: rgba(246,232,198,.8); font-size: 15px; line-height: 1.6;
}
.launch-globe {
  margin-top: 14px; cursor: pointer; border: 1px solid rgba(224,184,113,.55);
  background: rgba(224,184,113,.12); color: var(--cream); border-radius: 2px;
  padding: 11px 18px; font-family: "IM Fell English SC", serif; font-size: 13px; letter-spacing: .18em;
  min-height: 44px;
}
.launch-globe:hover { background: rgba(224,184,113,.24); }

.screen { position: absolute; inset: 0; pointer-events: none; }
.screen[hidden] { display: none; }

/* ── atlas screen ──────────────────────────────────────────────────── */

.atlas-grid {
  position: absolute; inset: 0; display: grid;
  grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr auto;
  pointer-events: none;
}
.atlas-header {
  pointer-events: auto; padding: 18px clamp(14px, 4vw, 44px) 0;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
}
.atlas-title {
  margin: 0; font-family: "IM Fell English SC", Georgia, serif;
  font-size: clamp(30px, 7vw, 62px); line-height: .95; letter-spacing: .02em; color: var(--cream);
  text-shadow: 0 2px 0 rgba(30,16,4,.55), 0 0 34px rgba(255,206,130,.25);
}
.atlas-title span { color: var(--gold); }
.atlas-tagline {
  margin: 8px 0 0; max-width: 34ch; font-size: clamp(13px, 3.4vw, 17px);
  font-style: italic; color: rgba(246,232,198,.86); text-wrap: pretty;
}
.globe-hint-row { display: grid; place-items: center; padding: 8px 16px; }
.globe-hint {
  pointer-events: none; margin: 0; max-width: min(92vw, 460px);
  font-family: ui-monospace, monospace; font-size: 10.5px; line-height: 1.7; letter-spacing: .2em;
  text-transform: uppercase; color: rgba(246,232,198,.66); background: rgba(36,22,8,.42);
  padding: 7px 14px; border: 1px solid rgba(224,184,113,.28); border-radius: 2px;
  backdrop-filter: blur(2px); text-align: center;
  transition: opacity .9s ease .2s, transform .9s ease .2s;
}
/* It has said its piece after a few seconds, or the moment you touch anything. */
.globe-hint.is-gone { opacity: 0; transform: translateY(-6px); }
.ledgers { pointer-events: auto; min-width: 0; padding: 0 clamp(10px, 3vw, 34px) clamp(14px, 3vw, 28px); }
.ledgers h2 {
  margin: 0 0 10px; padding: 0 4px; font-family: "IM Fell English SC", serif;
  font-size: 12px; letter-spacing: .3em; color: rgba(224,184,113,.85); text-transform: uppercase;
}
.ledger-rail {
  display: flex; align-items: stretch; min-width: 0; gap: 10px; overflow-x: auto; padding: 4px 4px 12px;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  list-style: none; margin: 0;
}
.ledger-rail > li { flex: 0 0 auto; scroll-snap-align: start; display: flex; }
/* Swiped-to card on a phone: the rest step back so the selected one is obvious.
   `rail-live` is added by the script on the first swipe and never before — see
   bindLedgerSwipe — so the atlas opens with all five ledgers equal and all five
   routes inked, which is the picture it exists to show. */
@media (max-width: 979px) {
  .ledger-rail.rail-live .ledger-card { opacity: .48; }
  .ledger-rail.rail-live .ledger-card.is-current { opacity: 1; }
}
/* Ledger card — option 1d from the design's card study: ruled index card,
   poured-wax countersign, and a band of three figures. */
.ledger-card {
  position: relative; display: flex; flex-direction: column; height: 100%;
  width: min(80vw, 306px); text-align: left; cursor: pointer;
  border: 1px solid rgba(58,42,23,.38); padding: 16px 17px 15px;
  color: var(--ink); font-family: inherit; text-decoration: none;
  background: linear-gradient(168deg, #f5e9d0, #e8dab4 60%, #dac59a);
  box-shadow: 0 14px 34px rgba(12,6,0,.5), inset 0 1px 0 rgba(255,250,232,.8);
  transition: transform .22s ease, box-shadow .22s ease, opacity .25s ease;
}
.ledger-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 42px rgba(12,6,0,.6), inset 0 1px 0 rgba(255,250,232,.9);
}
.ledger-card-rule { position: absolute; inset: 6px; pointer-events: none; border: 1px solid rgba(58,42,23,.16); }
.ledger-card-head {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 52px;
  column-gap: 12px; align-items: start;
}
.ledger-card-idents { display: block; min-width: 0; }

/* Poured wax: irregular blob, a drip where it ran, a pressed rim, the numeral struck in.
   Everything derives from --wax, so the same seal serves the card and the journey header. */
.wax {
  --wax: 52px;
  position: relative; display: block; width: var(--wax); height: var(--wax);
  animation: sealin .5s ease both;
}
.wax > * { position: absolute; }
.wax-blob {
  inset: 0; border-radius: 52% 48% 46% 54% / 50% 46% 54% 50%;
  background: radial-gradient(circle at 33% 25%, #cd5330 0%, #a63420 34%, #751d12 70%, #440e08 100%);
  filter: drop-shadow(0 3px 5px rgba(18,4,0,.5));
}
.wax-drip {
  left: 20%; top: 82%;
  width: calc(var(--wax) * .21); height: calc(var(--wax) * .31);
  border-radius: 50% 50% 44% 56% / 38% 40% 62% 60%;
  background: radial-gradient(circle at 42% 22%, #a63420, #4f120b 84%);
}
.wax-rim {
  inset: calc(var(--wax) * .096); border-radius: 50%;
  box-shadow: inset 0 -3px 5px rgba(40,6,0,.6), inset 0 2px 3px rgba(255,190,150,.3);
}
.wax-mark {
  inset: 0; display: grid; place-items: center;
  font-family: "IM Fell English SC", serif; font-size: calc(var(--wax) * .327); color: #f9dfc2;
  text-shadow: 0 1px 2px rgba(50,10,0,.85);
}
/* The journey header carries the same seal, struck a little larger. */
.wax--lg { --wax: 62px; flex: none; }

/* Three figures, ruled like a ledger band. */
.fact-band {
  position: relative; margin-top: 12px; display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px;
  background: rgba(58,42,23,.22); border: 1px solid rgba(58,42,23,.22);
}
.fact { display: block; background: rgba(255,248,228,.62); padding: 6px 7px; min-width: 0; }
.fact-k { display: block; font-family: "IM Fell English SC", serif; font-size: 8px; letter-spacing: .14em; color: var(--muted-light); }
.fact-v {
  display: block; font-family: ui-monospace, monospace; font-size: 10.5px; color: #40281a;
  margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.seal {
  flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  text-align: center; font-family: "IM Fell English SC", serif; font-size: 15px; line-height: 1;
  letter-spacing: .04em; color: #f7e3c4;
  background: radial-gradient(circle at 35% 28%, #a8341f, #6d1c12 72%, #4d130c);
  box-shadow: inset 0 -2px 4px rgba(0,0,0,.45), 0 2px 5px rgba(20,10,0,.4);
  animation: sealin .5s ease both;
}
/* These are spans so they can live inside the card's <a>; they still need to stack. */
.ledger-card-title { display: block; font-family: "IM Fell English SC", serif; font-size: 19px; line-height: 1.1; }
.ledger-card-years { display: block; font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .14em; color: var(--muted); margin-top: 3px; }
.ledger-card-seal { display: block; font-family: "IM Fell English SC", serif; font-size: 9.5px; letter-spacing: .22em; color: var(--muted-light); margin-top: 2px; }
.ledger-card p {
  position: relative; flex: 1 1 auto; margin: 11px 0 0;
  font-size: 13.5px; line-height: 1.48; color: var(--ink-soft); text-wrap: pretty;
}
.ledger-card-foot { position: relative; margin-top: 12px; }
.ledger-card-cta { font-family: "IM Fell English SC", serif; font-size: 11px; letter-spacing: .2em; color: var(--rust); }

.atlas-footer { margin: 9px 4px 0; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
/* On the ledger the colophon sits on parchment, not on the dark stage. */
.ledger-colophon { margin: 12px 0 0; }
.ledger-colophon .legal-link { color: var(--rust); }
.ledger-colophon .legal-link:hover { color: #40281a; }
.legal-link {
  padding: 4px 0; font-family: "IM Fell English SC", serif; font-size: 11px;
  letter-spacing: .2em; color: rgba(224,184,113,.85); text-decoration: none;
}
.legal-link:hover, .legal-link[aria-current="page"] { color: var(--cream); text-decoration: underline; }
.copyright { font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .1em; color: rgba(246,232,198,.42); }
.atlas-note {
  margin: 2px 4px 0; max-width: 78ch; font-size: 12.5px; line-height: 1.5;
  color: #f4e6c4; font-style: italic;
  text-shadow: 0 1px 3px rgba(24,12,2,.95), 0 0 10px rgba(24,12,2,.8);
}

/* ── journey screen ────────────────────────────────────────────────── */

.topbar {
  /* Above the passage (4) and the expand button (5): the topbar's own dropdown is
     painted inside this stacking context, so anything the menu has to cover has to
     be below the bar itself. It opened underneath the expand button otherwise. */
  position: absolute; left: 0; right: 0; top: 0; z-index: 6; pointer-events: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px clamp(10px, 3vw, 20px);
  background: linear-gradient(#3a2416, #2a1a0e);
  border-bottom: 1px solid rgba(224,184,113,.28);
  box-shadow: 0 6px 18px rgba(10,5,0,.45);
}
.topbar-btn {
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px; background: none;
  border: 1px solid rgba(224,184,113,.35); border-radius: 2px; padding: 7px 11px;
  color: var(--cream-dim); font-family: "IM Fell English SC", serif; font-size: 12px;
  letter-spacing: .16em; text-decoration: none; min-height: 38px;
}
.topbar-btn:hover { background: rgba(224,184,113,.14); color: var(--cream); }
.topbar-mid { min-width: 0; text-align: center; }
.topbar-title {
  font-family: "IM Fell English SC", serif; font-size: clamp(15px, 4vw, 22px); color: var(--cream);
  line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0;
}
.topbar-years {
  font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .18em;
  color: rgba(224,184,113,.8);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* The fleet roster is long enough to wrap the bar to three lines on a phone. */
@media (max-width: 700px) { .topbar-years .fleet { display: none; } }
.topbar-actions { display: flex; gap: 7px; }
.topbar-menu { display: flex; gap: 7px; }
/* The burger only appears where the topbar runs out of room, and only when the
   script that opens it is running. Both controls behind it are script-only
   anyway — the mode toggle needs the map, the passage panel is opened by JS — so
   without JS they stay laid out inline exactly as before rather than sitting
   behind a button that cannot open. */
.topbar-burger { display: none; }

@media (max-width: 700px) {
  /* "← Atlas" is the only back affordance on the page and the arrow carries it.
     The word is dropped for room, not from the accessible name: the link keeps
     its aria-label. */
  .topbar-back .btn-word { display: none; }
  .topbar-back { padding-left: 13px; padding-right: 13px; }

  html.js .topbar-burger { display: inline-flex; }
  html.js .topbar-menu {
    position: absolute; right: clamp(10px, 3vw, 20px); top: calc(100% + 6px);
    flex-direction: column; gap: 0; min-width: 176px; padding: 5px;
    background: linear-gradient(#3a2416, #2a1a0e);
    border: 1px solid rgba(224, 184, 113, .34);
    box-shadow: 0 14px 30px rgba(10, 5, 0, .55);
  }
  html.js .topbar-menu[hidden] { display: none; }
  html.js .topbar-menu .topbar-btn { border: 0; justify-content: flex-start; width: 100%; }
  html.js .topbar-menu .topbar-btn + .topbar-btn { border-top: 1px solid rgba(224, 184, 113, .18); }
}

.passage {
  position: absolute; z-index: 4; pointer-events: auto;
  left: 12px; right: 12px; top: 60px;
  padding: 14px 15px 16px;
  background: linear-gradient(#faf0d8, #f0e2c0); border: 1px solid rgba(58,42,23,.35);
  box-shadow: 0 14px 34px rgba(20,10,0,.45); animation: inkrise .35s ease both;
}
/* On a phone the passage opened directly over the map — the one thing it is
   describing. It sits at the foot instead, over the ledger, which is text the
   reader can get back to by closing it. It scrolls, because a long quotation on a
   small screen would otherwise run off the bottom with no way to reach the rest. */
@media (max-width: 979px) {
  .passage {
    top: auto; bottom: 10px; left: 8px; right: 8px;
    max-height: 52dvh; overflow-y: auto; overscroll-behavior: contain;
  }
  /* Expanded, the ledger is gone and only the console is below, so clear it. */
  .stage.map-full .passage { bottom: calc(var(--console-h) + 10px); }
}
.passage[hidden] { display: none; }

/* Expand the map. Only on a phone, where the chart gets barely a third of the
   screen and panning a route through that letterbox is the worst of both. Layout
   expansion rather than the Fullscreen API: this has to work in an iOS home-screen
   web app, where requestFullscreen on an element does not. */
/* Sized and aligned to the topbar buttons directly above it — same 38px box, same
   right edge, same border and radius — so it reads as one column of controls
   rather than a floating extra. The bar's own padding sets that edge, so the two
   stay lined up at every width. */
.map-expand {
  position: absolute; z-index: 5; display: none; pointer-events: auto;
  top: calc(var(--topbar-h) + 8px); right: clamp(10px, 3vw, 20px);
  width: 38px; height: 38px; padding: 0; cursor: pointer;
  align-items: center; justify-content: center;
  border: 1px solid rgba(224, 184, 113, .35); border-radius: 2px;
  background: linear-gradient(rgba(58, 36, 22, .88), rgba(42, 26, 14, .92));
  color: var(--cream-dim);
  box-shadow: 0 4px 14px rgba(10, 5, 0, .4);
  backdrop-filter: blur(2px);
}
.map-expand svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.map-expand:hover { background: linear-gradient(rgba(74, 48, 28, .94), rgba(54, 34, 18, .96)); color: var(--cream); }
.map-expand .ic-in { display: none; }
.map-expand[aria-pressed="true"] .ic-out { display: none; }
.map-expand[aria-pressed="true"] .ic-in { display: inline; }
@media (max-width: 979px) { .map-expand { display: inline-flex; } }

/* Expanded: the panel and the ledger get out of the way and the chart takes the
   stage. The console stays — it is how you move along the route, and losing it
   would trade one cramped thing for another. */
.stage.map-full .ledger-panel { display: none; }
.stage.map-full .console { bottom: 0; }
.passage-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.passage-head h3 { margin: 0; font-family: "IM Fell English SC", serif; font-size: 14px; letter-spacing: .18em; color: var(--rust); }
.passage-close { cursor: pointer; border: none; background: none; font-family: ui-monospace, monospace; font-size: 11px; color: var(--muted); min-height: 32px; }
.passage-text { margin: 10px 0 0; font-family: Caveat, cursive; font-size: 21px; line-height: 1.5; color: #2f2313; text-wrap: pretty; }
.passage-cite { margin: 8px 0 0; font-family: ui-monospace, monospace; font-size: 10.5px; line-height: 1.6; letter-spacing: .06em; color: var(--muted-light); }
.passage-audio {
  margin: 12px 0 0; padding-top: 9px; border-top: 1px dotted rgba(122,35,24,.4);
  font-family: ui-monospace, monospace; font-size: 10px; line-height: 1.7; letter-spacing: .06em; color: var(--rust);
}

.console {
  position: absolute; z-index: 2; pointer-events: auto;
  left: 0; width: 100%; bottom: 62%;
  display: flex; align-items: center; gap: 11px; flex-wrap: nowrap; padding: 8px 14px;
  background: linear-gradient(rgba(42,26,14,.86), rgba(30,18,9,.94));
  border-top: 1px solid rgba(224,184,113,.24); border-bottom: 1px solid rgba(224,184,113,.24);
  backdrop-filter: blur(3px); box-shadow: 0 -8px 26px rgba(10,5,0,.4);
}
.transport { display: flex; align-items: center; gap: 8px; }
.step-btn {
  cursor: pointer; width: 46px; height: 46px; flex: none; border-radius: 50%;
  border: 1px solid rgba(224,184,113,.4); background: rgba(246,232,198,.1);
  color: var(--cream-dim); font-size: 13px; display: none;
}
.step-btn:hover { background: rgba(246,232,198,.22); }
.play-btn {
  cursor: pointer; width: 54px; height: 54px; flex: none; border-radius: 50%;
  border: 1px solid #5c4218;
  background: radial-gradient(circle at 34% 28%, #d8ae5e, #8a6626 72%, #5c4218);
  color: var(--ink); font-size: 16px;
  box-shadow: 0 3px 8px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,236,190,.5);
}
.scrub-wrap { flex: 1 1 220px; min-width: 150px; }
.scrub-wrap input[type=range] { width: 100%; height: 24px; display: block; }
.scrub-labels {
  display: flex; justify-content: space-between; gap: 10px;
  font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .12em; color: rgba(240,222,186,.78);
}
.speeds { align-items: center; gap: 6px; display: none; }
.speed-btn {
  cursor: pointer; font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .1em;
  min-width: 44px; min-height: 44px; padding: 0 10px; border-radius: 2px;
  border: 1px solid rgba(224,184,113,.3); background: transparent; color: rgba(240,222,186,.7);
}
.speed-btn[aria-pressed="true"] { border-color: rgba(224,184,113,.75); background: rgba(224,184,113,.22); color: var(--cream); }

.ledger-panel {
  position: absolute; left: 0; right: 0; bottom: 0; height: 62%;
  pointer-events: auto; display: flex; flex-direction: column;
  background: linear-gradient(168deg, #f4e8ce, #ece0be 55%, #e5d3ac);
  border-top: 1px solid rgba(255,248,225,.7); border-radius: 6px 6px 0 0;
  box-shadow: 0 -18px 46px rgba(20,10,0,.5), inset 0 1px 0 rgba(255,250,230,.8);
}
.ledger-grain {
  position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background: repeating-linear-gradient(0deg, rgba(120,92,52,.045) 0 1px, transparent 1px 4px),
              radial-gradient(60% 40% at 12% 8%, rgba(126,86,40,.09), transparent 70%),
              radial-gradient(50% 36% at 88% 84%, rgba(126,86,40,.08), transparent 70%);
}
.tabbar {
  position: relative; flex: none; display: flex; gap: 4px; overflow-x: auto;
  padding: 9px 12px 0; border-bottom: 1px solid rgba(58,42,23,.32);
}
.tab {
  cursor: pointer; flex: none; font-family: "IM Fell English SC", serif; font-size: 12px;
  letter-spacing: .15em; min-height: 44px; padding: 0 13px; text-decoration: none;
  display: inline-flex; align-items: center;
  border: 1px solid rgba(58,42,23,.2); border-bottom: none; border-radius: 3px 3px 0 0;
  color: #7a6547; background: rgba(214,196,158,.45);
  transform: translateY(2px); transition: all .2s ease;
}
.tab[aria-selected="true"], .tab[aria-current="page"] {
  border-color: rgba(58,42,23,.5); color: #40281a;
  background: linear-gradient(#fdf3da, #f2e4c4); transform: translateY(0);
}
.ledger-scroll {
  position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; scroll-behavior: smooth;
  padding: clamp(16px, 3.2vw, 34px) clamp(15px, 3.4vw, 40px) 56px;
}
.read-width { max-width: none; margin: 0 auto; }

/* Separates the panels only when they stack, i.e. without scripting. An adjacent
   sibling selector does not care that the panel before it is display:none, so this
   was adding 42px above every tab except Chart. */
html:not(.js) .tabpanel + .tabpanel { margin-top: 42px; }
.tabpanel > h2 {
  margin: 2px 0 4px; font-family: "IM Fell English SC", serif;
  font-size: clamp(21px, 4.6vw, 30px); line-height: 1.05;
}
.tabpanel-lede { margin: 0 0 18px; font-size: 14.5px; font-style: italic; color: var(--muted); }

/* Chart tab */
.chart-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; justify-content: space-between; }
.chart-head-idents { min-width: 0; }
.chart-seal-label { font-family: "IM Fell English SC", serif; font-size: 10px; letter-spacing: .3em; color: var(--muted-light); }
.chart-title { margin: 4px 0 0; font-family: "IM Fell English SC", serif; font-size: clamp(26px, 5.4vw, 46px); line-height: 1; letter-spacing: .01em; }
.chart-sub { margin: 5px 0 0; font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .16em; color: var(--rust); }
.chart-blurb { margin: 14px 0 0; font-size: clamp(16px, 4vw, 19px); line-height: 1.6; font-style: italic; color: var(--ink-soft); text-wrap: pretty; }
.chart-summary { margin: 14px 0 0; font-size: clamp(15px, 3.9vw, 17.5px); line-height: 1.65; text-wrap: pretty; }
/* Sits under the live card: the "what was this voyage" text, out of the way of the
   card but still early in the document. */
.brief { margin-top: 26px; padding-top: 16px; border-top: 1px solid rgba(58,42,23,.24); }
.brief h3 {
  margin: 0; font-family: "IM Fell English SC", serif; font-size: 11px;
  letter-spacing: .22em; color: var(--muted-light);
}
.brief .chart-summary { margin-top: 8px; }

.now-card {
  margin-top: 24px; position: relative; border: 1px solid rgba(58,42,23,.3); border-radius: 2px;
  padding: 20px 20px 22px; background: linear-gradient(#f8eed7, #efe0c0);
  box-shadow: 0 8px 22px rgba(40,24,8,.16);
}
.now-stamp {
  position: absolute; top: -13px; right: 16px; transform: rotate(-3deg);
  font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .16em; color: var(--rust);
  border: 1.5px solid rgba(122,35,24,.55); border-radius: 2px; padding: 4px 8px;
  background: rgba(248,238,215,.97);
}
.now-eyebrow { font-family: "IM Fell English SC", serif; font-size: 10px; letter-spacing: .26em; color: var(--muted-light); }
.now-name { margin: 5px 0 2px; font-family: "IM Fell English SC", serif; font-size: clamp(22px, 5vw, 33px); line-height: 1.04; }
.now-place { font-size: 14.5px; font-style: italic; color: var(--muted); }
.now-quote {
  margin: 15px 0 0; padding: 0 0 0 15px; border-left: 2px solid rgba(122,35,24,.4);
  font-size: clamp(16px, 4.2vw, 20px); line-height: 1.55; font-style: italic; color: #33240f; text-wrap: pretty;
}
.now-source { margin-top: 6px; padding-left: 16px; font-family: ui-monospace, monospace; font-size: 10.5px; letter-spacing: .1em; color: var(--muted-light); }
.now-note { margin: 15px 0 0; font-size: clamp(15px, 3.9vw, 17.5px); line-height: 1.65; text-wrap: pretty; }
.now-facts { margin: 18px 0 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.now-facts > div { border-top: 1px solid rgba(58,42,23,.25); padding-top: 8px; }
.now-facts dt { font-family: "IM Fell English SC", serif; font-size: 10px; letter-spacing: .2em; color: var(--muted-light); }
.now-facts dd { margin: 3px 0 0; font-size: 15px; line-height: 1.4; }
.uncertain {
  margin: 15px 0 0; font-family: ui-monospace, monospace; font-size: 10.5px; line-height: 1.7;
  letter-spacing: .06em; color: var(--rust); border-top: 1px dotted rgba(122,35,24,.45); padding-top: 9px;
}
.chart-hint { margin: 15px 0 0; font-family: ui-monospace, monospace; font-size: 10.5px; line-height: 1.7; letter-spacing: .06em; color: var(--muted-light); }

/* Landfall navigator — step through stops without leaving the card. */
.landfall-nav {
  margin-top: 20px; padding-top: 15px; border-top: 1px solid rgba(58,42,23,.28);
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 10px; align-items: stretch;
}
.nav-btn {
  min-height: 52px; padding: 9px 12px; cursor: pointer;
  border: 1px solid rgba(58,42,23,.3); border-radius: 2px; font-family: inherit;
  background: rgba(255,248,228,.6);
  transition: background .2s ease, border-color .2s ease;
}
.nav-btn--prev { text-align: left; }
.nav-btn--next { text-align: right; }
.nav-btn:hover:not(:disabled) { background: rgba(255,250,232,.95); border-color: rgba(58,42,23,.5); }
.nav-btn:disabled { opacity: .38; pointer-events: none; cursor: default; }
.nav-btn-kicker { font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--muted-light); }
.nav-btn-name {
  display: block; margin-top: 3px; font-family: "IM Fell English SC", serif;
  font-size: 15px; line-height: 1.15; color: #40281a;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.landfall-count {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 6px; min-width: 66px;
}
.landfall-count-k { font-family: "IM Fell English SC", serif; font-size: 9.5px; letter-spacing: .2em; color: var(--muted-light); }
.landfall-count-v { font-family: ui-monospace, monospace; font-size: 14px; letter-spacing: .1em; color: var(--rust); margin-top: 3px; }
.stop-dots {
  grid-column: 1 / -1; list-style: none; margin: 0; padding: 0 0 2px;
  display: flex; gap: 2px; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.stop-dots > li { flex: 1 1 auto; min-width: 30px; }
.stop-dot-btn {
  width: 100%; height: 44px; display: grid; place-items: center; padding: 0;
  cursor: pointer; border: none; background: none; border-radius: 2px;
  transition: background .2s ease;
}
.stop-dot-btn:hover { background: rgba(58,42,23,.08); }
.stop-dot {
  display: block; width: 10px; height: 10px; border-radius: 50%;
  border: 1px solid rgba(58,42,23,.4); background: transparent;
  transition: background .2s ease, box-shadow .2s ease;
}
.stop-dot.is-past { background: rgba(58,42,23,.5); }
.stop-dot.is-current {
  border-color: rgba(58,42,23,.75); background: var(--rust);
  box-shadow: 0 0 0 3px rgba(122,35,24,.16);
}

/* Log tab */
.log-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.log-entry { border: 1px solid rgba(58,42,23,.22); padding: 14px 15px 15px; background: rgba(255,248,228,.42); transition: opacity .3s ease; }
.log-entry.is-current { border-color: rgba(58,42,23,.55); background: linear-gradient(#fdf3da, #f4e6c6); box-shadow: 0 6px 16px rgba(40,24,8,.16); }
.log-entry.is-future { opacity: .74; }
.log-entry > a, .log-entry > button {
  all: unset; cursor: pointer; display: block; width: 100%;
}
.log-entry > a:focus-visible, .log-entry > button:focus-visible { outline: 2px solid var(--rust); outline-offset: 3px; }
.log-meta { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; }
.log-stamp { font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .16em; color: var(--rust); }
.log-no { font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .1em; color: var(--muted-light); }
.log-name { display: block; margin-top: 5px; font-family: "IM Fell English SC", serif; font-size: 19px; line-height: 1.15; }
.log-place { display: block; font-size: 13px; font-style: italic; color: var(--muted); }
.log-note { margin: 9px 0 0; font-size: 15px; line-height: 1.58; text-wrap: pretty; }
.log-quote { margin: 9px 0 0; font-style: italic; font-size: 14.5px; line-height: 1.55; color: #5b452a; }
.chips { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .08em; color: var(--ink-soft);
  border: 1px solid rgba(58,42,23,.28); border-radius: 999px; padding: 3px 9px; background: rgba(255,247,226,.6);
}
.chip-warn { color: var(--rust); border-color: rgba(122,35,24,.4); background: rgba(122,35,24,.06); }
.log-event {
  display: block;
  margin-top: 10px; font-family: ui-monospace, monospace; font-size: 10px; line-height: 1.7;
  letter-spacing: .1em; text-transform: uppercase; color: var(--rust);
}
.ad-slot { margin-top: 26px; padding: 12px 12px 14px; border: 1px solid rgba(58,42,23,.3); background: rgba(226,208,170,.45); }
.ad-slot-label { font-family: "IM Fell English SC", serif; font-size: 10px; letter-spacing: .26em; color: var(--muted-light); }
.ad-slot-box {
  margin-top: 8px; border: 1px dashed rgba(58,42,23,.4); padding: 22px 14px; text-align: center;
  min-height: 250px; display: grid; place-items: center;
  font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .1em; color: var(--muted);
  background: repeating-linear-gradient(45deg, rgba(58,42,23,.05) 0 6px, transparent 6px 12px);
}

/* Landfalls tab */
.plate-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr)); gap: 16px; }
.plate { margin: 0; border: 1px solid rgba(58,42,23,.28); background: linear-gradient(#f7ecd4, #ecdcb8); box-shadow: 0 5px 16px rgba(40,24,8,.14); padding: 10px 10px 12px; }
.plate-frame { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: #ddcaa2; border: 1px solid rgba(58,42,23,.3); }
.plate-frame img { width: 100%; height: 100%; object-fit: cover; filter: sepia(.42) contrast(1.06) saturate(.72); display: block; }
/* The frame crops; the link goes to the uncropped original on the holding site. */
.plate-link { display: block; height: 100%; }
.plate-link:focus-visible { outline: 2px solid var(--rust); outline-offset: 2px; }
.plate-link img { transition: filter .25s ease, transform .25s ease; }
.plate-link:hover img, .plate-link:focus-visible img { filter: sepia(.18) contrast(1.04) saturate(.92); transform: scale(1.02); }
@media (prefers-reduced-motion: reduce) { .plate-link img { transition: none; } .plate-link:hover img { transform: none; } }
.plate-slot {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 12px; font-family: ui-monospace, monospace; font-size: 10.5px;
  line-height: 1.6; letter-spacing: .06em; color: var(--muted);
  background: repeating-linear-gradient(135deg, rgba(58,42,23,.07) 0 7px, transparent 7px 14px);
}
.plate figcaption { margin-top: 9px; }
.plate-name { font-family: "IM Fell English SC", serif; font-size: 16px; }
.plate-stamp { font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--rust); margin-top: 2px; }
.plate-note { margin: 7px 0 0; font-size: 14px; line-height: 1.5; text-wrap: pretty; }
.plate-hand { margin: 7px 0 0; font-family: Caveat, cursive; font-size: 17px; color: #5b452a; }

/* Reckoning tab */
.stat-grid { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }
.stat { border: 1px solid rgba(58,42,23,.24); padding: 12px 13px; background: rgba(255,248,228,.5); }
.stat dt { font-family: "IM Fell English SC", serif; font-size: 10px; letter-spacing: .22em; color: var(--muted-light); }
.stat dd { margin: 5px 0 0; font-size: 16px; line-height: 1.35; }
.stat-method { margin: 6px 0 0; font-family: ui-monospace, monospace; font-size: 9.5px; line-height: 1.6; color: var(--muted-light); }
.reck-cols { margin-top: 16px; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }
.difficulty { border: 1px solid rgba(122,35,24,.3); padding: 14px 15px; background: rgba(122,35,24,.05); }
.difficulty h3 { margin: 0; font-family: "IM Fell English SC", serif; font-size: 11px; letter-spacing: .22em; color: var(--rust); }
.dots { margin-top: 9px; display: flex; align-items: center; gap: 7px; }
.dot { width: 15px; height: 15px; border-radius: 50%; border: 1px solid rgba(122,35,24,.55); }
.dot.on { background: radial-gradient(circle at 34% 28%, #a8341f, #6d1c12 72%); box-shadow: inset 0 -1px 2px rgba(0,0,0,.4); }
.dots-label { margin-left: 6px; font-family: ui-monospace, monospace; font-size: 10.5px; letter-spacing: .1em; color: var(--muted); }
.axes { margin: 12px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 9px; }
.axis-row { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: baseline; }
.axis-key { font-family: "IM Fell English SC", serif; font-size: 12px; letter-spacing: .1em; }
.axis-score { font-family: ui-monospace, monospace; font-size: 10.5px; color: var(--rust); }
.axis-note { margin: 2px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
.model-note { margin: 12px 0 0; font-family: ui-monospace, monospace; font-size: 10px; line-height: 1.7; color: var(--muted-light); }
.modern h3 { margin: 0 0 8px; font-family: "IM Fell English SC", serif; font-size: 15px; letter-spacing: .06em; }
.modern p { margin: 0 0 12px; font-size: 15px; line-height: 1.6; text-wrap: pretty; }
.modern-rows { display: flex; flex-direction: column; gap: 1px; background: rgba(58,42,23,.2); border: 1px solid rgba(58,42,23,.2); }
.modern-row { display: flex; gap: 12px; justify-content: space-between; padding: 9px 12px; background: rgba(255,248,228,.72); font-size: 14.5px; }
.modern-row span:first-child { font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .12em; color: var(--rust); padding-top: 2px; }
.modern-row span:last-child { text-align: right; }
.review-note { margin: 10px 0 0; font-family: ui-monospace, monospace; font-size: 10px; line-height: 1.7; color: var(--muted-light); }

/* Archive tab */
.world-plates { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.archive-cols { margin-top: 22px; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 22px; align-items: start; }
.archive-cols h3 { margin: 0 0 9px; font-family: "IM Fell English SC", serif; font-size: 13px; letter-spacing: .2em; color: var(--rust); }
.source-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.source-list li { border-left: 2px solid rgba(58,42,23,.3); padding-left: 12px; }
.source-title { font-size: 15px; line-height: 1.4; }
.source-desc { margin-top: 3px; font-size: 13.5px; font-style: italic; color: var(--muted); line-height: 1.5; }
.source-meta { margin-top: 4px; font-family: ui-monospace, monospace; font-size: 9.5px; line-height: 1.6; letter-spacing: .06em; color: var(--muted-light); }
/* Set above the credit and darker than it: what the picture is worth as evidence
   matters more to a reader than who to thank for it. */
.plate-relation {
  margin: 8px 0 0; font-family: ui-monospace, monospace; font-size: 9.5px;
  line-height: 1.6; letter-spacing: .08em; text-transform: uppercase; color: var(--rust);
}
.plain-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; font-size: 14.5px; line-height: 1.45; }
.reading-h3 { margin-top: 18px; }
.faq-list { margin: 22px 0 0; }
.faq-head { margin: 0; font-family: "IM Fell English SC", serif; font-size: 13px; letter-spacing: .2em; color: var(--rust); }
.faq-item { border-top: 1px solid rgba(58,42,23,.22); padding: 12px 0 0; margin-top: 12px; }
.faq-q { margin: 0; font-family: "IM Fell English SC", serif; font-size: 16px; line-height: 1.25; }
.faq-a { margin: 6px 0 0; font-size: 14.5px; line-height: 1.6; text-wrap: pretty; }
.ledger-footer { margin-top: 30px; border-top: 1px solid rgba(58,42,23,.28); padding-top: 15px; }
.other-journeys { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0; padding: 0; }
.other-journeys a {
  display: inline-block; cursor: pointer; border: 1px solid rgba(58,42,23,.3);
  background: rgba(255,248,228,.6); border-radius: 2px; padding: 7px 11px;
  font-family: "IM Fell English SC", serif; font-size: 12px; letter-spacing: .1em;
  color: #40281a; text-decoration: none; min-height: 38px;
}
.other-journeys a:hover { background: rgba(255,248,228,.95); }
.colophon { margin: 12px 0 0; font-family: ui-monospace, monospace; font-size: 10px; line-height: 1.8; letter-spacing: .06em; color: var(--muted-light); }

/* Route legend — certainty must read without colour (plan.md §17). */
.legend { margin: 18px 0 0; padding: 12px 13px; border: 1px solid rgba(58,42,23,.24); background: rgba(255,248,228,.5); }
.legend--spaced { margin-top: 22px; }
.legend h3 { margin: 0 0 8px; font-family: "IM Fell English SC", serif; font-size: 11px; letter-spacing: .22em; color: var(--rust); }
.legend ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.legend li { display: grid; grid-template-columns: 46px 1fr; gap: 10px; align-items: center; font-size: 13px; }
.legend svg { display: block; }

/* ── ship's articles (privacy / terms) ─────────────────────────────── */

.legal-body { background: var(--dark); min-height: 100vh; }
.legal-wrap {
  min-height: 100vh; background: rgba(28,17,6,.72);
  padding: clamp(14px, 4vw, 46px) clamp(12px, 4vw, 40px) 60px;
}
.legal-sheet {
  position: relative; max-width: 74ch; margin: 0 auto;
  padding: clamp(22px, 4.5vw, 46px) clamp(18px, 4vw, 44px) clamp(28px, 5vw, 50px);
  background: linear-gradient(168deg, #f4e8ce, #ece0be 55%, #e5d3ac);
  border: 1px solid rgba(58,42,23,.4);
  box-shadow: 0 18px 46px rgba(10,5,0,.55), inset 0 1px 0 rgba(255,250,232,.8);
  color: var(--ink);
}
.legal-inner { position: relative; }
.legal-back { border-color: rgba(58,42,23,.35); color: var(--rust); }
.legal-back:hover { background: rgba(122,35,24,.08); color: #40281a; }
.legal-kicker { margin: 20px 0 0; font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .24em; color: var(--muted-light); }
.legal-title { margin: 6px 0 0; font-family: "IM Fell English SC", serif; font-size: clamp(28px, 6vw, 44px); line-height: 1.04; }
.legal-lede { margin: 12px 0 0; font-size: clamp(15px, 3.9vw, 17.5px); line-height: 1.6; font-style: italic; color: #5b452a; text-wrap: pretty; }
.legal-rule { margin: 22px 0; height: 1px; background: linear-gradient(90deg, rgba(58,42,23,.45), rgba(58,42,23,.08)); }
.legal-section { margin-bottom: 26px; }
.legal-section h2 { margin: 0 0 8px; font-family: "IM Fell English SC", serif; font-size: clamp(17px, 4vw, 21px); line-height: 1.15; }
.legal-section p { margin: 0 0 10px; font-size: clamp(15px, 3.8vw, 16.5px); line-height: 1.66; text-wrap: pretty; }
.legal-section p a, .legal-list a { color: var(--rust); text-underline-offset: 2px; }
.legal-list {
  margin: 4px 0 12px; padding-left: 20px;
  display: flex; flex-direction: column; gap: 7px;
  font-size: clamp(15px, 3.8vw, 16.5px); line-height: 1.6; text-wrap: pretty;
}
/* Section anchors are linked from the page's own contents list, so an in-page
   jump must not land the heading under the sheet's top edge. */
.legal-section[id] { scroll-margin-top: 18px; }
.legal-foot {
  margin-top: 30px; border-top: 1px solid rgba(58,42,23,.3); padding-top: 14px;
  display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center;
}
.legal-foot .legal-link { color: var(--rust); }
.legal-foot .legal-link:hover, .legal-foot .legal-link[aria-current="page"] { color: #40281a; }
.legal-foot .copyright { color: var(--muted-light); width: 100%; }

/* ── wide layout ───────────────────────────────────────────────────── */

@media (min-width: 980px) {
  .ledger-panel {
    left: auto; right: 0; top: var(--topbar-h); bottom: 0;
    width: var(--panel-w); height: auto;
    border-radius: 0; border-left: 1px solid rgba(58,42,23,.45);
  }
  .console { width: calc(100% - var(--panel-w)); bottom: 0; gap: 14px; flex-wrap: wrap; padding: 11px 22px; }
  .step-btn { display: inline-block; }
  .speeds { display: flex; }
  .tabbar { padding: 12px 22px 0; }
  .tab { font-size: 12.5px; }
  .read-width { max-width: 72ch; }
  .log-list { grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); }
  .passage { left: 24px; right: auto; top: 74px; width: min(400px, 34vw); }
}

/* ── progressive enhancement ───────────────────────────────────────── */

/* Server-rendered pages show every tab panel so the whole article is crawlable
   and usable without scripting. Only once the router boots do tabs start hiding. */
html.js .tabpanel[hidden] { display: none; }
html:not(.js) .tabpanel[hidden] { display: block; }
html:not(.js) .console { display: none; }
html:not(.js) .passage { display: none; }
html:not(.js) .ledger-panel { position: static; height: auto; width: auto; box-shadow: none; }
html:not(.js) .stage { height: auto; min-height: 0; }
html:not(.js) .map-wrap { position: relative; height: 60vh; }
html:not(.js) .screen { position: static; }
html:not(.js) .topbar { position: sticky; }
html:not(.js) .ledger-scroll { overflow: visible; }

/* Swipe transition between journeys. Transform only, so it stays on the compositor. */
.ledger-panel { will-change: transform; }
.ledger-panel.swiping { transition: none; }
.ledger-panel.settling { transition: transform .28s cubic-bezier(.22,.61,.36,1), opacity .28s ease; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001s !important;
  }
  .ledger-panel.settling { transition-duration: .08s; }
}

/* ── consent notice ─────────────────────────────────────────────────
   Fixed to the foot of the viewport, above everything, and hidden until the
   script has read the stored choice — so a reader who has already answered
   never sees it flash. `hidden` does the hiding; the rule below only stops
   `display:flex` from overriding the attribute. */
.consent[hidden] { display: none; }
/* A panel across the foot of the window, on every width.

   In a full-screen layout there is no empty corner, so a floating notice is
   always on top of something: an earlier version sat bottom left and covered the
   landfall stepper outright — the browser suite caught it by failing to click a
   button a reader could not have clicked either. A full-width panel makes the
   collision total and therefore solvable: the script measures the panel and
   publishes its height as --consent-h, and the console, the ledger and the atlas
   grid each give up exactly that much room for as long as it is up. Nothing ends
   up underneath it, so nothing has to be guessed at. */
.consent {
  position: fixed; z-index: 60;
  left: 0; right: 0; bottom: 0;
  padding: 15px clamp(12px, 4vw, 40px) calc(15px + env(safe-area-inset-bottom));
  background: linear-gradient(#f8eed7, #efe0c0);
  border-top: 1px solid rgba(58, 42, 23, .38);
  box-shadow: 0 -10px 30px rgba(40, 24, 8, .34);
}
.consent-inner {
  display: flex; align-items: center; justify-content: center; gap: clamp(16px, 3vw, 40px);
  max-width: 1180px; margin: 0 auto;
}
.consent-copy { min-width: 0; }
.consent-actions { margin-top: 0; flex: none; }

/* Room given back while the panel is up. Set on <html> by the script, cleared
   when the question is answered.
 *
 * The console is only re-anchored where it actually sits at the foot of the window:
 * the wide layout, and an expanded map. In the phone layout it sits above the
 * ledger at `bottom: 62%`, and shifting it to the panel's height moved it *down*,
 * into the ledger and under the passage. What covers it there is the ledger, and
 * the scroll padding below is what answers for that. */
.consent-open .atlas-grid { padding-bottom: var(--consent-h, 0px); }
.consent-open .ledger-scroll { padding-bottom: calc(var(--consent-h, 0px) + 56px); }
.consent-open .stage.map-full .console { bottom: var(--consent-h, 0px); }
@media (min-width: 980px) {
  .consent-open .console { bottom: var(--consent-h, 0px); }
}
.consent-h {
  margin: 0 0 6px; font-family: "IM Fell English SC", serif; font-size: 19px;
  font-weight: 400; color: var(--ink);
}
.consent-p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); text-wrap: pretty; }
.consent-actions { display: flex; gap: 10px; margin-top: 12px; }
/* Both buttons identical. A decline styled quieter than an accept is a way of
   asking without wanting an answer. */
.consent-btn {
  flex: 0 1 170px; padding: 9px 18px; cursor: pointer;
  font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); background: #f3e6c9; border: 1px solid rgba(58, 42, 23, .45);
}
.consent-btn:hover { background: #ecdcb4; }
.consent-btn:focus-visible { outline: 2px solid var(--rust); outline-offset: 2px; }
/* Side by side down to the narrowest phones: stacking them cost fifty pixels of
   height, and on the atlas that was the difference between the colophon clearing
   the panel and sitting under it. */
@media (max-width: 360px) { .consent-actions { flex-direction: column; } .consent-btn { flex: none; } }

/* Below the desktop breakpoint the map is only the top third of the screen and the
   console sits at its foot, so there is no room to float the card over the map. It
   becomes a bottom sheet instead — and the ledger it now covers gets that much extra
   scroll padding for as long as the sheet is up, so nothing underneath is stranded
   out of reach. `consent-open` is set by the script and removed when it is answered. */
@media (max-width: 979px) {
  /* Too narrow for text and buttons side by side: the buttons go underneath. The
     panel is a third of a small screen even so, which is why it is trimmed here —
     every line it saves is a line the atlas keeps. */
  .consent { padding: 12px 14px calc(12px + env(safe-area-inset-bottom)); }
  .consent-inner { display: block; }
  .consent-h { font-size: 17px; margin-bottom: 4px; }
  .consent-p { font-size: 13.5px; line-height: 1.5; }
  .consent-actions { margin-top: 10px; }
}

/* The line that stands in for the withdrawal button when there is nothing to
   withdraw — measurement off, or nobody asked yet. */
.consent-state {
  margin: 10px 0 0; font-family: ui-monospace, monospace; font-size: 11.5px;
  line-height: 1.6; color: var(--muted);
}
.consent-state[hidden] { display: none; }
