/* ===================================================================
   Azerbaijan.com
   The scaffold started as a borrowed one - labelled section chips,
   oversized sentence-case headings, rounded photo cards in grids, big
   stat numerals - and most of that has since been taken back out: the
   chips and the stat numerals were the reference showing through, not
   this site. What is left is the part that earned its place.
   =================================================================== */

:root {
  --ground:  #0B0B0C;
  --surface: #121011;   /* one step up from ground, for alternating bands */
  --raise:   #191617;   /* cards */
  --paper:   #F2EDE6;
  --soft:    rgba(242, 237, 230, 0.60);
  --line:    rgba(242, 237, 230, 0.14);

  /* The one arrow mark. Masked, so it takes currentColor and scales with
     the text, and drawn at the same 24/stroke-2 as the .pback chevron.
     These three links used to print the text glyph U+2192, which is a
     different weight and shape from every other mark on the site. */
  --icon-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  /* Lifted from #D4581F, which measured 4.46:1 as text on the raised
     surface: a hair under AA. This clears it on all three grounds
     (4.77 raise / 5.03 surface / 5.22 ground) and is the same colour
     to look at. Text sitting ON the accent uses --on-accent, because
     paper over it is only 3.2:1. */
  --accent:  #D95E22;
  --on-accent: #0B0B0C;

  /* Two voices, not three, and the first two are the same family.

     Bricolage Grotesque carries both the display and the reading, using
     its optical-size axis the way Sakazuki uses a display cut and a text
     cut of one typeface: the same letterforms, drawn differently for the
     job. High opsz for headlines, opsz 14 for paragraphs. That is the
     structural idea taken from the references, not the shapes.

     The face itself is contemporary rather than classical, which is the
     actual change. The Didone that was here read as a fashion magazine;
     both reference sites read as now.

     IBM Plex Mono stays as the label voice: uppercase, tracked, and
     deliberately from a different world, which is the contrast Santioni
     gets from setting an expressive face against a plain one.          */
  --display: "Bricolage Grotesque", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --sans:    "Bricolage Grotesque", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --serif:   var(--display);   /* legacy alias, kept so nothing dangles */

  /* One spacing scale. Every gap on the page comes from this, so the
     rhythm cannot drift section to section the way ad-hoc clamps did. */
  --s1: .5rem;  --s2: .75rem; --s3: 1rem;   --s4: 1.5rem;
  --s5: 2rem;   --s6: 3rem;   --s7: 4.5rem; --s8: 7rem;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --r: 14px;                       /* one radius, everywhere */
  --gutter: clamp(1.25rem, 6vw, 6rem);
  --maxw: 82rem;
  --band: clamp(4.5rem, 9vw, 8rem);   /* one band rhythm, used by every section */
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--ground); color-scheme: dark; -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--paper);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, video, svg { display: block; max-width: 100%; }
::selection { background: var(--accent); color: var(--on-accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px; }
.stop { color: var(--accent); }

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }

/* ---------------------------------------------------------------- type */
.h-xl { font-family: var(--serif); font-weight: 400; font-optical-sizing: auto;
  font-size: clamp(2.75rem, 7.5vw, 6rem); line-height: 1; letter-spacing: -.025em; margin: 0; }
.h-lg { font-family: var(--serif); font-weight: 400; font-optical-sizing: auto;
  font-size: clamp(2rem, 4.6vw, 3.75rem); line-height: 1.06; letter-spacing: -.022em; margin: 0; text-wrap: balance; }
.h-md { font-family: var(--serif); font-weight: 400; font-optical-sizing: auto;
  font-size: clamp(1.75rem, 3.4vw, 2.75rem); line-height: 1.1; letter-spacing: -.02em; margin: 0; text-wrap: balance; }

.lede { margin: 1.25rem 0 0; max-width: 46ch; font-size: clamp(1rem, 1.35vw, 1.1875rem);
  line-height: 1.6; color: var(--soft); }
.body { margin: 1.1rem 0 0; max-width: 60ch; font-size: clamp(.9375rem, 1.05vw, 1.0625rem);
  line-height: 1.7; color: var(--soft); }
.body--right { max-width: 34ch; margin-top: 0; }

/* ---------------------------------------------------------------- bar */
.bar { position: fixed; inset: 0 0 auto 0; z-index: 80; display: flex; align-items: center;
  gap: 1.5rem; padding: 1.15rem var(--gutter);
  background: linear-gradient(to bottom, rgba(11,11,12,.72), rgba(11,11,12,0));
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: var(--paper); margin-right: auto; }
.brand__flag { height: 18px; width: auto; flex: none; border-radius: 2px; overflow: hidden;
  outline: 1px solid rgba(242,237,230,.25); outline-offset: -1px; }
.brand__word { font-family: var(--sans); font-weight: 600; font-size: .9375rem; line-height: 1;
  text-transform: uppercase; letter-spacing: .12em; }
.bar__links { display: flex; gap: clamp(1.25rem, 2.4vw, 2.25rem); }
.bar__links a { display: block; padding-block: .9rem; margin-block: -.9rem;
  font-weight: 500; font-size: .8125rem; text-transform: uppercase; letter-spacing: .14em;
  color: var(--paper); opacity: .78; text-decoration: none; transition: opacity 300ms ease; }
.bar__links a:hover, .bar__links a:focus-visible { opacity: 1; }
.bar__cta { flex: none; padding: .6rem 1.15rem; border: 1px solid var(--line); border-radius: 999px;
  font-weight: 600; font-size: .75rem; text-transform: uppercase; letter-spacing: .14em;
  color: var(--paper); text-decoration: none;
  transition: background 300ms var(--ease), border-color 300ms var(--ease), color 300ms var(--ease); }
.bar__cta:hover, .bar__cta:focus-visible { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* Mobile keeps the navigation and the name. Dropping the links left a phone
   with a flag and one button, which is not a nav. The CTA goes instead: it is
   a duplicate of the Places link, and the links are the thing you cannot lose. */
@media (max-width: 860px) {
  .bar { gap: .75rem; padding-inline: 1.25rem; }
  .bar__cta { display: none; }
  .bar__links { gap: clamp(.6rem, 3vw, 1.1rem); }
  .bar__links a { font-size: .6875rem; letter-spacing: .1em; }
  .brand__word { font-size: .8125rem; letter-spacing: .09em; }
  .brand__flag { height: 16px; }
}
@media (max-width: 340px) { .brand__word { display: none; } }

/* ---------------------------------------------------------------- hero (unchanged) */
.hero { position: relative; height: 100vh; height: 100svh; width: 100%; overflow: hidden; background: var(--ground); }
.hero__video { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center; border: 0; pointer-events: none; }
.hero__gradient { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to right, rgba(11,11,12,.75) 0%, rgba(11,11,12,.3) 40%, transparent 65%); }
.hero__depth { position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(to top, rgba(11,11,12,.82) 0%, rgba(11,11,12,.34) 26%, transparent 54%),
    radial-gradient(125% 95% at 50% 42%, transparent 38%, rgba(11,11,12,.55) 100%); }
.hero__content { position: absolute; z-index: 3; left: var(--gutter); bottom: 18%;
  max-width: calc(100% - var(--gutter) * 2); }
.hero__title { margin: 0 0 1rem -.035em; font-family: var(--serif); font-weight: 400;
  font-optical-sizing: auto; font-size: clamp(3.5rem, 9vw, 9rem); line-height: .95;
  letter-spacing: -.02em; color: var(--paper); }
.hero__sub { margin: 0; max-width: 46ch; font-size: clamp(.9375rem, 1.4vw, 1.0625rem);
  line-height: 1.6; color: var(--soft); }
@media (max-width: 767px) {
  .hero__content { bottom: 13%; }
  .hero__title { font-size: clamp(2.5rem, 14vw, 4.25rem); }
}

/* ---------------------------------------------------------------- bands */
.band { padding-block: var(--band); }
.band--surface { background: var(--surface); }
.band__head { display: grid; gap: var(--s4) var(--s6); align-items: end; margin-bottom: var(--s7); }
@media (min-width: 900px) { .band__head { grid-template-columns: 1.4fr 1fr; } }

.claim { margin-bottom: var(--s7); }

/* photo frames: one radius, and a hairline so an image never floats */
.shot { position: relative; margin: 0; overflow: hidden; border-radius: var(--r);
  background: var(--raise); box-shadow: inset 0 0 0 1px var(--line); }
.shot img { width: 100%; height: 100%; object-fit: cover; }
.shot--tall { aspect-ratio: 4 / 5; }
.shot--sm { aspect-ratio: 1 / 1; }

/* ---------------------------------------------------------------- pillars */
.pillars { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
@media (min-width: 700px) { .pillars { grid-template-columns: repeat(3, 1fr); } }
.pillar__name { font-family: var(--serif); font-weight: 400; font-size: clamp(1.35rem, 2vw, 1.75rem);
  line-height: 1.1; letter-spacing: -.02em; margin: 1.1rem 0 .5rem; }
.pillar__note { margin: 0; font-size: .9375rem; line-height: 1.6; color: var(--soft); }

/* ---------------------------------------------------------------- about */
.about { display: grid; gap: var(--s7); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 960px) { .about { grid-template-columns: 1.05fr .95fr; } }
.about__shot { margin: 0; overflow: hidden; border-radius: var(--r); aspect-ratio: 4 / 3;
  box-shadow: inset 0 0 0 1px var(--line); }
.about__shot img { width: 100%; height: 100%; object-fit: cover; }

/* Three facts about a country, which arrived here as the big-number
   triptych every landing page ships: huge numeral, small-caps label,
   repeated three times. The same three facts read better as a ledger,
   and that is also the shape the place pages already use for exactly
   this job, so the two now share one pattern instead of describing the
   same thing twice. */
.pfacts { display: grid; gap: 0; align-content: start; margin-top: var(--s6);
  border-top: 1px solid var(--line); }
.pfact { position: relative; display: grid; grid-template-columns: 8.5rem 1fr;
  gap: var(--s3); padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.pfact dt { margin: 0; font-size: .6875rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .14em; color: var(--soft); }
.pfact dd { margin: 0; font-size: .9375rem; line-height: 1.55;
  font-variant-numeric: tabular-nums; }
@media (max-width: 480px) { .pfact { grid-template-columns: 1fr; gap: .25rem; } }

/* The rows draw a hairline in from the left under the pointer, so a
   static table acknowledges being read. */
.pfact::after { content: ""; position: absolute; left: 0; bottom: -1px; height: 1px;
  width: 100%; background: var(--accent); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .5s var(--ease); }
@media (hover: hover) and (pointer: fine) { .pfact:hover::after { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .pfact::after { display: none; } }

/* ---------------------------------------------------------------- places grid */
.grid { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
@media (min-width: 640px) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .grid { grid-template-columns: repeat(3, 1fr); } }
.card { display: flex; flex-direction: column; background: var(--raise); border-radius: var(--r);
  overflow: hidden; box-shadow: inset 0 0 0 1px var(--line);
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease); }
.card .shot { border-radius: 0; box-shadow: none; aspect-ratio: 4 / 3; }
.card__body { padding: 1.35rem 1.35rem 1.6rem; }
.card__name { font-family: var(--serif); font-weight: 400; font-size: clamp(1.25rem, 1.8vw, 1.6rem);
  line-height: 1.1; letter-spacing: -.02em; margin: 0 0 .4rem; }
.card__meta { margin: 0 0 .75rem; font-size: .6875rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .14em; color: var(--accent); }
.card__note { margin: 0; font-size: .9375rem; line-height: 1.6; color: var(--soft); }
@media (hover: hover) and (pointer: fine) {
  .card:hover { transform: translateY(-4px); box-shadow: inset 0 0 0 1px rgba(242,237,230,.28); }
}

/* ---------------------------------------------------------------- route */
.route { position: relative; padding-block: calc(var(--band) * 1.15); overflow: hidden; isolation: isolate; }
.route__bed { position: absolute; inset: 0; z-index: -2; }
.route__bed img { width: 100%; height: 100%; object-fit: cover; opacity: .16; }
.route::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(to bottom, rgba(11,11,12,.94), rgba(11,11,12,.86) 45%, rgba(11,11,12,.97)); }
.route__inner { display: grid; gap: var(--s7); }
.route__lead { max-width: 46rem; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5);
  grid-template-columns: 1fr; }
@media (min-width: 620px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step { padding-top: 1.25rem; border-top: 1px solid var(--line); }
.step__n { margin: 0 0 1.25rem; font-family: var(--serif); font-size: 1.125rem; letter-spacing: .02em;
  color: var(--accent); }
.step__h { margin: 0 0 .5rem; font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.2rem, 1.8vw, 1.5rem); line-height: 1.1; letter-spacing: -.02em; }
.step__p { margin: 0; font-size: .9375rem; line-height: 1.6; color: var(--soft); }

/* ---------------------------------------------------------------- close */
.close { padding-block: calc(var(--band) * 1.25); text-align: center; }
.close__inner { display: grid; justify-items: center; }
.close__lede { max-width: 44ch; text-align: center; }

/* ---------------------------------------------------------------- foot */
.foot { border-top: 1px solid var(--line); padding-block: clamp(2.5rem, 5vw, 3.5rem); background: var(--surface); }
.foot__inner { display: grid; gap: 1.75rem; }
@media (min-width: 900px) { .foot__inner { grid-template-columns: auto 1fr; align-items: start; gap: 3rem; } }
.foot__brand { display: flex; flex-direction: column; gap: .4rem; }
.foot__tag { font-size: .75rem; text-transform: uppercase; letter-spacing: .16em; color: var(--soft); }
.credits { margin: 0; font-size: .6875rem; line-height: 1.7; color: var(--soft); }
.credits a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* ===================================================================
   MOTION
   Reveals are JS-gated so a failed script never leaves the page blank.
   Parallax uses NAMED view timelines declared on the frame: a bare
   view() resolved from an image inside an overflow:hidden frame
   measures against a box the image never moves in, and sits frozen.
   =================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* One entrance per section, not five. Headings run their own line by
     line reveal and body copy is simply present, so what still travels
     is the structural furniture: a photograph, the atlas, the pillars.
     22px over 900ms was far enough to read as an element sliding in;
     10px out of an exponential ease-out reads as settling. */
  .js [data-r] { opacity: 0; transform: translateY(10px);
    transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out); }
  .js [data-r].in { opacity: 1; transform: none; }

  /* The pillars sit side by side, so without this the three of them
     arrive on one frame and read as a single block appearing. */
  .js .pillar[data-r]:nth-child(2) { transition-delay: 90ms; }
  .js .pillar[data-r]:nth-child(3) { transition-delay: 180ms; }

  @supports (animation-timeline: view()) {
    .hero__video { animation: heroPush linear both; animation-timeline: scroll(root);
      animation-range: 0 100vh; will-change: transform; }
    .hero__content { animation: heroLift linear both; animation-timeline: scroll(root);
      animation-range: 0 90vh; }

    .shot, .about__shot { view-timeline-name: --shot; view-timeline-axis: block; }
    .about__shot img, .plate img, .echo__shot img { height: 118%; animation: shotDrift linear both;
      animation-timeline: --shot; animation-range: entry 0% exit 100%; will-change: transform; }

    .route__bed { view-timeline-name: --bed; view-timeline-axis: block; }
    .route__bed img { height: 128%; animation: bedDrift linear both;
      animation-timeline: --bed; animation-range: entry 0% exit 100%; }

  }
}

@keyframes heroPush { from { transform: scale(1); }        to { transform: scale(1.1); } }
@keyframes heroLift { from { transform: translateY(0); opacity: 1 }
                      to   { transform: translateY(-9vh); opacity: 0 } }
@keyframes shotDrift { from { transform: translateY(-13%); } to { transform: translateY(0%); } }
@keyframes bedDrift  { from { transform: translateY(-18%); } to { transform: translateY(0%); } }

/* --t has to be a registered property or it cannot be interpolated. */
@property --t { syntax: "<number>"; inherits: true; initial-value: 1; }

@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
}

/* ===================================================================
   PREMIUM MECHANICS
   Drop-ins from the brand-sites mechanics library, adapted to this
   palette. Numbers refer to that reference.
   =================================================================== */

/* --- §6 Horizontal ride: down, then right, then down again --------- */
.band--tight { padding-bottom: 0; }
.hs   { position: relative; height: 320vh; }
.hsS  { position: sticky; top: 0; height: 100svh; overflow: hidden;
        display: flex; align-items: center; }
.track { display: flex; gap: var(--s4); height: auto;
         padding-inline: var(--gutter); will-change: transform; }
.panel { flex: 0 0 auto; width: clamp(15rem, 26vw, 22rem);
         display: flex; flex-direction: column;
         background: var(--raise); border-radius: var(--r); overflow: hidden;
         box-shadow: inset 0 0 0 1px var(--line); }
.panel .shot { border-radius: 0; box-shadow: none; aspect-ratio: 4 / 5; }
/* the rail needs its own top and bottom fades or it butts into the bands */
.hsS::before, .hsS::after { content: ""; position: absolute; left: 0; right: 0;
  height: 14vh; pointer-events: none; z-index: 3; }
.hsS::before { top: 0;    background: linear-gradient(to bottom, var(--ground), transparent); }
.hsS::after  { bottom: 0; background: linear-gradient(to top,    var(--ground), transparent); }

/* --- §2 + §3 Pinned chapter with gradient seams ------------------- */
.ch .bg { position: sticky; top: 0; height: 100svh; overflow: hidden; z-index: 0; }
.ch .bg::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 16vh;
  background: linear-gradient(to bottom, var(--ground), transparent); z-index: 1; pointer-events: none; }
.ch .bg::after  { content: ""; position: absolute; inset: auto 0 0 0; height: 24vh;
  background: linear-gradient(to top,    var(--ground), transparent); z-index: 1; pointer-events: none; }
.route.ch { padding-block: 0; }
.route.ch .route__inner { position: relative; z-index: 2; margin-top: -100svh;
  padding-block: calc(var(--band) * 1.2); }

/* --- §4 Brand-hue wash instead of a flat black void --------------- */
.winewrap { position: relative; overflow: hidden; background: var(--ground); isolation: isolate; }
.winewrap > .wb { position: absolute; inset: -12%; z-index: 0; }
.winewrap > .wb img { width: 100%; height: 100%; object-fit: cover;
  filter: blur(64px) saturate(1.3); opacity: .30; transform: scale(1.2); }
.winewrap > *:not(.wb) { position: relative; z-index: 2; }

/* --- §7 Reveal cascade: media scales in, text staggers ------------ */
.rv { overflow: hidden; }
.rv:not(.panel) img { transform: scale(1.12); opacity: 0;
  transition: transform 1.5s cubic-bezier(.16,1,.3,1), opacity 1s ease; }
.rv.in:not(.panel) img { transform: scale(1); opacity: 1; }

/* --- §9 Giant stroked footer wordmark ----------------------------- */
.giantwrap { padding-inline: var(--gutter); margin-bottom: clamp(2rem, 5vw, 3.5rem);
  overflow: hidden; }
.giant { margin: 0; font-family: var(--serif); text-transform: uppercase;
  text-align: center; font-size: clamp(2.5rem, 13.5vw, 13rem); line-height: .9;
  letter-spacing: .04em; color: transparent;
  -webkit-text-stroke: 1px rgba(242, 237, 230, .40); }

@media (prefers-reduced-motion: reduce) {
  /* §6 fallback: the ride becomes an ordinary column, nothing unreachable */
  .hs   { height: auto; }
  .hsS  { position: static; height: auto; display: block; }
  .track { flex-direction: column; transform: none !important;
           padding-block: var(--band); }
  .panel { width: auto; }
  .hsS::before, .hsS::after { display: none; }
  .route.ch .bg { position: relative; height: 46svh; }
  .route.ch .route__inner { margin-top: 0; }
  .rv img { transform: none; opacity: 1; }
}

/* ===================================================================
   THE DESCENT
   The hero pins, then shrinks, rounds and darkens while the first dark
   section rides up over it. Reads as sinking past the surface rather
   than the hero simply scrolling away.
   =================================================================== */
.hero { position: sticky; top: 0; z-index: 0;
  transform-origin: 50% 42%; will-change: transform; }
.hero__sink { position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: var(--ground); opacity: 0; }

/* Everything after the hero has to be opaque and above it, or the pinned
   hero shows through the gaps between bands. */
main > section:not(.hero) { position: relative; z-index: 2; }
.band { background: var(--ground); }
.band--surface { background: var(--surface); }
.route.ch { background: var(--ground); }
.close.winewrap { background: var(--ground); }

/* ===================================================================
   ATLAS: real projected geography, ten selectable places
   =================================================================== */
/* Three children, so the columns are declared as areas. A plain two-column
   grid wrapped the info panel onto a second row and off the screen. */
.atlas { display: grid; gap: var(--s5); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 960px) {
  .atlas { grid-template-columns: 1.32fr .68fr; gap: var(--s5) var(--s6);
    grid-template-areas: "stage panel" "list panel"; align-items: start; }
  .atlas__stage { grid-area: stage; }
  .atlas__list  { grid-area: list; margin-top: 0; }
  .atlas__panel { grid-area: panel; position: sticky; top: 6rem; }
}

.atlas__stage { position: relative; margin: 0; }
.atlas__svg { width: 100%; height: auto; overflow: visible; }
.atlas__land { fill: rgba(242,237,230,.045); stroke: rgba(242,237,230,.30); stroke-width: 2;
  stroke-linejoin: round; vector-effect: non-scaling-stroke; }

.pin { cursor: pointer; }
.pin__halo { fill: var(--accent); opacity: 0; transition: opacity .35s var(--ease); }
.pin__dot  { fill: var(--paper); transition: fill .3s var(--ease), r .3s var(--ease); }
.pin__hit  { fill: transparent; }
/* Labels are revealed, not permanent. Ten of them at once collided into an
   unreadable knot around Absheron, where three pins sit within 25px. */
.pin__lbl  { fill: var(--paper); font-family: var(--sans); font-size: 21px; font-weight: 500;
  text-anchor: middle; opacity: 0; transition: opacity .3s var(--ease); paint-order: stroke;
  stroke: var(--ground); stroke-width: 6px; pointer-events: none; }
.pin:hover .pin__halo, .pin:focus-visible .pin__halo { opacity: .22; }
.pin:hover .pin__lbl,  .pin:focus-visible .pin__lbl  { opacity: 1; }
.pin.is-on .pin__dot { fill: var(--accent); }
.pin.is-on .pin__halo { opacity: .30; }
.pin.is-on .pin__lbl { opacity: 1; }
.pin:focus-visible { outline: none; }
.pin:focus-visible .pin__dot { stroke: var(--accent); stroke-width: 3; }

.atlas__hint { margin: var(--s3) 0 0; font-size: .6875rem; text-transform: uppercase;
  letter-spacing: .18em; color: var(--soft); }

.atlas__panel { background: var(--raise); border-radius: var(--r); overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--line); }
.atlas__shot { aspect-ratio: 4 / 3; overflow: hidden; background: var(--surface); }
.atlas__shot img { width: 100%; height: 100%; object-fit: cover; }
.atlas__body { padding: var(--s4); }
.atlas__region { margin: 0 0 var(--s1); font-size: .6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .14em; color: var(--accent); }
.atlas__name { margin: 0 0 var(--s2); font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.35rem, 2.2vw, 1.85rem); line-height: 1.1; letter-spacing: -.02em; }
.atlas__note { margin: 0; font-size: .9375rem; line-height: 1.65; color: var(--soft); }

@media (prefers-reduced-motion: reduce) {
  .hero { position: relative; transform: none !important; }
  .hero__sink { display: none; }
}


/* --- atlas place list: discoverable, keyboard-navigable, and the only
       workable way to choose on a phone where a 5px dot cannot be tapped --- */
.atlas__list { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s4); }
.atlas__chip { appearance: none; cursor: pointer;
  /* sized to clear the 44px touch minimum, not eyeballed */
  padding: .9rem 1.15rem; border: 1px solid var(--line); border-radius: 999px;
  background: transparent; color: var(--paper);
  font-family: var(--sans); font-size: .75rem; font-weight: 500;
  letter-spacing: .06em; line-height: 1;
  transition: background .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease); }
.atlas__chip:hover { border-color: rgba(242,237,230,.42); }
.atlas__chip.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
@media (max-width: 600px) { .atlas__chip { padding: .9rem 1.05rem; font-size: .78rem; } }


/* ===================================================================
   TEXT: vertical cut reveal (the 21st.dev pattern, line-based).
   Lines rise from behind a mask. Characters are deliberately not split:
   both skills say that turns reading into waiting.
   =================================================================== */
.tl { display: block; overflow: hidden; }
/* the mask must clear descenders or g, y, p and j get sheared off */
.tl__i { display: block; padding-bottom: .12em; margin-bottom: -.12em;
  will-change: transform, opacity; }
.js .tl__i { transform: translateY(105%); opacity: 0; }

/* ===================================================================
   PLACES: cards reveal as they arrive, and answer the pointer
   =================================================================== */
.panel { transition: box-shadow .5s var(--ease); }
.panel img { will-change: transform; }
.js .panel { opacity: 0; }
.panel.is-in { opacity: 1; }
.panel:hover { box-shadow: inset 0 0 0 1px rgba(242,237,230,.34); }

/* ===================================================================
   ATLAS, premium pass: a sea, a graticule, a glow on the live pin
   =================================================================== */
.atlas__stage { padding: var(--s4); border-radius: var(--r);
  background:
    radial-gradient(120% 90% at 78% 44%, rgba(217,94,34,.10), transparent 58%),
    linear-gradient(180deg, rgba(242,237,230,.035), rgba(242,237,230,.012));
  box-shadow: inset 0 0 0 1px var(--line); }
.atlas__grid line { stroke: rgba(242,237,230,.055); stroke-width: 1;
  vector-effect: non-scaling-stroke; }
.atlas__sea { fill: none; stroke: rgba(217,94,34,.20); stroke-width: 1.5;
  vector-effect: non-scaling-stroke; stroke-dasharray: 3 7; }
.atlas__land { fill: url(#landFill); stroke: rgba(242,237,230,.42); stroke-width: 1.5; }
/* Selected region lights up over the base outline, the way the reference
   does it with PNG overlays. Real rayon boundaries, matched to each place
   by point-in-polygon rather than by eye. */
.atlas__regions .rg { fill: rgba(217,94,34,.14); stroke: var(--accent); stroke-width: 1.75;
  vector-effect: non-scaling-stroke; opacity: 0; pointer-events: none;
  transition: opacity .55s var(--ease); }
.atlas__regions .rg.is-on { opacity: 1; }
.pin.is-on .pin__dot { filter: drop-shadow(0 0 7px rgba(217,94,34,.95)); }
.pin__ring { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0;
  vector-effect: non-scaling-stroke; }
.pin.is-on .pin__ring { opacity: .55; }

/* ===================================================================
   PLANNER
   =================================================================== */
@media (min-width: 900px) { .plan { grid-template-columns: .8fr 1.2fr; gap: var(--s7); } }
@media (max-width: 420px) {
    }

@media (prefers-reduced-motion: reduce) {
  .js .tl__i { transform: none; opacity: 1; }
  .js .panel { opacity: 1; }
}

/* --- cards are links now, so they need the anchor reset --- */
a.panel { text-decoration: none; color: var(--paper); }
a.panel:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* --- atlas: through to the full page --- */
.atlas__go { display: inline-flex; align-items: center; gap: .5rem;
  margin: 0 0 var(--s2); font-family: var(--sans); font-size: .6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .16em; color: var(--accent);
  text-decoration: none; border-bottom: 1px solid rgba(217,94,34,.45);
  padding-bottom: .2rem; transition: border-color .3s var(--ease); }
.atlas__go::after { content: ""; width: 1em; height: 1em; flex: none; background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat; }
.atlas__go:hover { border-color: var(--accent); }

/* ===================================================================
   SCROLL LAYER
   Six mechanics added on top of the base page. Every one of them is
   transform/opacity only, and every hidden state is gated behind .js
   so that with scripting off the page is simply the static document.
   =================================================================== */

/* -- 1. progress hairline ------------------------------------------ */
.prog { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
  pointer-events: none; background: rgba(242,237,230,.07); }
.prog__b { height: 100%; width: 100%; transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--accent), #F0873F); }

/* -- 2. scroll-driven text reveal ----------------------------------
   Two grammars.

   [data-hl] lights a paragraph WORD by word.
   [data-ch] lights it CHARACTER by character, which is the finer,
   slower-reading version: the line resolves like something developing
   rather than switching on. Characters are inline-block so each can
   carry its own opacity without breaking the line box; word wrappers
   keep whole words together so wrapping still happens at spaces. */
.js [data-hl] { color: var(--paper); }
[data-hl] .hw { transition: none; }
.mo [data-hl] .hw { opacity: .2; }

.js [data-ch] { color: var(--paper); }
[data-ch] .cw { display: inline-block; white-space: nowrap; }
[data-ch] .cc { display: inline-block; will-change: opacity; }
.mo [data-ch] .cc { opacity: .28; }

/* -- 3. marquee ----------------------------------------------------
   Two identical runs sit side by side and the pair is translated by
   exactly one run width, so the seam is never visible. */
.mq { overflow: hidden; border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line); padding: clamp(1rem,2.4vw,1.9rem) 0;
  background: var(--ground); }
.mq__t { display: flex; width: max-content; will-change: transform; }
.mq__r { display: flex; flex: none; align-items: center; }
.mq__i { display: inline-flex; align-items: center; gap: clamp(1.4rem,3vw,2.8rem);
  padding-right: clamp(1.4rem,3vw,2.8rem);
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.5rem,3.6vw,3rem); line-height: 1; letter-spacing: -.02em;
  color: var(--soft); white-space: nowrap; }
.mq__i::after { content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); flex: none; }

/* -- 4. position indicator -----------------------------------------
   Replaces a 10px line of small caps that sat under mix-blend-mode:
   difference, washed out over every bright photograph, and was hidden
   outright below 700px. So on a phone there was no indicator at all.

   Desktop  a tick per section down the right edge. The active tick
            grows and takes the accent, and only the active one carries
            a label, so the rail reads as position rather than as a menu.
   Mobile   the rail would be a row of 6px targets, which is not worth
            having, so the same state becomes a legible pill at the
            bottom with its own progress line.                          */
.idx { position: fixed; z-index: 55; pointer-events: none;
  opacity: 0; transition: opacity .5s var(--ease); }
.idx.is-on { opacity: 1; }
.idx__i { display: flex; align-items: center; gap: .7rem; }
/* Scaled, not resized: this used to transition width, which is a layout
   pass on every frame of a mark that redraws on every section change. */
.idx__tick { display: block; width: 34px; height: 2px; border-radius: 1px; flex: none;
  background: rgba(242,237,230,.26);
  transform: scaleX(.47); transform-origin: 100% 50%;
  transition: transform .45s var(--ease), background .45s var(--ease); }
.idx__lab { font-family: var(--mono); font-size: .5625rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .16em; white-space: nowrap;
  color: var(--paper); opacity: 0; transform: translateX(6px);
  transition: opacity .4s var(--ease), transform .4s var(--ease); }
.idx__i.is-cur .idx__tick { background: var(--accent); }
/* The name is announced on arrival, then gets out of the way. Held
   permanently it reached back into the column and sat on the copy. */
.idx__i.is-cur.is-say .idx__lab { opacity: 1; transform: none; }

@media (min-width: 861px) {
  .idx { right: calc(var(--gutter) * .55); top: 50%; transform: translateY(-50%);
    display: grid; gap: .85rem; justify-items: end; }
  .idx__i { flex-direction: row-reverse; }
  .idx__i.is-cur .idx__tick { transform: scaleX(1); }
}

@media (max-width: 860px) {
  .idx { left: 50%; transform: translateX(-50%); bottom: 1rem;
    display: flex; align-items: center; gap: .5rem;
    padding: .55rem .85rem; border-radius: 999px;
    background: rgba(11,11,12,.72); border: 1px solid var(--line);
    backdrop-filter: saturate(140%) blur(12px);
    -webkit-backdrop-filter: saturate(140%) blur(12px); }
  .idx__i { display: none; }
  .idx__i.is-cur { display: flex; }
  /* the pill exists to carry the name, so it does not fade there */
  .idx__i.is-cur .idx__lab { opacity: 1; transform: none; }
  .idx__tick { width: 22px; transform: none; }
  .idx__lab { font-size: .5625rem; }
  .idx__count { font-family: var(--mono); font-size: .5625rem; font-weight: 600;
    letter-spacing: .12em; color: var(--soft); font-variant-numeric: tabular-nums; }
}
@media (min-width: 861px) { .idx__count { display: none; } }

/* -- 5. pointer spotlight ------------------------------------------
   A soft accent wash that follows the cursor across a card. Painted in
   a pseudo-element so it can never intercept a click. */
.pillar, .panel { position: relative; }
.pillar::after, .panel::after { content: ""; position: absolute; inset: 0;
  border-radius: inherit; pointer-events: none; opacity: 0;
  transition: opacity .45s var(--ease);
  background: radial-gradient(18rem 18rem at var(--mx,50%) var(--my,50%),
              rgba(217,94,34,.16), transparent 70%); }
@media (hover: hover) and (pointer: fine) {
  .pillar:hover::after, .panel:hover::after { opacity: 1; }
}

/* -- 6. depth ------------------------------------------------------ */
.mo [data-depth] { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .js [data-hl] .hw { opacity: 1; }
  .prog, .idx { display: none; }
  .mq__t { transform: none !important; }
}

/* -- 7. the band opens, then plays -----------------------------------
   It used to be one photograph in a frame that widened. Now the frame
   still widens, and then runs the whole country through it: eleven
   places crossfading under the scroll like frames of a film.

   The clip and the crossfade are driven from one progress value so they
   can never disagree, and the whole thing is gated on .mo, so with no
   script it is a single photograph in an open frame and no extra scroll
   is added to the page for a mechanic that is not running. */
.xband { background: var(--ground); padding: var(--band) 0; }
.xband__track { position: relative; }
.xband__f { position: relative; margin: 0; height: clamp(18rem, 62vh, 34rem);
  overflow: hidden; }
/* 11 frames after the opening: at 340vh each place held for about
   26vh of scroll, which read as a flicker rather than a look. 560vh
   gives each one roughly 45vh, about half a screen of scrolling. */
.mo .xband__track { height: 560vh; }
.mo .xband__f { position: sticky; top: calc(50vh - min(17rem, 31vh)); }
.mo .xband__f { clip-path: inset(0 26% 0 26% round var(--r)); }

.xband__f img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; will-change: transform, opacity; }
/* Without the script the strip is simply its first frame. */
.mo .xband__f .xf { opacity: 0; }
.mo .xband__f .xf:first-of-type { opacity: 1; }
/* `:not(.mo) > .xband__f` reads as "a frame whose DIRECT PARENT lacks
   .mo" - and its direct parent is .xband__track, which never has it. So
   this matched always and every frame after the first was display:none
   while the caption happily cycled underneath. .mo lives on <html>. */
html:not(.mo) .xf ~ .xf, .xband__f:not([data-strip]) .xf ~ .xf { display: none; }

.xband__c { position: absolute; left: var(--gutter); bottom: var(--s4); z-index: 3;
  max-width: 30rem; display: grid; gap: .3rem;
  text-shadow: 0 1px 18px rgba(11,11,12,.95); }
.xband__n { font-family: var(--display); font-weight: 400;
  font-variation-settings: "opsz" 96;
  font-size: clamp(1.6rem, 3.2vw, 2.6rem); line-height: 1;
  letter-spacing: -.03em; color: var(--paper); }
.xband__t { font-family: var(--mono); font-weight: 500; font-size: var(--t-micro);
  letter-spacing: .09em; text-transform: uppercase; color: rgba(242,237,230,.82); }

/* Position in the strip, not a control. */
.xband__bar { position: absolute; right: var(--gutter); bottom: var(--s4); z-index: 3;
  display: flex; gap: .3rem; }
.xband__bar i { display: block; width: 14px; height: 2px; border-radius: 1px;
  background: rgba(242,237,230,.28);
  transition: background .35s var(--ease), transform .35s var(--ease); }
.xband__bar i[data-on="true"] { background: var(--accent); transform: scaleY(2.4); }
@media (max-width: 620px) {
  .xband__bar { left: var(--gutter); right: auto; bottom: var(--s2); }
  .xband__bar i { width: 9px; }
  .xband__c { bottom: calc(var(--s4) + .9rem); }
}

@media (prefers-reduced-motion: reduce) {
  .mo .xband__track { height: auto; }
  .mo .xband__f { position: relative; clip-path: inset(0 round var(--r)); }
  .mo .xband__f .xf { opacity: 0; }
  .mo .xband__f .xf:first-of-type { opacity: 1; }
  .xband__bar { display: none; }
}
}

/* -- 8. nav gains a ground once the page has moved -------------------
   Without this the marquee and the giant headings run straight through
   the links, which reads as a bug rather than as transparency. */
.bar { transition: background .4s var(--ease), backdrop-filter .4s var(--ease),
       border-color .4s var(--ease); border-bottom: 1px solid transparent; }
.bar.is-stuck { background: rgba(11,11,12,.72); backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px); border-bottom-color: var(--line); }

/* -- 9. touch targets ------------------------------------------------
   Two links are set in small caps and would be 16px tall if you measured
   the box you can actually hit. The type stays where it is; an invisible
   pseudo-element carries the hit area out to 44px. ::after is already
   spoken for on .atlas__go (the arrow), so this uses ::before. */
.brand, .atlas__go { position: relative; }
.brand::before, .atlas__go::before { content: ""; position: absolute;
  left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); }

/* ===================================================================
   TYPE LAYER
   Three voices held apart on purpose: a Didone that only ever shouts,
   a mono that only ever labels, and a neutral sans that only ever
   explains. The old page ran one text-face for all three jobs, which
   is why it read as typeset rather than designed.
   =================================================================== */

/* -- display: bigger, tighter, heavier ------------------------------
   A Didone needs scale to show what makes it a Didone. Below about
   3rem the hairlines stop reading and it is just a serif. */
.h-xl, .h-lg, .h-md, .pillar__name, .atlas__name, .phero__t, .pnext__n, .plate__t {
  font-family: var(--display); font-optical-sizing: auto;
  font-weight: 500; font-style: normal; }
.h-xl { font-size: clamp(3rem, 10.5vw, 10rem); line-height: .88; letter-spacing: -.035em; }
.h-lg { font-size: clamp(2.4rem, 6.4vw, 5.4rem);  line-height: .94; letter-spacing: -.03em; }
.h-md { font-size: clamp(2rem, 4.4vw, 3.4rem);    line-height: .98; letter-spacing: -.028em; }

/* -- mono: every label on the site ---------------------------------
   One rule, so a new label cannot quietly arrive in the wrong voice. */
.bar__links a, .bar__cta, .foot__tag, .credits,
.atlas__chip, .atlas__region, .atlas__go, .ask__legend, .ask__n,
.rstop__day, .rstop__go, .idx, .pnext__r, .pfact dt, .pback, .xband__c,
.panel__r, .cr__l, .cr__by {
  font-family: var(--mono); font-weight: 500;
  text-transform: uppercase; letter-spacing: .14em;
  font-feature-settings: "kern" 1; }

/* Labels are small by definition; mono runs wide, so they need room. */
.bar__links a, .bar__cta { font-size: .6875rem; letter-spacing: .16em; }
.credits { font-size: .625rem; letter-spacing: .07em; line-height: 1.9; text-transform: none; }
.credits a { text-transform: none; }
.xband__c { font-size: .625rem; letter-spacing: .12em; }

/* -- body stays quiet ---------------------------------------------- */
.body, .lede, .pillar__note, .atlas__note, .plead__body p, .pfact dd {
  font-family: var(--sans); text-transform: none; letter-spacing: normal; }

/* The selected place has to out-read its own district. The shaded
   polygon covers thousands of square kilometres; the dot covers a
   village. Before this the shading was the loudest thing on the map,
   so a village looked like it WAS the district. */
.pin.is-on .pin__dot { fill: var(--paper); r: 7; filter: drop-shadow(0 0 10px rgba(242,237,230,.9)); }
.pin.is-on .pin__ring { opacity: .85; stroke-width: 2; }
.pin.is-on .pin__lbl { font-family: var(--mono); font-weight: 600;
  font-size: 19px; letter-spacing: .06em; text-transform: uppercase;
  paint-order: stroke; stroke: rgba(11,11,12,.85); stroke-width: 5px; }
.atlas__hint { max-width: 22rem; line-height: 1.7; }

/* -- 10. the wordmark catches ---------------------------------------
   The footer wordmark was a dead outline. Now it fills with the accent
   from left to right as the footer arrives, so the page ends on the
   same colour it started with.

   Two layers rather than one: the outline stays exactly as it was, and
   a solid accent copy sits on top of it, revealed by a clip that scroll
   drives. Animating the stroke colour instead would have meant
   repainting text on every frame; a clip on a already-painted layer is
   just a composite. */
.giantwrap { position: relative; }
.giant { position: relative; }
.giant__fill { position: absolute; inset: 0; margin: 0;
  font: inherit; letter-spacing: inherit; text-align: inherit;
  text-transform: inherit; color: var(--accent);
  -webkit-text-stroke: 0; pointer-events: none;
  will-change: clip-path; }
.mo .giant__fill { clip-path: inset(0 100% 0 0); }
@media (prefers-reduced-motion: reduce) {
  .mo .giant__fill { clip-path: inset(0 0 0 0); }
}

/* ===================================================================
   INTERACTION LAYER
   The page animated beautifully on scroll and gave nothing back when
   you actually touched it: not one :active state anywhere. Pressing a
   chip, a nav link or a plan option produced no acknowledgement at all,
   which on a phone reads as a dead control.
   =================================================================== */

:root {
  /* One rhythm for every hand-triggered transition, so a chip and a
     nav link do not disagree about how fast the site responds. */
  --t-fast: 140ms;    /* press: has to feel immediate */
  --t-base: 260ms;    /* hover and state changes */
  --t-out:  180ms;    /* release, ~70% of enter, so it snaps back */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in:  cubic-bezier(0.55, 0, 1, 0.45);
}

/* Removes the ~300ms tap delay without disabling pinch-zoom. */
a, button, .atlas__chip, .ask__opt { touch-action: manipulation; }

/* Press feedback. Transform only, so nothing reflows under a finger.
   The nudge is forward, along the arrow these controls already carry. */
.bar__cta, .atlas__chip, .atlas__go, .pback { transition-duration: var(--t-fast); }
.bar__cta:active, .atlas__chip:active, .atlas__go:active, .pback:active {
  transform: translateX(2px); transition-duration: var(--t-fast); }
.pnext__c:active { transform: scale(.99); transition-duration: var(--t-fast); }
.bar__links a { transition: opacity var(--t-base) var(--ease-out),
                            transform var(--t-out) var(--ease-out); }
.bar__links a:active { transform: translateY(1px); transition-duration: var(--t-fast); }
.panel:active { transform: scale(.995); }

/* A focus ring that survives the dark ground and never shifts layout. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

@media (prefers-reduced-motion: reduce) {
  .bar__cta:active, .atlas__chip:active, .atlas__go:active,
  .pback:active, .pnext__c:active,
  .bar__links a:active, .panel:active { transform: none; }
}

/* ===================================================================
   HOVER LAYER
   Desktop only, behind (hover: hover) and (pointer: fine). None of it
   is the only route to anything: every affordance here restates
   something the page already does, it just says it out loud when a
   pointer is present. Touch keeps the pressed states instead.
   =================================================================== */

/* -- 1. the ride cards say they are doors ---------------------------
   They were links whose only tell was a 10px lift. */
.card__go { margin: var(--s2) 0 0; display: inline-flex; align-items: center; gap: .45rem;
  font-family: var(--mono); font-size: .5625rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .16em; color: var(--accent); }
.card__go::after { content: ""; width: 1em; height: 1em; flex: none; background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat;
  transition: transform var(--t-base) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .card__go { opacity: 0; transform: translateY(6px);
    transition: opacity var(--t-base) var(--ease-out),
                transform var(--t-base) var(--ease-out); }
  .panel:hover .card__go, .panel:focus-visible .card__go { opacity: 1; transform: none; }
  .panel:hover .card__go::after { transform: translateX(4px); }
}

/* -- 2. the marquee stops when you look at it -----------------------
   It is the one thing on the page that never stops, which makes it the
   one thing you cannot read. */
.mq { cursor: default; }

/* -- 3. the position rail becomes a way to travel -------------------
   Hovering opens every label at once and the ticks become jumps. The
   rail still works as a pure readout if you never touch it. */
.idx__i { pointer-events: none; }
@media (min-width: 861px) and (hover: hover) and (pointer: fine) {
  .idx { pointer-events: auto; padding: .6rem .5rem; border-radius: 12px;
    transition: opacity .5s var(--ease), background .35s var(--ease-out); }
  .idx__i { pointer-events: auto; cursor: pointer; }
  .idx:hover { background: rgba(11,11,12,.66);
    backdrop-filter: saturate(140%) blur(12px);
    -webkit-backdrop-filter: saturate(140%) blur(12px); }
  .idx:hover .idx__lab { opacity: .55; transform: none; }
  .idx:hover .idx__i.is-cur .idx__lab { opacity: 1; }
  .idx__i:hover .idx__lab { opacity: 1 !important; }
  .idx__i:hover .idx__tick { transform: scaleX(1); background: var(--accent); }
  .idx__i:active .idx__tick { transform: scaleX(1) scaleY(2.2); }
}

/* -- 4. the map answers the pointer before the click ---------------- */
.pin { cursor: pointer; }
.atlas__stage.is-peek .rg.is-on { opacity: .35; }
.rg.is-peek { opacity: 1 !important; }
.pin.is-peek .pin__lbl { opacity: 1; }
.pin.is-peek .pin__dot { fill: var(--paper); }

/* -- 5. the wordmark leans toward the pointer ----------------------- */
@media (hover: hover) and (pointer: fine) {
  .giant__glow { position: absolute; inset: 0; margin: 0; font: inherit;
    letter-spacing: inherit; text-align: inherit; text-transform: inherit;
    color: var(--accent); -webkit-text-stroke: 0; pointer-events: none;
    opacity: 0; transition: opacity .5s var(--ease-out);
    -webkit-mask-image: radial-gradient(14rem 14rem at var(--gx,50%) var(--gy,50%),
      #fff 0%, transparent 68%);
    mask-image: radial-gradient(14rem 14rem at var(--gx,50%) var(--gy,50%),
      #fff 0%, transparent 68%); }
  .giantwrap:hover .giant__glow { opacity: .85; }
}

@media (prefers-reduced-motion: reduce) {
  .card__go { opacity: 1 !important; transform: none !important; }
  .giant__glow { display: none; }
}

/* ===================================================================
   TYPE SCALE
   A pass over the whole page after Sakazuki and Santioni. Neither of
   those sites builds hierarchy by piling on weights: Sakazuki runs one
   superfamily at a single weight and lets SIZE do all the work, and
   Santioni gives one expressive face the identity and keeps the reading
   face quiet underneath. The audit here found the opposite of both:
   three families, weights scattered across 400/500/600, the mono
   carrying eight different jobs at six different sizes, and body copy
   rendering at 15.12px on desktop.

   Two rules from the brief, both absolute: body sits between 16 and
   18px, and there is exactly one display face.
   =================================================================== */

:root {
  /* One step of the scale per job, so a new element has somewhere to go
     without inventing a size. */
  --t-micro: 0.75rem;    /* 12px  labels, the floor for anything          */
  --t-small: 0.8125rem;  /* 13px  captions, meta, credits                 */
  --t-body:  1.0625rem;  /* 17px  the middle of the 16-18 band            */
  --t-lede:  1.25rem;    /* 20px  opening paragraphs                      */
}

/* -- one display face, one weight ------------------------------------
   Bodoni at 400 rather than 500. A Didone IS its hairlines; the heavier
   cut was thickening them back up and quietly undoing the reason for
   choosing the face. Optical sizing keeps the small end readable. */
.h-xl, .h-lg, .h-md, .pillar__name, .atlas__name, .phero__t, .pnext__n,
.card__name, .mq__i, .giant, .giant__fill, .cr__g h2, .cr__h h1 {
  font-family: var(--display); font-weight: 400; font-optical-sizing: auto; }

/* -- body: the rule ---------------------------------------------------
   Everything a reader reads in sentences lands on one size. */
.body, .lede, .pillar__note, .card__note, .atlas__note, .plead__body p,
.pfact dd, .close__lede, .cr__h p {
  font-family: var(--sans); font-weight: 400;
  font-size: var(--t-body); line-height: 1.65;
  text-transform: none; letter-spacing: normal; }
.lede, .plead__body p:first-child, .close__lede {
  font-size: var(--t-lede); line-height: 1.55; }
.pillar__note, .card__note, .atlas__note { line-height: 1.6; }

/* -- labels: one voice, one weight, and off the floor ----------------
   Mono tracked out is the label voice, but 0.16em at 9px was spacing
   the letters further apart than they were tall. */
.bar__links a, .bar__cta, .foot__tag, .atlas__chip,
.atlas__region, .atlas__go, .ask__legend, .ask__n, .idx,
.card__meta, .pnext__r, .pfact dt, .pback, .xband__c,
.cr__l {
  font-family: var(--mono); font-weight: 500;
  text-transform: uppercase; letter-spacing: .1em; }
.ask__n, .atlas__chip, .bar__links a, .bar__cta,
.pfact dt, .pback, .pnext__r, .card__meta {
  font-size: var(--t-micro); }
.idx__lab, .idx__count, .foot__tag, .atlas__region, .atlas__go,
/* Photo captions are prose. They sat in the label voice with the rest of
   the small type, which put whole sentences into tracked capitals. */
.pshot figcaption, .shot figcaption {
  font-family: var(--sans); font-variation-settings: "opsz" 14; font-weight: 400;
  font-size: var(--t-small); text-transform: none; letter-spacing: normal;
  line-height: 1.5; }

.xband__c, .cr__l {
  font-size: var(--t-micro); letter-spacing: .09em; }
/* This is a whole sentence explaining the map, not a label. Ninety
   characters of tracked capitals is a thing you decode, not read. */
.atlas__hint { font-family: var(--sans); font-variation-settings: "opsz" 14;
  font-size: var(--t-small); font-weight: 400; text-transform: none;
  letter-spacing: normal; line-height: 1.6; color: var(--soft); max-width: 46ch; }

/* -- credits read as prose, not as a label -------------------------- */
.credits, .cr__by { font-family: var(--sans); font-weight: 400;
  font-size: var(--t-small); line-height: 1.75;
  text-transform: none; letter-spacing: normal; }

/* -- the wordmark is the one place the brand shouts ------------------ */
.brand__word { font-family: var(--mono); font-weight: 600;
  font-size: var(--t-micro); letter-spacing: .16em; }

/* -- the last four out of step --------------------------------------
   Found by auditing the rendered page rather than the stylesheet, which
   is the only way these show up: each one was set in a different place
   and none of them looked wrong on its own. */

/* Only the SELECTED pin's label had been moved to the mono. The other
   ten were still sitting in the body sans, so the map changed voice
   depending on what you had clicked. */
.pin__lbl { font-family: var(--mono); font-weight: 500; font-size: 19px;
  letter-spacing: .06em; text-transform: uppercase;
  paint-order: stroke; stroke: rgba(11,11,12,.8); stroke-width: 4px; }
.pin.is-on .pin__lbl { font-weight: 600; stroke-width: 5px; }

/* Below the 12px floor, and the only w600 label on the page. */
.card__go { font-size: var(--t-micro); font-weight: 500; letter-spacing: .1em; }

/* -- the superfamily, wired to the optical-size axis ------------------
   One typeface doing two jobs. Display sizes ask for the highest
   optical size, where the letterforms tighten and the spacing closes
   up; paragraphs ask for opsz 14, where they open out and become
   readable. This is the same relationship Sakazuki gets from a display
   cut and a text cut, obtained from one variable font. */
.h-xl, .h-lg, .h-md, .pillar__name, .atlas__name, .phero__t, .pnext__n,
.card__name, .mq__i, .giant, .giant__fill, .cr__g h2, .cr__h h1 {
  /* 400, the same weight the paragraphs run at. Sakazuki sets its whole
     page in one weight and lets size carry the hierarchy; at 500 the
     headings sat close enough to the body to flatten it. */
  font-family: var(--display); font-weight: 400;
  font-variation-settings: "opsz" 96;
  font-optical-sizing: auto; }

/* A grotesque holds far more colour than a Didone at the same size, so
   the giant sizes come down a step and the tracking closes further. */
.h-xl { font-size: clamp(2.7rem, 9vw, 8.4rem); line-height: .9;  letter-spacing: -.035em; }
.h-lg { font-size: clamp(2.2rem, 5.6vw, 4.6rem); line-height: .96; letter-spacing: -.032em; }
.h-md { font-size: clamp(1.85rem, 4vw, 3rem);    line-height: 1;   letter-spacing: -.03em; }
.giant, .giant__fill { letter-spacing: -.01em; }

.body, .lede, .pillar__note, .card__note, .atlas__note, .plead__body p,
.pfact dd, .close__lede, .cr__h p, .credits, .cr__by {
  font-family: var(--sans); font-weight: 400;
  font-variation-settings: "opsz" 14; }

/* ===================================================================
   THE PLANNER
   Rebuilt. It was a form beside a results list: two rows of pills that
   wrapped raggedly into an accidental shape, and five thumbnail rows
   that read as search results rather than as a journey.

   Two moves. The answers now complete a sentence, so choosing produces
   a statement instead of a filled-in form. And the result is drawn as a
   route: one rule running down the page, the day numerals large enough
   to count at a glance, and a real photograph at every stop.
   =================================================================== */

.route__inner { position: relative; z-index: 2; max-width: 64rem; }
.route__bed img { opacity: .32; }

/* -- the sentence ---------------------------------------------------- */
.ask__say { margin: var(--s4) 0 var(--s6); max-width: 30ch;
  font-family: var(--display); font-weight: 400;
  font-variation-settings: "opsz" 96;
  font-size: clamp(1.5rem, 3.4vw, 2.6rem); line-height: 1.18;
  letter-spacing: -.028em; color: var(--soft); }
.ask__fixed { color: var(--soft); }
.ask__val { color: var(--paper); position: relative;
  box-shadow: inset 0 -2px 0 rgba(217,94,34,.55);
  transition: box-shadow var(--t-base) var(--ease-out), color var(--t-base) var(--ease-out); }
.ask__val.is-set { color: var(--accent); box-shadow: inset 0 -2px 0 rgba(217,94,34,0); }
.ask__val:not(.is-set) { color: rgba(242,237,230,.45); font-style: italic; }

/* -- the two questions ----------------------------------------------
   A grid, not flex-wrap. Wrapping is what made the old pills look
   accidental: four labels of different lengths broke 1 / 2 / 1. */
.ask { display: grid; gap: var(--s5); margin-bottom: var(--s7); }
@media (min-width: 900px) { .ask { grid-template-columns: 1.15fr .85fr; gap: var(--s6); } }
.ask__set { margin: 0; padding: 0; border: 0; min-width: 0; }
.ask__legend { padding: 0 0 var(--s2); font-family: var(--mono); font-weight: 500;
  font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase;
  color: var(--soft); }
.ask__grid { display: grid; gap: .5rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .ask__grid { grid-template-columns: 1fr 1fr; } }
.ask__grid--two { grid-template-columns: 1fr; }
@media (min-width: 560px) { .ask__grid--two { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .ask__grid--two { grid-template-columns: 1fr; } }

.ask__opt { appearance: none; cursor: pointer; text-align: left;
  display: grid; gap: .25rem; padding: .85rem .95rem;
  background: rgba(242,237,230,.035); color: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: background var(--t-base) var(--ease-out),
              border-color var(--t-base) var(--ease-out),
              transform var(--t-out) var(--ease-out); }
.ask__opt:hover { background: rgba(242,237,230,.07); border-color: rgba(242,237,230,.3); }
.ask__opt:active { transform: scale(.985); transition-duration: var(--t-fast); }
.ask__opt.is-on { background: var(--accent); border-color: var(--accent); }
.ask__n { font-family: var(--mono); font-weight: 500; font-size: var(--t-micro);
  letter-spacing: .09em; text-transform: uppercase; }
.ask__hint { font-family: var(--sans); font-variation-settings: "opsz" 14;
  font-size: var(--t-small); line-height: 1.45; color: var(--soft); }
.ask__opt.is-on .ask__hint { color: rgba(11,11,12,.78); }
.ask__opt.is-on .ask__n { color: var(--on-accent); }

/* -- the route -------------------------------------------------------
   One rule down the page with a marker per stop. The rule is the thing
   that turns five cards into a journey. */
.route__lead { margin: 0 0 var(--s4); font-family: var(--sans);
  font-variation-settings: "opsz" 14; font-size: var(--t-body);
  line-height: 1.6; color: var(--soft); max-width: 46ch; }
.route__list { list-style: none; margin: 0; padding: 0; position: relative; }
/* The rule is the thing that turns five cards into a journey, so it has
   to actually read. At 1px and 16% alpha at the tail it disappeared. */
.route__list::before { content: ""; position: absolute; left: 15px; top: 12px; bottom: 12px;
  width: 2px; border-radius: 1px; background: linear-gradient(180deg,
    var(--accent) 0%, rgba(217,94,34,.75) 55%, rgba(217,94,34,.28) 100%); }
.mo .route__list::before { transform: scaleY(0); transform-origin: 50% 0;
  transition: transform 1.1s var(--ease); }
.mo .route__list.is-drawn::before { transform: scaleY(1); }

.rstop { position: relative; padding: 0 0 var(--s5) calc(16px + var(--s4)); }
.rstop:last-child { padding-bottom: 0; }
.rstop__mark { position: absolute; left: 7px; top: 8px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--ground);
  box-shadow: inset 0 0 0 2px var(--accent), 0 0 0 5px var(--ground); }
.rstop__mark::after { content: ""; position: absolute; inset: 5px;
  border-radius: 50%; background: var(--accent); opacity: 0;
  transition: opacity var(--t-base) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .rstop:hover .rstop__mark::after { opacity: 1; }
}
.rstop__day { display: block; font-family: var(--mono); font-weight: 500;
  font-size: var(--t-micro); letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin-bottom: .15rem; }
.rstop__a { display: grid; gap: var(--s3); grid-template-columns: 1fr;
  text-decoration: none; color: inherit; border-radius: var(--r);
  transition: transform var(--t-out) var(--ease-out); }
@media (min-width: 640px) { .rstop__a { grid-template-columns: 12rem 1fr;
  align-items: start; gap: var(--s4); } }
.rstop__a:active { transform: scale(.995); transition-duration: var(--t-fast); }
.rstop__shot { margin: 0; overflow: hidden; border-radius: var(--r);
  aspect-ratio: 4 / 3; background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line); }
.rstop__shot img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .8s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .rstop__a:hover .rstop__shot img { transform: scale(1.06); }
  .rstop__a:hover .rstop__n { color: var(--accent); }
}
.rstop__n { margin: 0 0 .3rem; font-family: var(--display); font-weight: 400;
  font-variation-settings: "opsz" 96;
  font-size: clamp(1.35rem, 2.4vw, 1.9rem); line-height: 1.05;
  letter-spacing: -.03em; transition: color var(--t-base) var(--ease-out); }
.rstop__why { margin: 0; font-family: var(--sans);
  font-variation-settings: "opsz" 14; font-size: var(--t-body);
  line-height: 1.6; color: var(--soft); max-width: 52ch; }
.rstop__go { display: inline-flex; align-items: center; gap: .4rem; margin-top: .5rem;
  font-family: var(--mono); font-weight: 500; font-size: var(--t-micro);
  letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
.rstop__go::after { content: ""; width: 1em; height: 1em; flex: none; background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat;
  transition: transform var(--t-base) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .rstop__a:hover .rstop__go::after { transform: translateX(4px); }
}

.mo .rstop { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .mo .rstop { opacity: 1; }
  .mo .route__list::before { transform: scaleY(1); }
  /* Has to live here, after the rules it silences: the site-wide press
     reset sits earlier in the file at the same specificity and loses. */
  .ask__opt:active, .rstop__a:active { transform: none; }
}
