/* RunnerLap — black and white, same principles as the app. */

:root {
  color-scheme: light;
  --bg: #f9f9f9;          /* the app's Color(white: 0.975) */
  --ink: #000;
  --muted: #6e6e73;
  --line: rgba(0, 0, 0, 0.07);
  --surface: #fff;        /* cards, chips and white buttons */
  --btn-bg: #000;         /* the solid pills: black on light, white on dark */
  --btn-fg: #fff;
  --glass: rgba(249, 249, 249, 0.86);
  --hud-bg: #000;
  --dot-idle: rgba(0, 0, 0, 0.15);
  --icon-ring: rgba(0, 0, 0, 0.06);
  --watch-ring: #1c1c1e;
  --spark-fill: rgba(0, 0, 0, 0.06);
  --spring: cubic-bezier(0.34, 1.45, 0.5, 1);

  /* the demo map */
  --m-bg: #f0f0f3; --m-bank: #e4e9e6; --m-water: #d6d9e1; --m-wave: #e8eaf0;
  --m-roof0: #f4f4f6; --m-roof1: #eeeef1; --m-roof2: #f8f8fa; --m-roof3: #e9ebf0; --m-roof4: #eef1ee;
  --m-wallE: #c3c3cc; --m-wallS: #d3d3da; --m-shadow: rgba(40, 40, 60, 0.10);
  --m-court: #e2e2e7; --m-hvac: #d6d6dc; --m-edge: #dcdce2;
  --m-lawn: #e1e8e3; --m-pond: #d6d9e1; --m-pondring: #eaf0ec; --m-pathcase: #cdd7d0; --m-path: #fff;
  --m-tree: #c9d4cd; --m-streettree: #cfd9d2;
  --m-road: #fff; --m-roadcase: #d6d6dc; --m-lane: #e6e6ea;
  --m-deck: #fff; --m-deckline: #d6d6dc; --m-rail: #bcbcc4;
  --m-label: #a0a0aa; --m-halo: #fff; --m-parklabel: #8f9d95; --m-rivlabel: #a7aab6; --m-caption: #b4b4ba;
  --m-compass-ring: #e2e2e6;
  --r-casing: #fff; --r-base: #9697a3; --r-done: #000;
  --r-mark-fill: #fff; --r-mark: #000;
  --rig: #000; --rig-out: #fff;

  --top-h: 58px;          /* the sticky header: 12px above the 34px Download pill and 12px below it, so its edge never touches the button */
}

/* Dark theme: the whole page, and a night version of the map. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0b0b0d;
  --ink: #fff;
  --muted: #9b9ba3;
  --line: rgba(255, 255, 255, 0.1);
  --surface: #17181c;
  --btn-bg: #fff;
  --btn-fg: #000;
  --glass: rgba(11, 11, 13, 0.82);
  --hud-bg: #050506;
  --dot-idle: rgba(255, 255, 255, 0.22);
  --icon-ring: rgba(255, 255, 255, 0.16);
  --watch-ring: #2a2a2f;
  --spark-fill: rgba(255, 255, 255, 0.08);

  --m-bg: #14151a; --m-bank: #16221c; --m-water: #1c2536; --m-wave: #27324a;
  --m-roof0: #2a2c33; --m-roof1: #24262c; --m-roof2: #30323a; --m-roof3: #262a35; --m-roof4: #242b27;
  --m-wallE: #0b0c0f; --m-wallS: #15161b; --m-shadow: rgba(0, 0, 0, 0.4);
  --m-court: #202228; --m-hvac: #3a3d46; --m-edge: #34363e;
  --m-lawn: #16261c; --m-pond: #1d2c44; --m-pondring: #27405f; --m-pathcase: #0f1a13; --m-path: #3b3f48;
  --m-tree: #1f3326; --m-streettree: #1e2d23;
  --m-road: #2e3038; --m-roadcase: #0a0b0e; --m-lane: #464954;
  --m-deck: #3a3d46; --m-deckline: #0a0b0e; --m-rail: #60636e;
  --m-label: #8a8d99; --m-halo: #14151a; --m-parklabel: #7fa38d; --m-rivlabel: #7587ad; --m-caption: #6a6d78;
  --m-compass-ring: #33353d;
  --r-casing: #0a0b0e; --r-base: #8f94a5; --r-done: #fff;
  --r-mark-fill: #14151a; --r-mark: #fff;
  --rig: #fff; --rig-out: #0a0b0e;
}
/* While the theme switches, ease the colours rather than snapping. */
html.theme-anim *, html.theme-anim *::before, html.theme-anim *::after {
  transition: background-color 0.35s ease, color 0.35s ease, border-color 0.35s ease, fill 0.35s ease, stroke 0.35s ease, box-shadow 0.35s ease !important;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { background: var(--bg); -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 400 16px/1.4 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* `clip` keeps stray sideways overflow out without turning the body into a scroll container, which is what can stop
     the pinned map (position: sticky) from sticking in Safari. Browsers that don't know it keep `hidden` above. */
  overflow-x: clip;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

a { color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* ---------- Header ---------- */

.top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: calc(var(--top-h) + env(safe-area-inset-top));
  padding: calc(12px + env(safe-area-inset-top)) 24px 12px;
  transition: background-color 0.25s ease, box-shadow 0.25s ease;
}
/* Once the page scrolls, the bar stays and frosts over whatever passes beneath it. */
.top.is-stuck {
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  backdrop-filter: saturate(1.4) blur(14px);
  box-shadow: 0 1px 0 var(--line);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
}

.app-icon {
  display: block;
  width: 30px;
  height: 30px;
  border-radius: 22.37%;                 /* the iOS icon corner */
  box-shadow: 0 0 0 1px var(--icon-ring), 0 2px 6px rgba(0, 0, 0, 0.14);
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  min-width: 96px;
  padding: 0 16px;
  border-radius: 17px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
}
.pill:active, .cta:active { opacity: 0.85; }

/* ---------- Buttons ---------- */

.cta {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 24px;
  border-radius: 24px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

@media (min-width: 960px) {
  :root { --top-h: 82px; }
  .top { padding: 24px 40px; }
  .wordmark { font-size: 16px; gap: 12px; }
  .app-icon { width: 34px; height: 34px; }
}

/* ---------- Intro: the logo draws itself on a white screen, then lifts away to reveal the run ---------- */

.intro { display: none; }
.has-intro { overflow: hidden; }
.has-intro .intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(28px, 6dvh, 56px);
  padding-bottom: 4dvh;
  background: var(--bg);
  transition: opacity 0.7s ease, visibility 0s linear 0.7s;
}
.has-intro .intro.is-leaving { opacity: 0; visibility: hidden; pointer-events: none; }

.intro-mark {
  width: min(72vw, 400px, 46dvh);
  transition: transform 0.9s cubic-bezier(0.4, 0, 0.2, 1);
}
.intro.is-leaving .intro-mark { transform: scale(1.12); }

/* 6% wider than the logo on every side (see PAD in site.js) so its shadow isn't clipped;
   the negative margins cancel that out so layout still sees only the logo. */
#logo {
  display: block;
  width: 112%;
  height: auto;
  margin: -6%;
}

.intro-tag {
  margin: 0;
  text-align: center;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.25em;
  line-height: 1.6;
  color: var(--muted);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.intro.is-done .intro-tag { opacity: 1; transform: none; }
.intro.is-leaving .intro-tag { opacity: 0; transition-duration: 0.3s; }
@media (min-width: 960px) { .intro-tag { font-size: 11px; } }

/* The pager sits just under the chapter text. JS sets --pager-y once, from the tallest chapter, so it never moves. The "Scroll" prompt (first screen only) lives in the window's bottom-right corner. */
.pager { display: none; }
.is-live .pager {
  position: absolute; left: 4px; top: var(--pager-y, 100%);
  display: flex; align-items: center; gap: 22px;
}
.scroll-cue {
  position: fixed;                     /* the bottom-right corner of the window, whatever the layout */
  right: calc(20px + env(safe-area-inset-right));
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 15;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  text-decoration: none;
  transition: opacity 0.35s ease;
}
.scroll-cue svg {
  flex: none;
  width: 14px; height: 14px;
  fill: none; stroke: currentColor; stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  animation: cue-bob 1.8s ease-in-out 3;          /* a few bobs, then it rests: nothing keeps moving on its own for long */
}
@keyframes cue-bob {
  0%, 100% { transform: translateY(-2px); opacity: 0.55; }
  50%      { transform: translateY(2px);  opacity: 1; }
}
.is-scrolled .scroll-cue, .is-drawing .scroll-cue { opacity: 0; pointer-events: none; }
@media (max-width: 959px) and (orientation: landscape) { .scroll-cue { display: none; } }
.journey:not(.is-live) .scroll-cue { display: none; }

/* ====================================================================================
   The run: a route plans itself and a runner follows it as you scroll.
   Two modes. `.is-live` pins the map and swaps chapters as you scroll; without it (reduced
   motion, or no script) everything simply stacks and reads top to bottom.
   ==================================================================================== */

.journey {
  position: relative;
  flex: none;
  scroll-margin-top: var(--top-h);
}

.journey-pin {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 1240px;
  margin: 0 auto;
  padding: 28px 16px 56px;
}

.journey-map {
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  aspect-ratio: 6 / 7;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 28px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.06);
}                                           /* not clipped: the runner may reach past the map; the map and panel round their own corners */
.journey-map { display: flex; flex-direction: column; --hud-h: 88px; }
.map-stage { position: relative; flex: 1 1 0; min-height: 0; }
.map-stage > svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
#map { border-radius: 28px 28px 0 0; overflow: hidden; }              /* the city is clipped to the card's rounded top */
.map-top { overflow: visible; pointer-events: none; z-index: 2; }       /* the runner is not: it may stand on, or leap over, the map's edge */

/* The run panel under the map: the app's four run figures, on black so the numbers carry. */
.hud {
  flex: none; height: var(--hud-h);
  display: flex; flex-direction: column; justify-content: center; gap: 12px;
  padding: 0 20px;
  background: var(--hud-bg); color: #fff;
  border-radius: 0 0 27px 27px;
  transition: background-color 0.3s ease;
}
.hud-progress { display: flex; align-items: center; gap: 12px; }
.hud-bar { flex: 1; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.2); overflow: hidden; }
.hud-bar i { display: block; height: 100%; width: 0; border-radius: 2px; background: #fff; }
.hud-progress b { min-width: 3.4ch; text-align: right; font-size: 12px; font-weight: 600; color: rgba(255, 255, 255, 0.7); font-variant-numeric: tabular-nums; }
.hud-grid { display: flex; justify-content: space-between; }
.hud-grid > div { display: flex; flex-direction: column; gap: 3px; padding: 0 10px; border-left: 1px solid rgba(255, 255, 255, 0.16); min-width: 0; }
.hud-grid > div:first-child { padding-left: 0; border-left: 0; }
.hud-grid > div:last-child { padding-right: 0; }
.hud-grid b { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hud-grid small { font-size: 10px; color: rgba(255, 255, 255, 0.55); white-space: nowrap; }
.hud-target label { display: flex; flex-direction: column; gap: 3px; cursor: text; }
.hud-target input {
  width: 4.1ch; padding: 0 0 1px; margin: 0 0 -2px;
  border: 0; border-bottom: 1px dashed rgba(255, 255, 255, 0.45); border-radius: 0;
  background: transparent; color: #fff; caret-color: #fff;
  font: inherit; font-size: 20px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.05;
  font-variant-numeric: tabular-nums; outline: none; -webkit-appearance: none; appearance: none;
}
.hud-target input:focus { border-bottom: 1px solid #fff; }
.hud-target small svg { width: 9px; height: 9px; margin-left: 2px; vertical-align: -1px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
/* While drawing, the panel gives its place to the drawing buttons. */
.is-drawing .hud { background: var(--surface); }
.is-drawing .hud-progress, .is-drawing .hud-grid { visibility: hidden; }

.chapters { list-style: none; margin: 0; padding: 0; }
.chapter { padding: 36px 6px; border-top: 1px solid var(--line); }
.chapter:first-child { border-top: 0; }
.chapter-dots { display: none; }

.eyebrow {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--muted);
}
.eyebrow span { color: var(--ink); margin-right: 10px; }

.chapter h3 {
  margin: 0 0 10px;
  font-size: clamp(28px, 8.6vw, 38px);
  line-height: 1.1;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.lede { margin: 0; max-width: 38ch; font-size: 16.5px; line-height: 1.48; color: var(--muted); }
/* Links inside a paragraph read as part of it: the same colour, underlined, going dark on hover. */
.lede a { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--muted); transition: text-decoration-color 0.2s ease; }
.lede a:hover, .lede a:focus-visible { text-decoration-color: var(--ink); }
.viz { margin-top: 18px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

/* Plan: the figures a planned route comes with. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  height: 40px; padding: 0 15px;
  border-radius: 20px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  font-size: 15px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.chip b { color: var(--ink); font-weight: 600; }
.chip svg { width: 16px; height: 16px; fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Together: the group and the playlist, laid out as the app's run details show them. */
.viz-together { flex-direction: column; align-items: flex-start; gap: 12px; }
.going { display: flex; align-items: center; gap: 12px; }
.dots { display: flex; }
.rdot {
  width: 32px; height: 32px; margin-left: -6px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface); color: var(--ink);
  border: 2px solid var(--ink);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.18);
  font-size: 11px; font-weight: 700;
}
.rdot:first-child { margin-left: 0; }
.going-text { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 500; color: var(--muted); }
.pl-card {
  display: flex; align-items: center; gap: 12px;
  width: 100%; max-width: 330px; padding: 10px 14px 10px 10px;
  border-radius: 16px; background: var(--surface); border: 1px solid var(--line);
}
.pl-cover {
  flex: none; width: 46px; height: 46px; border-radius: 4px;
  display: grid; place-items: center;
  background: linear-gradient(145deg, #4a4a52, #0b0b0d);
}
:root[data-theme="dark"] .pl-cover { background: linear-gradient(145deg, #7a7a85, #32323a); }
.pl-cover svg { width: 20px; height: 20px; fill: none; stroke: #fff; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pl-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pl-text b { font-size: 16px; font-weight: 600; line-height: 1.2; }
/* The scroll fills this in: two runners are out from the start, four more join (--j3..--j6), and the playlist comes on
   early (--pl). Without the script they all read as complete. */
.viz-together { --j3: 1; --j4: 1; --j5: 1; --j6: 1; --pl: 1; }
.rdot:nth-child(3) { opacity: var(--j3); transform: scale(calc(0.55 + 0.45 * var(--j3))); }
.rdot:nth-child(4) { opacity: var(--j4); transform: scale(calc(0.55 + 0.45 * var(--j4))); }
.rdot:nth-child(5) { opacity: var(--j5); transform: scale(calc(0.55 + 0.45 * var(--j5))); }
.rdot:nth-child(6) { opacity: var(--j6); transform: scale(calc(0.55 + 0.45 * var(--j6))); }
.pl-card { position: relative; }
.pl-card::after { content: ""; position: absolute; inset: -1px; border-radius: 16px; border: 1.5px solid var(--ink); opacity: var(--pl); pointer-events: none; }
.pl-sub { display: grid; }
.pl-sub small { grid-area: 1 / 1; font-size: 13px; color: var(--muted); }
.pl-sub .s0 { opacity: calc(1 - var(--pl)); }
.pl-sub .s1 { opacity: var(--pl); }
/* The levels beside the song: still until the playlist comes on, then moving like music playing. */
.pl-wave { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 3px; height: 20px; opacity: var(--pl); }
.pl-wave i { display: block; width: 3px; height: 100%; border-radius: 2px; background: var(--ink); transform: scaleY(var(--h, 0.5)); }
.pl-wave i:nth-child(1) { --h: 0.35; }
.pl-wave i:nth-child(2) { --h: 0.7; }
.pl-wave i:nth-child(3) { --h: 1; }
.pl-wave i:nth-child(4) { --h: 0.55; }
.pl-wave i:nth-child(5) { --h: 0.3; }
.is-playing .pl-wave i { animation: music 0.9s ease-in-out infinite; }
.is-playing .pl-wave i:nth-child(1) { animation-duration: 0.75s; animation-delay: -0.1s; }
.is-playing .pl-wave i:nth-child(2) { animation-duration: 0.55s; animation-delay: -0.4s; }
.is-playing .pl-wave i:nth-child(3) { animation-duration: 0.95s; animation-delay: -0.2s; }
.is-playing .pl-wave i:nth-child(4) { animation-duration: 0.62s; animation-delay: -0.5s; }
.is-playing .pl-wave i:nth-child(5) { animation-duration: 0.82s; animation-delay: -0.3s; }
@keyframes music { 0%, 100% { transform: scaleY(0.2); } 35% { transform: scaleY(1); } 60% { transform: scaleY(0.5); } 80% { transform: scaleY(0.85); } }

/* The group on the map, in the same round markers: they run a little behind you while this chapter is up. */
.pk circle { fill: var(--surface); stroke: var(--ink); stroke-width: 2.4; }
.pk text { fill: var(--ink); font: 700 10px -apple-system, BlinkMacSystemFont, "SF Pro Text", Arial, sans-serif; text-anchor: middle; dominant-baseline: central; }
.pk { filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25)); }

/* Smartwatch: an Apple Watch showing the app's run screen. Everything is in em, so one font-size sizes the whole watch. */
.viz-watch { flex-wrap: nowrap; }
.watch {
  --ink-w: #fff; --dim-w: #a1a1a6;
  position: relative; flex: none; font-size: 9.5px;
  width: 12em; height: 14.4em; margin-bottom: 1.1em;      /* room for the lower strap, so it doesn't run into the dots */
}
.w-body {
  position: absolute; inset: 0; border-radius: 3.5em;
  background: linear-gradient(150deg, #55555b 0%, #26262a 45%, #3b3b40 100%);
  box-shadow: 0 .9em 2.4em rgba(0, 0, 0, 0.28), inset 0 0 0 .12em rgba(255, 255, 255, 0.16), inset 0 .12em .25em rgba(255, 255, 255, 0.22);
}
.w-screen {
  position: absolute; inset: .55em; border-radius: 3em; overflow: hidden;
  background: #000; color: var(--ink-w);
  padding: 1.1em .95em .9em; display: flex; flex-direction: column; justify-content: center; gap: .5em;
  box-shadow: inset 0 0 0 .1em rgba(255, 255, 255, 0.07);
}
.w-screen::after { content: ""; position: absolute; inset: 0; background: linear-gradient(125deg, rgba(255, 255, 255, 0.11), transparent 40%); pointer-events: none; }
.w-crown, .w-btn { position: absolute; background: linear-gradient(#66666c, #2a2a2e); box-shadow: inset 0 0 0 .08em rgba(255, 255, 255, 0.16); }
.w-crown { right: -.55em; top: 3.3em; width: 1em; height: 2.7em; border-radius: .5em; }
.w-btn { right: -.4em; top: 7.2em; width: .7em; height: 1.9em; border-radius: .35em; }
.w-strap { position: absolute; left: 1.5em; right: 1.5em; height: 2.2em; z-index: -1; background: linear-gradient(#2c2c30, #1b1b1d); }
.w-top { top: -1.1em; border-radius: .9em .9em 0 0; -webkit-mask-image: linear-gradient(to top, #000 35%, transparent); mask-image: linear-gradient(to top, #000 35%, transparent); }
.w-bot { bottom: -1.1em; border-radius: 0 0 .9em .9em; -webkit-mask-image: linear-gradient(to bottom, #000 35%, transparent); mask-image: linear-gradient(to bottom, #000 35%, transparent); }

/* The turn card, as the watch app draws it: it only appears once a turn is close, light at first and solid black right at the turn. */
.w-card {
  display: flex; align-items: center; gap: .45em; overflow: hidden;
  max-height: 4.2em; padding: .5em .6em; border-radius: 1.2em;
  background: #e9e9ec; color: #000;
  transition: max-height 0.35s ease, padding 0.35s ease, margin 0.35s ease, opacity 0.25s ease, background-color 0.25s ease, color 0.25s ease;
}
.watch[data-state="far"] .w-card { max-height: 0; padding-top: 0; padding-bottom: 0; margin-bottom: -.5em; opacity: 0; }
.watch[data-state="now"] .w-card { background: #000; color: #fff; box-shadow: inset 0 0 0 .12em rgba(255, 255, 255, 0.5); }
.w-turn { flex: none; width: 2.05em; height: 2.05em; fill: none; stroke: currentColor; stroke-width: 2.3; stroke-linecap: round; stroke-linejoin: round; }
.watch[data-dir="left"] .w-turn { transform: scaleX(-1); }
.w-text { display: flex; flex-direction: column; min-width: 0; }
.w-text b { font-size: 1.65em; font-weight: 700; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; }
.w-text small { font-size: .98em; font-weight: 500; line-height: 1.15; white-space: nowrap; }

.w-prog { display: flex; align-items: center; gap: .55em; font-size: .95em; color: var(--dim-w); font-variant-numeric: tabular-nums; }
.w-bar { flex: 1; height: .45em; border-radius: 1em; background: #3a3a3c; overflow: hidden; }
.w-bar i { display: block; height: 100%; width: 0; border-radius: 1em; background: #fff; }
.w-dist { font-size: 2em; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.w-dist span { font: inherit; }
.w-stats { display: flex; justify-content: space-between; gap: .6em; }
.w-stats span { display: flex; flex-direction: column; }
.w-stats b { font-size: 1.45em; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
.w-stats small { font-size: .92em; color: var(--dim-w); }

/* The round running watch, in the style of the running watches from the big GPS brands: a coloured polymer case that matches its
   strap, a darker ring round a big flat screen (no tick marks), small buttons on the edge, and an accent band on the strap.
   It shows the same run as the other two devices. */
.viz-watch { align-items: center; gap: 2em; font-size: 9.5px; }
.watch.garmin { width: 12.4em; height: 12.4em; }
.g-body {
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 30% 20%, #e4e0d6 0%, #c3beb3 52%, #a7a298 100%);
  box-shadow: 0 .9em 2.4em rgba(0, 0, 0, 0.26), inset 0 0 0 .1em rgba(255, 255, 255, 0.5), inset 0 -.15em .3em rgba(0, 0, 0, 0.12);
}
/* the ring round the screen */
.g-bezel {
  position: absolute; inset: .7em; border-radius: 50%;
  background: linear-gradient(145deg, #55555c, #232327 60%, #333338);
  box-shadow: 0 .1em .3em rgba(0, 0, 0, 0.35), inset 0 0 0 .08em rgba(255, 255, 255, 0.14);
}
.g-screen {
  position: absolute; inset: 1.55em; border-radius: 50%; overflow: hidden;
  background: #000; color: #fff;
  display: flex; align-items: center; justify-content: center; text-align: center;
  box-shadow: 0 0 0 .1em #050506;
}
.g-screen::after { content: ""; position: absolute; inset: 0; background: linear-gradient(125deg, rgba(255, 255, 255, 0.1), transparent 42%); pointer-events: none; }
/* the progress ring runs round the edge of the screen itself */
.g-ring { position: absolute; inset: .2em; width: calc(100% - .4em); height: calc(100% - .4em); }
.g-ring circle { fill: none; stroke-width: 3.6; }
.g-ring-bg { stroke: #26262a; }
.g-ring-fg { stroke: #fff; stroke-linecap: round; stroke-dasharray: 292.2; stroke-dashoffset: 292.2; }
.g-info, .g-turn { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .2em; padding: 0 1.1em; transition: opacity 0.3s ease; }
.g-turn { opacity: 0; padding-bottom: .4em; }
.watch[data-state="soon"] .g-info, .watch[data-state="now"] .g-info { opacity: 0; }
.watch[data-state="soon"] .g-turn, .watch[data-state="now"] .g-turn { opacity: 1; }
.g-turn .w-turn { width: 2.4em; height: 2.4em; }
.g-turn b { font-size: 1.95em; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.g-turn small { font-size: .98em; font-weight: 500; color: #d0d0d4; }
.watch.garmin[data-state="now"] .g-screen { box-shadow: 0 0 0 .1em #050506, inset 0 0 0 .3em #fff; }
.watch.garmin .w-dist { font-size: 1.6em; }
.g-stats { display: flex; gap: .85em; margin-top: .2em; }
.g-stats span { display: flex; flex-direction: column; align-items: center; }
.g-stats b { font-size: 1.08em; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; }
.g-stats small { font-size: .78em; color: var(--dim-w); }
/* five buttons on the edge of the case: three on the left, two on the right, small and slightly raised */
.g-b {
  position: absolute; left: 50%; top: 50%; width: 1.5em; height: .75em; border-radius: .3em;
  background: linear-gradient(90deg, #5c5c63, #2b2b30 55%, #45454b);
  box-shadow: 0 0 0 .06em rgba(0, 0, 0, 0.3), inset 0 0 0 .06em rgba(255, 255, 255, 0.16);
  transform: translate(-50%, -50%) rotate(var(--a)) translateY(-6.2em);
}
/* a silicone strap in the case colour, with a darker band near the case like the keeper loop */
.g-strap {
  position: absolute; left: 50%; width: 5.2em; height: 4em; transform: translateX(-50%); z-index: -1;
  background: linear-gradient(90deg, #a7a298, #c9c4ba 50%, #a7a298);
}
.g-strap::before { content: ""; position: absolute; left: 0; right: 0; height: .4em; background: linear-gradient(90deg, #2d2d32, #4a4a50 50%, #2d2d32); }
.g-top { top: -2.4em; border-radius: 1em 1em 0 0; -webkit-mask-image: linear-gradient(to top, #000 45%, transparent); mask-image: linear-gradient(to top, #000 45%, transparent); }
.g-top::before { bottom: 1.3em; }
.g-bot { bottom: -2.4em; border-radius: 0 0 1em 1em; -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent); mask-image: linear-gradient(to bottom, #000 45%, transparent); }
.g-bot::before { top: 1.3em; }

/* The phone: the top of the app's run screen, cropped and fading out below the figures. */
.phone {
  position: relative; flex: none; font-size: 9.5px; width: 11.8em; height: 19em; margin-bottom: 1.1em;
  border-radius: 2.8em 2.8em 0 0; padding: .5em .5em 0;
  background: linear-gradient(150deg, #4c4c52, #232326 50%, #38383d);
  box-shadow: 0 .9em 2.4em rgba(0, 0, 0, 0.28), inset 0 0 0 .12em rgba(255, 255, 255, 0.15);
  -webkit-mask-image: linear-gradient(to bottom, #000 88%, transparent); mask-image: linear-gradient(to bottom, #000 88%, transparent);
}
.p-screen { position: relative; height: 100%; border-radius: 2.4em 2.4em 0 0; overflow: hidden; background: #fff; color: #000; }
.p-map { position: absolute; left: 0; right: 0; top: 0; height: 9.2em; background: #e4e4e7; }
.p-map svg { display: block; width: 100%; height: 100%; }
.p-grid { fill: none; stroke: #fff; stroke-width: 1.6; }
.p-base, .p-done { fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2.6; }
.p-base { stroke: #a2a2aa; }
.p-done { stroke: #000; stroke-dasharray: 0 400; }
.p-dot { fill: #000; stroke: #fff; stroke-width: 1.4; }
.p-island { position: absolute; top: .55em; left: 50%; width: 3.2em; height: .95em; margin-left: -1.6em; border-radius: 1em; background: #000; z-index: 3; }
.p-card {
  position: absolute; z-index: 2; left: .6em; right: .6em; top: 1.9em;
  display: flex; align-items: center; gap: .55em; padding: .55em .7em; border-radius: 1.3em;
  background: #fff; color: #000; box-shadow: 0 .3em 1em rgba(0, 0, 0, 0.14);
  transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease;
}
.p-arrow { flex: none; width: 2em; height: 2em; fill: none; stroke: currentColor; stroke-width: 2.3; stroke-linecap: round; stroke-linejoin: round; }
.p-arrow-go { display: none; }
.phone[data-state="after"] .p-arrow-turn { display: none; }
.phone[data-state="after"] .p-arrow-go { display: block; }
.phone[data-dir="left"] .p-arrow-turn { transform: scaleX(-1); }
.p-text { display: flex; flex-direction: column; min-width: 0; }
.p-text b { font-size: 1.6em; font-weight: 600; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; }
.p-text > span { font-size: 1.05em; font-weight: 500; line-height: 1.2; white-space: nowrap; }
.p-text small { font-size: .82em; color: #6e6e73; white-space: nowrap; }
.phone[data-state="soon"] .p-card, .phone[data-state="now"] .p-card { background: #000; color: #fff; box-shadow: 0 .4em 1.4em rgba(0, 0, 0, 0.32); }
.phone[data-state="soon"] .p-text small, .phone[data-state="now"] .p-text small { color: rgba(255, 255, 255, 0.65); }
.phone[data-state="now"] .p-card { animation: nowpulse 0.5s ease-in-out infinite alternate; }
@keyframes nowpulse { from { transform: scale(1); } to { transform: scale(1.03); } }
.p-panel { position: absolute; left: 0; right: 0; top: 9.2em; bottom: 0; padding: .8em .9em 0; background: #fff; border-radius: 1.4em 1.4em 0 0; }
.p-panel .w-prog { color: #6e6e73; }
.p-panel .w-bar { background: #e4e4e7; }
.p-panel .w-bar i { background: #000; }
.p-stats { display: grid; grid-template-columns: 1fr 1fr; gap: .55em .6em; margin-top: .65em; }
.p-stats span { display: flex; flex-direction: column; min-width: 0; }
.p-stats b { font-size: 1.55em; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.p-stats small { order: 2; font-size: .8em; color: #6e6e73; white-space: nowrap; }

/* The tap on the wrist when the turn arrives: a quick buzz of the whole watch. */
.watch.buzz { animation: buzz 0.55s linear; }
@keyframes buzz { 0%, 100% { transform: translateX(0); } 12% { transform: translateX(-2px) rotate(-1deg); } 24% { transform: translateX(2px) rotate(1deg); } 36% { transform: translateX(-2px) rotate(-1deg); } 48% { transform: translateX(2px) rotate(1deg); } 62% { transform: translateX(-1px); } 78% { transform: translateX(1px); } }

/* Your running, organized: the app's log, as a calendar of planned (grey) and completed (black) runs and the run for the
   day you pick. Everything is in em, so one font-size sizes the lot. */
.viz-log { display: block; font-size: 9.5px; max-width: 34em; }
.cal-head { font-size: 1.5em; font-weight: 500; text-align: center; margin-bottom: .5em; }
.cal-wk, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-wk span { text-align: center; font-size: 1.2em; color: var(--muted); }
.cal-grid { margin-top: .3em; row-gap: .1em; }
.cal-day { display: flex; flex-direction: column; align-items: center; gap: .25em; padding: 0; border: 0; background: none; color: var(--ink); cursor: default; font: inherit; font-size: 1.45em; }
.cal-day.has-run { cursor: pointer; }
.cal-n { display: grid; place-items: center; width: 2.35em; height: 2.35em; border-radius: 50%; font-size: 1em; font-weight: 400; }
.cal-day.is-today .cal-n { box-shadow: inset 0 0 0 .12em var(--ink); }
.cal-day.is-sel .cal-n { background: var(--ink); color: var(--bg); font-weight: 600; box-shadow: none; }
.cal-dot { width: .38em; height: .38em; border-radius: 50%; background: var(--dot-idle); opacity: 0; transform: scale(.3); transition: opacity .35s ease, transform .4s var(--spring), background-color .3s ease; }
.cal-day.has-run .cal-dot { opacity: 1; transform: none; background: #bfbfc4; }
.cal-day.has-run.is-done .cal-dot { background: var(--ink); }
.cal-sel { margin-top: 1em; }
.cal-date { display: block; font-size: 1em; font-weight: 500; letter-spacing: .25em; color: var(--muted); margin-bottom: .5em; }
.log-row { display: flex; align-items: center; gap: 1.2em; }
.log-thumb { flex: none; width: 5.2em; height: 5.2em; padding: .5em; border-radius: 1.1em; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); fill: none; stroke: var(--ink); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.log-text { display: flex; flex-direction: column; gap: .2em; min-width: 0; flex: 1; }
.log-text b { font-size: 1.5em; font-weight: 600; line-height: 1.15; }
.log-text span { font-size: 1.3em; color: var(--muted); }
.log-text small { font-size: 1.2em; color: var(--muted); }
.cal-legend { display: flex; flex-wrap: wrap; gap: .5em 1.6em; margin-top: 1em; font-size: 1.15em; color: var(--muted); }
.cal-legend span { display: inline-flex; align-items: center; gap: .5em; }
.cal-legend i { display: inline-block; border-radius: 50%; }
.lg-done { width: .75em; height: .75em; background: var(--ink); }
.lg-plan { width: .75em; height: .75em; background: #bfbfc4; }
.lg-today { width: 1em; height: 1em; box-shadow: inset 0 0 0 .12em var(--ink); }

/* Progress: live figures and the climb. */
.viz-progress { display: block; }
.stats { display: grid; grid-template-columns: repeat(4, auto); justify-content: start; gap: 8px 22px; }
.stats div { display: flex; flex-direction: column; gap: 2px; }
.stats b { font-size: 21px; font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.stats small { font-size: 9.5px; letter-spacing: 0.2em; color: var(--muted); }
/* While drawing, the pace figure is a field the visitor can change; the time follows it. */
.stats .stat-in { display: none; width: 4.1ch; padding: 0 0 1px; margin: 0 0 -2px; border: 0; border-bottom: 1px dashed var(--muted); border-radius: 0; background: transparent; color: inherit; caret-color: currentColor; font: inherit; font-size: 21px; font-weight: 600; letter-spacing: -0.01em; line-height: inherit; font-variant-numeric: tabular-nums; outline: none; -webkit-appearance: none; appearance: none; }
.stats .stat-in:focus { border-bottom: 1px solid currentColor; }
.stats .edit-ic { display: none; width: 9px; height: 9px; margin-left: 2px; vertical-align: -1px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.is-drawing .stats .stat-in { display: block; }
.is-drawing .stats .edit-ic { display: inline; }
.is-drawing .stats [data-v="pace2"] { display: none; }
.spark { display: block; width: 100%; max-width: 300px; height: auto; margin-top: 12px; overflow: visible; }
.spark-area { fill: var(--spark-fill); stroke: none; }
.spark-line { fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.spark-dot { fill: var(--ink); stroke: var(--bg); stroke-width: 2; }

.cta.cta-inline {
  position: static; transform: none; opacity: 1; pointer-events: auto;
  display: inline-flex; min-width: 190px;
}
/* Where to get it: the app's icon and name, then a button for each platform; Android's isn't live yet, so it is quiet and says so. */
.viz-free { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.get { display: flex; align-items: center; gap: 14px; }
.get-icon { display: block; flex: none; width: 44px; height: 44px; border-radius: 22.37%; box-shadow: 0 0 0 1px var(--icon-ring), 0 2px 8px rgba(0, 0, 0, 0.14); }
.get-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.get-text b { font-size: 17px; font-weight: 600; line-height: 1.2; }
.get-text span { font-size: 14px; line-height: 1.3; color: var(--muted); }
.get-btns { display: flex; flex-wrap: wrap; gap: 10px; }

/* ---- the map ---- */
/* The route runs down the middle of a street (streets are 14 wide), so it is slimmer than before. */
.route-casing { fill: none; stroke: var(--r-casing); stroke-width: 12; stroke-linecap: round; stroke-linejoin: round; }
.route-base   { fill: none; stroke: var(--r-base); stroke-width: 7.5; stroke-linecap: round; stroke-linejoin: round; }
.route-done   { fill: none; stroke: var(--r-done); stroke-width: 7.5; stroke-linecap: round; stroke-linejoin: round; }
.mk { opacity: 0; }
.start-ring { fill: var(--r-mark-fill); stroke: var(--r-mark); stroke-width: 3; }
.start-dot { fill: var(--r-mark); }
.flag-frame { fill: var(--r-mark-fill); stroke: var(--r-mark); stroke-width: 3; }
.flag-b { fill: var(--r-mark); }
.pen-ring { fill: var(--r-mark-fill); stroke: var(--r-mark); stroke-width: 3; }
.pen-dot { fill: var(--r-mark); }
#runner { filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.18)); }
#rigOut path, #rigOut circle { fill: none; stroke: var(--rig-out); stroke-linecap: round; stroke-linejoin: round; }
#rig path { fill: none; stroke: var(--rig); stroke-linecap: round; stroke-linejoin: round; }
#rig circle { fill: var(--rig); }
#rigOut circle { fill: var(--rig-out); }

/* ---- compass and the light / dark switch ---- */
/* Like Apple Maps' compass: a round button with fine ticks around the edge, N at the top, and a needle whose
   north half is red. */
.compass-shadow { fill: rgba(0, 0, 0, 0.12); }
.compass-bg { fill: var(--surface); stroke: var(--m-compass-ring); stroke-width: 0.8; }
.compass-tick { stroke: var(--muted); stroke-width: 0.9; stroke-linecap: round; opacity: 0.55; }
.compass-tick.is-major { stroke-width: 1.3; opacity: 0.85; }
.compass-t { fill: var(--ink); letter-spacing: 0.2px; }
.compass-north { fill: #ff3b30; }
.compass-south { fill: var(--muted); opacity: 0.5; }
/* A two-way switch that shows the sun and the moon together; a thumb slides under whichever is on. It is the same
   height as the draw button and sits on the same line, so the two line up. */
.theme-toggle {
  --slot: 28px;
  position: absolute; top: 14px; left: 14px; z-index: 3;
  display: grid; grid-template-columns: var(--slot) var(--slot); place-items: center;
  width: calc(var(--slot) * 2 + 6px); height: calc(var(--slot) + 6px); padding: 2px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--muted);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: opacity 0.3s ease;
}
.tt-thumb {
  position: absolute; top: 2px; left: 2px;
  width: var(--slot); height: var(--slot); border-radius: 50%;
  background: var(--btn-bg);
  transition: transform 0.3s cubic-bezier(0.3, 0.9, 0.3, 1);
}
:root[data-theme="dark"] .tt-thumb { transform: translateX(var(--slot)); }
.theme-toggle svg {
  position: relative; z-index: 1;
  width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  transition: color 0.3s ease;
}
.theme-toggle .i-sun { color: var(--btn-fg); }                                   /* light is on */
:root[data-theme="dark"] .theme-toggle .i-sun { color: var(--muted); }
:root[data-theme="dark"] .theme-toggle .i-moon { color: var(--btn-fg); }          /* dark is on */
.theme-toggle:active .tt-thumb { transform: scale(0.94); }
:root[data-theme="dark"] .theme-toggle:active .tt-thumb { transform: translateX(var(--slot)) scale(0.94); }
.is-drawing .theme-toggle, .is-live:not(.at-plan) .theme-toggle { opacity: 0; pointer-events: none; }      /* it shows only alongside Draw / Redraw */
@media (min-width: 960px) { .theme-toggle { --slot: 42px; top: 20px; left: 20px; } .theme-toggle svg { width: 20px; height: 20px; } }

/* ---- try it: draw your own route on the demo map ---- */
.journey-map { position: relative; }
.map-label {
  position: absolute; left: 16px; bottom: calc(var(--hud-h) + 10px);
  font-size: 9px; font-weight: 500; letter-spacing: 0.25em; text-transform: uppercase;
  color: var(--m-caption); pointer-events: none;
}

/* The draw button sits on the map, at the top, where nothing else is. */
.map-actions {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  z-index: 3; display: flex; align-items: center; gap: 6px;
  transition: opacity 0.3s ease;
}
.try {
  display: inline-flex; align-items: center; gap: 8px;
  height: 42px; padding: 0 18px 0 16px;
  border: 0; border-radius: 21px;
  background: var(--btn-bg); color: var(--btn-fg);
  font: inherit; font-size: 15px; font-weight: 600; white-space: nowrap; cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.try svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.try:active { opacity: 0.85; }
.reset {
  height: 42px; padding: 0 16px; border: 1px solid var(--line); border-radius: 21px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
}
.is-live:not(.at-plan) .map-actions { opacity: 0; pointer-events: none; }
/* Small screens: the draw button shrinks to a compact pill in the top-right corner (and the decorative compass
   makes way for it), leaving the middle of the map clear. */
@media (max-width: 959px) {
  .map-actions { left: auto; right: 12px; top: 12px; transform: none; gap: 6px; }
  .try { height: 34px; padding: 0 14px 0 12px; gap: 6px; font-size: 13px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.16); }
  .try svg { width: 14px; height: 14px; }
  .try .more { display: none; }
  .reset { height: 34px; padding: 0 12px; font-size: 13px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); }
  #compass { display: none; }
  .theme-toggle { --slot: 28px; top: 12px; left: 12px; }
  .theme-toggle svg { width: 16px; height: 16px; }
}

/* With a mouse you can also just drag on the map. */
@media (hover: hover) and (pointer: fine) { .at-plan #map { cursor: crosshair; } }

.map-ui { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.map-hint {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  width: max-content; max-width: calc(100% - 32px); margin: 0; padding: 9px 16px;
  border-radius: 18px; background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
  text-align: center;
}
.map-hint b { font-size: 14px; font-weight: 600; }
.map-hint span { font-size: 12px; color: var(--muted); }
.map-tools { position: absolute; left: 0; right: 0; bottom: 14px; display: flex; justify-content: center; gap: 8px; }
.tool {
  pointer-events: auto; height: 40px; min-width: 76px; padding: 0 18px;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
}
.tool.primary { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }
.tool:disabled { opacity: 0.35; cursor: default; }
.tool:active:not(:disabled) { transform: scale(0.97); }
/* Small screens: while drawing, nothing sits on the map. The guidance moves down into the panel under it, as
   one line above the Clear / Cancel / Done buttons. */
@media (max-width: 959px) {
  .map-hint {
    top: auto; bottom: calc(8px + 36px + 8px); left: 0; right: 0; transform: none;
    width: auto; max-width: none; padding: 0 12px;
    flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 0 8px;
    background: transparent; border: 0; border-radius: 0; box-shadow: none;
  }
  .map-hint b { font-size: 13.5px; }
  .map-hint span { font-size: 12px; }
  .map-tools { bottom: 8px; }
  .tool { height: 36px; min-width: 72px; padding: 0 16px; font-size: 13.5px; box-shadow: none; }
}

/* Author display rules must not beat the `hidden` attribute. */
[hidden] { display: none !important; }
.is-drawing .journey-map { box-shadow: 0 0 0 2px var(--ink), 0 12px 40px rgba(0, 0, 0, 0.12); }
.is-drawing .map-label, .is-drawing .map-actions { opacity: 0; pointer-events: none; }
.is-drawing #map { touch-action: none; cursor: crosshair; }

/* ---- live: the map pins and chapters swap as you scroll ---- */
.journey.is-live { height: 540vh; }
.is-live .journey-pin {
  z-index: 30;                        /* above the header, so the runner can reach over it */
  position: sticky;
  top: calc(var(--top-h) + env(safe-area-inset-top));
  height: calc(100vh - var(--top-h) - env(safe-area-inset-top));
  height: calc(100dvh - var(--top-h) - env(safe-area-inset-top));
  gap: 12px;
  padding: 12px 16px 14px;
}
.is-live .journey-map { flex: 1 1 0; min-height: 0; max-width: none; aspect-ratio: auto; margin: 0; }
.is-live .journey-copy { flex: none; position: relative; display: flex; flex-direction: column; gap: 14px; padding-bottom: 44px; }
.is-live .chapters { display: grid; align-items: start; }
.is-live .chapter {
  grid-area: 1 / 1; padding: 4px 4px 0; border: 0;
  opacity: 0; transform: translateY(14px); pointer-events: none;
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.is-live .chapter.is-active { opacity: 1; transform: none; pointer-events: auto; }
.is-live .chapter-dots { display: flex; align-items: center; gap: 11px; }
.chapter-dots button {
  position: relative; width: 10px; height: 10px; padding: 0; border: 0; border-radius: 5px;
  background: var(--dot-idle); cursor: pointer;
  transition: width 0.3s ease, background-color 0.3s ease;
}
.chapter-dots button::after { content: ""; position: absolute; inset: -12px -6px; }      /* a generous tap area around each dot */
.chapter-dots button[aria-current="true"] { width: 32px; background: var(--ink); }

@media (max-height: 740px) {
  .chapter h3 { font-size: clamp(25px, 7.2vw, 30px); }
  .lede { font-size: 15px; }
  .viz { margin-top: 12px; }
  .chip { height: 36px; }
  .journey-map { --hud-h: 80px; }
  .hud { gap: 9px; }
  .hud-grid b { font-size: 17px; }
  .hud-target input { font-size: 17px; }
  .watch, .phone { font-size: 8.4px; }
  .viz-log { font-size: 8.4px; }
}

/* Short phones (an iPhone SE, say): tighter type so the map keeps room. */
@media (max-height: 680px) and (max-width: 959px) {
  .chapter h3 { font-size: clamp(22px, 6.4vw, 26px); margin-bottom: 6px; }
  .eyebrow { margin-bottom: 5px; font-size: 11px; }
  .lede { font-size: 13.5px; line-height: 1.4; }
  .viz { margin-top: 8px; gap: 8px; }
  .chip { height: 32px; padding: 0 11px; font-size: 13px; }
  .journey-map { --hud-h: 66px; }
  .hud { gap: 6px; padding: 0 16px; }
  .hud-grid b { font-size: 15px; }
  .hud-target input { font-size: 16px; }
  .hud-grid small { font-size: 9px; }
  .watch, .phone { font-size: 7.3px; }
  .viz-log { font-size: 7.3px; }
  .cal-legend { display: none; }
  .is-live .journey-pin { gap: 8px; }
  .is-live .journey-copy { gap: 8px; padding-bottom: 36px; }
}

@media (min-width: 960px) {
  .chapter-dots button { width: 12px; height: 12px; border-radius: 6px; }
  .chapter-dots button[aria-current="true"] { width: 38px; }
  .is-live .chapter-dots { gap: 13px; }
  .journey-pin { padding: 48px 40px 72px; }
  .chapter h3 { font-size: clamp(38px, 4.1vw, 60px); margin-bottom: 14px; }
  .eyebrow { font-size: 13px; margin-bottom: 14px; }
  .lede { font-size: clamp(18px, 1.55vw, 21px); max-width: 34ch; }
  .viz { margin-top: 28px; gap: 12px; }
  .chip { height: 46px; padding: 0 20px; font-size: 17px; gap: 9px; }
  .chip svg { width: 18px; height: 18px; }
  .map-actions { top: 20px; }
  .scroll-cue { font-size: 11.5px; right: calc(32px + env(safe-area-inset-right)); bottom: calc(28px + env(safe-area-inset-bottom)); }
  .scroll-cue svg { width: 15px; height: 15px; }
  .try, .reset { height: 48px; font-size: 16px; border-radius: 24px; }
  .try { padding: 0 24px 0 20px; }
  .rdot { width: 40px; height: 40px; font-size: 12px; }
  .going-text { font-size: 15px; }
  .pl-card { max-width: 380px; padding: 12px 18px 12px 12px; }
  .pl-cover { width: 56px; height: 56px; }
  .pl-cover svg { width: 24px; height: 24px; }
  .stats b, .stats .stat-in { font-size: 30px; }
  .stats small { font-size: 11px; }
  .watch, .phone { font-size: 10.6px; }
  .viz-log { font-size: 10.4px; }
  .journey-map { --hud-h: 112px; }
  .cta.cta-inline { height: 56px; min-width: 220px; font-size: 17px; border-radius: 28px; }
  .hud { padding: 0 26px; gap: 14px; }
  .hud-grid b { font-size: 25px; }
  .hud-target input { font-size: 25px; }
  .hud-grid small { font-size: 12px; }
  .hud-grid > div { padding: 0 18px; }
  .hud-grid > div:first-child { padding-left: 0; }
  .hud-grid > div:last-child { padding-right: 0; }

  .is-live .journey-pin {
    flex-direction: row;
    align-items: stretch;
    gap: clamp(40px, 5vw, 80px);
    padding: 20px 40px 32px;
  }
  .is-live .journey-copy { flex: 0 0 min(600px, 54%); justify-content: center; }
  .is-live .chapter { padding: 0; }
}

/* Landscape phones: too short to stack the text over the map, too narrow for the desktop type. Put the
   text beside the map instead, in smaller type. */
@media (max-width: 959px) and (orientation: landscape) and (max-height: 560px) {
  .is-live .journey-pin { flex-direction: row; align-items: stretch; gap: 22px; padding: 12px 22px 12px; }
  .is-live .journey-copy { flex: 0 0 46%; justify-content: center; }
  .is-live .chapter { padding: 0; }
  .chapter h3 { font-size: 21px; margin-bottom: 6px; }
  .eyebrow { margin-bottom: 6px; }
  .lede { font-size: 13px; line-height: 1.42; }
  .viz { margin-top: 10px; gap: 8px; }
  .chip { height: 30px; padding: 0 11px; font-size: 12.5px; }
  .rdot { width: 26px; height: 26px; font-size: 9px; }
  .pl-cover { width: 34px; height: 34px; }
  .pl-text b { font-size: 13px; }
  .pl-sub small { font-size: 11px; }
  .watch, .phone { font-size: 7.4px; }
  .viz-log { font-size: 7.2px; }
  .cal-legend { display: none; }
  .stats b, .stats .stat-in { font-size: 17px; }
  .stats { gap: 6px 16px; }
  .spark { max-width: 220px; margin-top: 8px; }
  .cta.cta-inline { height: 44px; min-width: 160px; font-size: 14px; }
  .journey-map { --hud-h: 62px; }
  .hud { gap: 6px; padding: 0 14px; }
  .hud-grid b { font-size: 14px; }
  .hud-target input { font-size: 16px; }
}

/* Narrow phones, and desktop windows where the map card is slim: a little tighter so all four figures fit. */
@media (max-width: 349px) {
  .hud { padding: 0 12px; }
  .hud-grid > div { padding: 0 6px; }
  .hud-grid > div:first-child { padding-left: 0; }
  .hud-grid > div:last-child { padding-right: 0; }
  .hud-grid b { font-size: 14px; }
  .hud-target input { font-size: 16px; width: 3.9ch; }
  .hud-grid small { font-size: 8.5px; }
  .hud-target small svg { display: none; }
}
@media (min-width: 960px) and (max-width: 1199px) {
  .hud { padding: 0 20px; }
  .hud-grid > div { padding: 0 9px; }
  .hud-grid > div:first-child { padding-left: 0; }
  .hud-grid > div:last-child { padding-right: 0; }
  .hud-grid b { font-size: 19px; }
  .hud-target input { font-size: 19px; }
  .hud-grid small { font-size: 10.5px; }
}

/* The shortest panels (66px and 62px): slightly smaller buttons so the guidance line still fits inside. */
@media (max-width: 959px) and (max-height: 680px) {
  .tool { height: 32px; min-width: 66px; padding: 0 14px; font-size: 13px; }
  .map-hint { bottom: calc(6px + 32px + 5px); }
  .map-hint b { font-size: 13px; }
  .map-hint span { font-size: 11.5px; }
  .map-tools { bottom: 6px; }
}
@media (max-width: 959px) and (orientation: landscape) and (max-height: 560px) {
  .tool { height: 30px; min-width: 62px; padding: 0 12px; font-size: 12.5px; }
  .map-hint { bottom: calc(5px + 30px + 4px); }
  .map-tools { bottom: 5px; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-cue svg, .is-playing .pl-wave i, .phone .p-card { animation: none !important; }
}

/* On a phone-width screen the three devices shrink together so they stay on one row. */
@media (max-width: 440px) and (min-height: 681px) {
  .viz-watch { gap: 1.6em; font-size: 7.6px; }
  .watch, .phone { font-size: 7.6px; }
  .viz-log { font-size: 8px; }
}

/* Shorter screens keep the phone cropped higher up, so the map keeps its room. */
@media (max-width: 440px) and (min-height: 681px) { .phone { height: 17em; } }
@media (max-height: 740px) { .phone { height: 15.4em; } }
@media (max-width: 959px) and (orientation: landscape) and (max-height: 560px) { .phone { height: 14.6em; } }

/* On short screens the calendar tightens: no month title, no legend, smaller days. */
@media (max-height: 740px), (max-width: 440px) {
  .cal-head, .cal-legend { display: none; }
  .cal-n { width: 2.1em; height: 2.1em; }
  .log-thumb { width: 4.4em; height: 4.4em; }
  .cal-sel { margin-top: .6em; }
}

/* ---- Wherever the text sits under the map (any window under 960 wide, phones and narrow browsers alike): one type scale for every chapter, so the room is taken from the words and not from the map. ----
   This comes last so it holds whatever the screen's height; the long paragraphs and the figures under them all step down
   together instead of the map being squeezed to make room. */
@media (max-width: 959px) and (min-height: 561px) {
  .chapter h3 { font-size: clamp(22px, 2.6vw + 10px, 32px); margin-bottom: 6px; }
  .eyebrow { margin-bottom: 5px; font-size: 11px; }
  .lede { font-size: clamp(13px, 1.2vw + 8.5px, 16px); line-height: 1.38; max-width: none; }
  .viz { margin-top: 10px; gap: 8px; }
  .stats b, .stats .stat-in { font-size: 17px; }
  .stats small { font-size: 9px; }
  .stats { gap: 6px 16px; }
  .spark { max-width: 220px; margin-top: 6px; }
  .viz-watch { gap: 1.5em; font-size: clamp(7px, .8vw + 3.6px, 9.6px); }
  .watch, .phone { font-size: clamp(7px, .8vw + 3.6px, 9.6px); }
  .phone { height: 15.4em; }
  .viz-log { font-size: clamp(7px, .8vw + 3.6px, 9.6px); }
  .cal-head, .cal-legend { display: none; }
  .cal-n { width: 2.1em; height: 2.1em; }
  .log-thumb { width: 4.4em; height: 4.4em; }
  .cal-sel { margin-top: .6em; }
  .viz-together { gap: 8px; }
  .rdot { width: 26px; height: 26px; font-size: 9px; }
  .going-text { font-size: 12.5px; }
  .pl-card { padding: 8px 12px 8px 8px; }
  .pl-cover { width: 38px; height: 38px; }
  .pl-text b { font-size: 14px; }
  .pl-sub small { font-size: 11.5px; }
  .cta.cta-inline { height: 44px; min-width: 180px; font-size: 15px; }
}

/* The shortest phones (a browser with its toolbars showing, or an SE): the same scale, one notch down for the figures. */
@media (max-width: 959px) and (min-height: 561px) and (max-height: 700px) {
  .watch, .phone, .viz-watch { font-size: 6.4px; }
  .phone { height: 15.2em; }
  .viz-log { font-size: 6.4px; }
  .stats b { font-size: 15px; }
  .spark { max-width: 190px; margin-top: 4px; }
  .viz { margin-top: 8px; }
}

/* ---- A big computer window: use the room. ----
   The words and the figures grow with a roomy window, so the right-hand side isn't a small column on a big page. Two steps,
   by how much width and height there is; below them nothing changes. The map is as it was. */
@media (min-width: 1280px) and (min-height: 880px) {
  .chapter h3 { font-size: clamp(56px, 4.4vw, 66px); }
  .eyebrow { font-size: 14px; }
  .lede { font-size: 22px; max-width: 36ch; line-height: 1.46; }
  .stats b { font-size: 36px; }
  .stats small { font-size: 12px; }
  .stats { gap: 10px 30px; }
  .spark { max-width: 400px; }
  .watch, .phone, .viz-watch { font-size: 12px; }
  .viz-log { font-size: 11.8px; }
  .rdot { width: 44px; height: 44px; font-size: 13px; }
  .going-text { font-size: 17px; }
  .pl-card { max-width: 430px; }
  .pl-cover { width: 62px; height: 62px; }
  .pl-text b { font-size: 18px; }
  .pl-sub small { font-size: 15px; }
  .cta.cta-inline { height: 60px; min-width: 240px; font-size: 18px; border-radius: 30px; }
}
@media (min-width: 1600px) and (min-height: 1000px) {
  .chapter h3 { font-size: clamp(64px, 4vw, 74px); }
  .eyebrow { font-size: 15px; }
  .lede { font-size: 25px; max-width: 36ch; }
  .stats b { font-size: 44px; }
  .stats small { font-size: 13px; }
  .stats { gap: 12px 38px; }
  .spark { max-width: 480px; }
  .watch, .phone, .viz-watch { font-size: 14.2px; }
  .viz-log { font-size: 13.8px; }
  .rdot { width: 52px; height: 52px; font-size: 15px; }
  .going-text { font-size: 19px; }
  .pl-card { max-width: 500px; }
  .pl-cover { width: 72px; height: 72px; }
  .pl-text b { font-size: 21px; }
  .pl-sub small { font-size: 17px; }
  .cta.cta-inline { height: 66px; min-width: 270px; font-size: 20px; border-radius: 33px; }
}

/* Paragraphs take the full width of their section, like the headings do, wherever the text sits under the map. */
@media (max-width: 959px) { .lede { max-width: none; } }

/* ---- Even spacing, and paragraphs that fill their section ---- */
/* The paragraph uses the whole width of its section, like the heading above it, at every window size. */
.lede { max-width: none; }

/* Every section is as tall as the tallest one, so the figure or animation under each paragraph sits centred in what's left:
   the same gap above it (from the paragraph) as below it (to the dots), instead of all the spare room piling up underneath. */
.is-live .chapters { align-items: stretch; }
.is-live .chapter { display: flex; flex-direction: column; }
.is-live .chapter .lede { margin-bottom: 16px; }
.is-live .chapter .viz { margin-top: auto; margin-bottom: auto; }

/* The calendar is no taller than the other animations: no month title or key, and compact days, at every window size. */
.cal-head, .cal-legend { display: none; }
.cal-n { width: 2.1em; height: 2.1em; }
.log-thumb { width: 4.4em; height: 4.4em; }
.cal-sel { margin-top: .6em; }

/* the download card scales with the window, like everything else beside the map */
@media (min-width: 960px) {
  .viz-free { gap: 18px; }
  .get-icon { width: 54px; height: 54px; }
  .get-text b { font-size: 20px; }
  .get-text span { font-size: 16px; }
  .get-btns { gap: 12px; }
}
@media (min-width: 1280px) and (min-height: 880px) {
  .get-icon { width: 62px; height: 62px; }
  .get-text b { font-size: 22px; }
  .get-text span { font-size: 17px; }
}
@media (min-width: 1600px) and (min-height: 1000px) {
  .get-icon { width: 72px; height: 72px; }
  .get-text b { font-size: 25px; }
  .get-text span { font-size: 19px; }
}
@media (max-width: 959px) and (min-height: 561px) {
  .viz-free { gap: 8px; }
  .get-icon { width: 34px; height: 34px; }
  .get-text b { font-size: 14px; }
  .get-text span { font-size: 12px; }
  .get-btns { gap: 8px; }
  .cta.cta-inline { min-width: 0; padding: 0 12px; height: 40px; font-size: 12.5px; white-space: nowrap; }
  .get-btns { flex-wrap: nowrap; gap: 6px; }
}

/* Apple's badge, as supplied and unaltered: black on a light page, white on a dark one, with at least a quarter of its height clear all round. */
.store-badge { position: relative; display: inline-block; height: 44px; margin: 3px 0; line-height: 0; border-radius: 9px; }
.store-badge img { display: block; height: 100%; width: auto; }
.store-badge .sb-dark { display: none; }
:root[data-theme="dark"] .store-badge .sb-light { display: none; }
:root[data-theme="dark"] .store-badge .sb-dark { display: block; }
/* Until the listing is live, tapping it says so, without changing the badge. */
.store-badge.is-soon::after {
  content: "Coming soon"; position: absolute; inset: 0; display: grid; place-items: center; border-radius: inherit;
  background: rgba(0, 0, 0, 0.82); color: #fff; font: 600 13px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", Arial, sans-serif;
}
:root[data-theme="dark"] .store-badge.is-soon::after { background: rgba(255, 255, 255, 0.88); color: #000; }
.get-btns { align-items: center; }
@media (min-width: 960px) { .store-badge { height: 52px; } }
@media (min-width: 1280px) and (min-height: 880px) { .store-badge { height: 58px; } }
@media (min-width: 1600px) and (min-height: 1000px) { .store-badge { height: 66px; } }
@media (max-width: 959px) and (min-height: 561px) { .store-badge { height: 40px; margin: 2px 0; } }

/* Sections 01 and 04 are sized like the devices in the others: the same footprint, growing smoothly with the height of the window
   (never in steps by width), and never wider than the column on a phone. The climb is drawn in these pixels (see journey.js). */
.stats { width: min(100%, 47vh); justify-content: space-between; }
.stats b { font-size: clamp(15px, min(3vh, 5vw), 44px); }
.spark { width: min(100%, 47vh); max-width: none; height: clamp(44px, min(11vh, 12vw), 130px); margin-top: 10px; }
.spark-line { vector-effect: non-scaling-stroke; stroke-width: 2; }
.viz-log { width: min(100%, 47vh); max-width: none; font-size: clamp(6.2px, min(1.3vh, 1.8vw), 15px); }
@media (max-height: 700px) { .stats b { font-size: 15px; } .viz-log { font-size: 6.4px; } }
/* Stacked under the map, 01 and 04 sit a little smaller than 02's card, in the same proportion as beside the map. */
@media (max-width: 959px) and (min-height: 561px) {
  .stats, .spark, .viz-log { width: min(88%, 300px); }
  .stats b { font-size: clamp(15px, min(2.6vh, 5vw), 44px); }
  .spark { height: clamp(40px, min(9vh, 11vw), 130px); }
  .viz-log { font-size: clamp(6.2px, min(1.3vh, 1.8vw, 8.8px), 15px); }
}
@media (max-height: 700px) { .stats b { font-size: 15px; } .viz-log { font-size: 6.4px; } }

/* Phone and tablet-portrait layout: the Scroll prompt sits on the same row as the chapter dots, at the right end, instead of floating over the content (which in-app browsers, with their taller-than-visible pages, made it cover). */
@media (max-width: 959px) and (min-height: 561px) {
  .is-live .pager { right: 4px; justify-content: space-between; }
  .scroll-cue { position: static; font-size: 11px; }
}
