/* Whisper Maps site styles
 *
 * Static CSS, no build step, no framework, no JavaScript. Mobile first at 390px.
 * Tokens come from tokens.css. No hex value is declared in this file.
 *
 * Controlling records, repo-resident under /docs:
 *   Brand Foundation v2.0
 *   City Artwork Design System v4.0
 *   Marketing Site Design Guidelines v4.0
 *
 * Page field rule. Every section is Ink except the Featured Edition and the
 * city cards, which are light Bone fields. That alternation is the frozen
 * composition and is not a free choice.
 */

/* ---------------------------------------------------------------- fonts */
/* Self-hosted. No third-party request at runtime. Licenses ship beside the
 * files. Hanken Grotesk is a variable font: one file serves 400 and 600. */

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/cormorant-garamond-600.woff2") format("woff2");
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/hanken-grotesk-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/hanken-grotesk-variable.woff2") format("woff2");
}

/* ----------------------------------------------------------------- base */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  font-weight: 400;
  overflow-wrap: break-word;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  margin: 0;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img { max-width: 100%; display: block; }

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

/* Ink focus ring on any light field. The city cards carry a Bone background
 * inside a dark section, so they need naming separately from .section--light.
 * Amber against Bone measures 1.61 to 1 and fails the 3 to 1 that a focus
 * indicator needs. Ink against Bone is 15.14 to 1. */
.section--light :focus-visible,
.edition :focus-visible { outline-color: var(--ink); }

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

.skip-link {
  position: absolute;
  left: var(--s2);
  top: -4rem;
  z-index: 10;
  padding: var(--s1) var(--s2);
  background: var(--bone);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  transition: top var(--motion) var(--ease);
}
.skip-link:focus { top: var(--s2); }

/* --------------------------------------------------------------- layout */

.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--s3);
}

.section { padding-block: var(--s5); }

/* Restrained hairline division. Never Amber, which is action only. */
.section--ruled { border-top: 1px solid var(--hairline); }

.section--light {
  background: var(--bone);
  color: var(--ink);
}

.eyebrow {
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bone-faint);
}

.section--light .eyebrow { color: var(--ink-faint); }

.section__title {
  font-size: clamp(1.75rem, 4vw, 2.25rem);
  margin-block: var(--s2) var(--s3);
}

.prose { max-width: var(--measure); color: var(--bone-quiet); }
.section--light .prose { color: var(--ink-quiet); }
.prose + .prose { margin-top: var(--s2); }

/* ------------------------------------------------------- image slots */
/* One shared system for all four replaceable assets.
 *
 * The assets supplied for the CURRENT Home composition are each a complete
 * assembled poster object, carrying their own inset frame, type plate, and
 * lockup in the pixels. So this page adds no frame, no border, and no text
 * around a slot, and no slot crops the current sources. That is a property of
 * today's assets, not a permanent requirement for future artwork. A
 * replacement file drops in without touching composition.
 *
 * No pixel dimensions are tied to a specific image anywhere in this file. */

.img-slot { display: block; width: 100%; }

.img-slot > img {
  width: 100%;
  height: auto;
  object-fit: contain;
  object-position: center;
}

/* Hero and featured poster size from their own artwork, alone in a column.
 * Mobile keeps the featured poster as a modest edition object rather than a
 * near-full-width block. The square source is never cropped or stretched into
 * portrait geometry; only its display size changes. */
.img-slot--hero { max-width: 30rem; margin-inline: auto; }
.img-slot--poster { max-width: 15rem; margin-inline: 0; }

/* Card thumbnails hold one geometry so three cards align whatever the source
 * ratio is. contain rather than cover, so an assembled poster is never cut. */
.img-slot--thumb > img {
  aspect-ratio: 3 / 4;
  height: 100%;
}

/* --------------------------------------------------------------- header */

.site-header {
  padding-block: var(--s3);
  border-bottom: 1px solid var(--hairline);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: center;
  justify-content: space-between;
}

.brand-lockup {
  display: inline-block;
  color: var(--bone);
  text-decoration: none;
  line-height: 1.1;
}

.brand-lockup__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.375rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.brand-lockup__sub {
  display: block;
  margin-top: 0.35em;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  /* Bone, not Amber. The header is Ink, Bone, and Amber for action only, so
   * the brand sub-line cannot carry the action color. Measured 8.07 to 1. */
  color: var(--bone-quiet);
}

.header-actions {
  display: none; /* mobile uses the native details menu instead */
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2) var(--s4);
}

.nav--primary ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

.nav--primary a {
  font-size: var(--text-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-quiet);
  text-decoration: none;
}

.nav--primary a:hover { color: var(--bone); }

/* Mobile menu. Native details and summary, no JavaScript anywhere.
 * Hidden at and above the tablet breakpoint, where .header-actions returns. */

.menu { position: relative; }

.menu__toggle {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.5rem -0.5rem -0.5rem 0;
  color: var(--bone);
  cursor: pointer;
  list-style: none;
}

.menu__toggle::-webkit-details-marker { display: none; }

.menu__bars { display: block; width: 1.5rem; height: 1.5rem; }
.menu__bars svg { width: 100%; height: 100%; }

.menu__panel {
  position: absolute;
  right: 0;
  z-index: 20;
  min-width: 12rem;
  margin-top: var(--s2);
  padding: var(--s2) var(--s3);
  background: var(--crypt);
  border: 1px solid var(--hairline);
}

.menu__panel ul { display: grid; gap: var(--s1); }

.menu__panel a {
  display: block;
  padding-block: 0.4em;
  font-size: var(--text-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-quiet);
  text-decoration: none;
}

.menu__panel a:hover { color: var(--bone); }

/* ----------------------------------------------------------------- hero */

.hero { padding-block: var(--s4) var(--s5); }

.hero__grid { display: grid; gap: var(--s4); align-items: center; }

/* Mobile places the poster before the proposition, per the frozen mobile
 * composition. Order only, so nothing is duplicated in the markup. */
.img-slot--hero { order: 1; }
.hero__copy { order: 2; }

.hero__eyebrow { margin-bottom: var(--s3); color: var(--bone-faint); }

.hero__headline {
  font-size: clamp(2rem, 6.2vw, 3.1rem);
  max-width: 16ch;
  margin-bottom: var(--s3);
}

.hero__sub {
  max-width: 32rem;
  color: var(--bone-quiet);
  margin-bottom: var(--s4);
}

/* -------------------------------------------------- choose / tap / walk */
/* Master-brand treatment. Amber marks only, no city accent. */

.step-flow {
  display: flex;
  align-items: flex-start;
  gap: var(--s2);
  margin-bottom: var(--s4);
}

.step { flex: 0 1 auto; }

.step__mark {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-bottom: var(--s1);
  color: var(--amber);
}

.step__mark svg { width: 100%; height: 100%; }

.step__label {
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone);
}

.step__note {
  font-size: var(--text-eyebrow);
  color: var(--bone-faint);
  letter-spacing: 0.04em;
}

.step-flow__arrow {
  flex: 0 0 auto;
  align-self: center;
  width: 2rem;
  height: 1px;
  margin-top: -1.25rem;
  background: var(--bone-faint);
}

/* ------------------------------------------------------------------ CTA */
/* One dominant Amber action per decision point.
 *
 * Amber is action and activation, never a decorative or city color. In this
 * stylesheet --amber is used by this CTA component, by the master-brand step
 * and beat marks authorized for this Home slice, and by the :focus-visible
 * outline. Those are its only uses. */

.cta-block { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); }

.cta {
  display: inline-block;
  padding: 0.85em 1.5em;
  border: 0;
  border-radius: 2px; /* component-local. Not a global doctrine. */
  background: var(--amber);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: left;
}

.cta--compact { padding: 0.6em 1.05em; font-size: var(--text-small); }

.cta[aria-disabled="true"] { cursor: not-allowed; }

.access-line {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-size: var(--text-small);
  color: var(--bone-quiet);
}

.section--light .access-line { color: var(--ink-quiet); }

.access-line svg { width: 0.9em; height: 0.9em; flex: 0 0 auto; }

.cta-note {
  max-width: 32rem;
  font-size: var(--text-small);
  color: var(--bone-faint);
}

.section--light .cta-note { color: var(--ink-faint); }

/* ------------------------------------------------------ featured edition */
/* The one light field on the page. Savannah edition cues are permitted here:
 * accent-forward framing per the Brand Foundation balance rule, with Amber
 * reserved for the action. */

.featured__grid { display: grid; gap: var(--s5); align-items: start; }

.featured__title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 6vw, 3.25rem);
  font-weight: 600;
  line-height: 1;
  margin-block: var(--s2) var(--s1);
}

.featured__tour {
  font-size: var(--text-body);
  font-weight: 600;
  color: var(--ink);
}

.featured__meta {
  margin-top: var(--s1);
  padding-top: var(--s2);
  border-top: 2px solid var(--accent-deep, var(--hairline-ink));
  font-size: var(--text-small);
  color: var(--ink-quiet);
}

.facts-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
  margin-top: var(--s4);
}

.fact__mark {
  display: grid;         /* a bare span is inline, which ignores width/height */
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-bottom: var(--s1);
  color: var(--accent-deep, var(--ink-faint));
}

.fact__mark svg { width: 100%; height: 100%; }

.fact__label { font-size: var(--text-small); font-weight: 600; color: var(--ink); }
.fact__note { font-size: var(--text-eyebrow); color: var(--ink-faint); letter-spacing: 0.04em; }

/* ------------------------------------------------------------ sample */
/* No audio asset exists. The affordance is present and visibly pending.
 * Nothing autoplays, and no waveform, duration, or timecode is fabricated. */

.sample__title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  margin-block: var(--s2) 0.15em;
}

.sample__kicker { font-size: var(--text-small); color: var(--ink-quiet); }

.sample__player {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin-block: var(--s3);
  padding: var(--s2);
  border: 1px dashed var(--hairline-ink);
}

.sample__mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--hairline-ink);
  border-radius: 50%;
  color: var(--ink-faint);
}

.sample__mark svg { width: 1rem; height: 1rem; }

.sample__pending { font-size: var(--text-small); color: var(--ink-faint); }

/* ------------------------------------------------- how whisper maps works */
/* Master brand. Bone and restrained Amber. No city accent anywhere in here. */

.works__title { text-align: center; }

.beats { display: grid; gap: var(--s4); margin-top: var(--s5); }

.beat { display: flex; gap: var(--s2); align-items: flex-start; }

.beat__mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--amber);
  border-radius: 50%;
  color: var(--amber);
}

.beat__mark svg { width: 1.1rem; height: 1.1rem; }

.beat__label { font-weight: 600; color: var(--bone); }
.beat__note { font-size: var(--text-small); color: var(--bone-quiet); }

/* -------------------------------------------------------- city editions */
/* Ink surrounding section, light cards. One shared chrome. A new city swaps
 * image, name, approved accent, and status. Nothing else changes. */

.editions { display: grid; gap: var(--s3); margin-top: var(--s4); }

.edition {
  display: grid;
  grid-template-columns: 5rem 1fr;
  gap: var(--s2);
  align-items: start;
  padding: var(--s2);
  background: var(--bone);
  color: var(--ink);
  border-left: 3px solid var(--accent, var(--hairline-ink));
}

/* City name is set in Ink, not in the city accent.
 *
 * Measured on the Bone field: Haint Blue 1.43 to 1, Haint Deep 2.30, Indigo
 * 2.42. All three fail WCAG AA even at the 3 to 1 large-text threshold, so an
 * accent-colored city name on a light card is unreadable for some viewers.
 * Brand Foundation v2.0 gives the accent the frame, brand line, rules, and
 * edition cues rather than body or heading text, so the edition signal moves
 * to the card border and the keyline below. Ink on Bone is 15.14 to 1. */
.edition__name {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}

/* Edition keyline. Carries the city cue without carrying the words. */
.edition__keyline {
  display: block;
  width: 2.5rem;
  height: 2px;
  margin-top: 0.5em;
  background: var(--accent-deep, var(--accent, var(--hairline-ink)));
}

.edition__status {
  margin-top: 0.2em;
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.edition__note { margin-top: var(--s1); font-size: var(--text-small); color: var(--ink-quiet); }

/* City-card destination line. Carries either the pending status as plain text
 * or, once that city route exists, the link to it. */
.edition__pending {
  display: inline-block;
  margin-top: var(--s2);
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* --------------------------------------------------------------- footer */
/* Master brand Bone and restrained Amber. No social destinations exist, so
 * none are rendered. Nothing here links to a route that is not built. */

.site-footer {
  padding-block: var(--s4);
  border-top: 1px solid var(--hairline);
}

.site-footer__inner { display: grid; gap: var(--s4); }

.footer__tagline { margin-top: var(--s2); font-size: var(--text-small); color: var(--bone-faint); }

.footer__nav ul { display: flex; flex-wrap: wrap; gap: var(--s3); }

.footer__nav a {
  font-size: var(--text-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-quiet);
  text-decoration: none;
}

.footer__nav a:hover { color: var(--bone); }

.footer__legal {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--hairline);
  font-size: var(--text-small);
  color: var(--bone-faint);
}

/* --------------------------------------------------- savannah edition */
/* Patterns added for the /savannah city-edition page. Nothing in this block
 * is used by the Home, and no existing selector above it is modified.
 *
 * Brand Foundation v2.0 section 05 gives the city accent the frames,
 * keylines, rules, labels, and stop numbers, and keeps Gaslight Amber for
 * action and activation only. Nothing below references --amber.
 *
 * ACCENT CONTRAST. These patterns carry accent on Ink and Crypt fields.
 * Measured against Ink: Haint Blue 10.69 to 1, Haint Deep 6.61 to 1. Both
 * clear WCAG AA and Haint Blue clears AAA. The same accents measured against
 * the light Bone field are 1.43 and 2.30 and fail even at the large-text
 * threshold, so every .section--light override below drops the accent and
 * returns to Ink. Do not remove those overrides.
 *
 * Every accent reference carries a fallback, so a pattern used outside a
 * [data-city] scope degrades to a neutral rather than to nothing. */

/* Edition keyline for section-level use. Carries the city cue without
 * carrying any words. Background, never text, so it is safe on both fields. */
.rule--edition {
  display: block;
  width: 2.5rem;
  height: 2px;
  border: 0;
  margin: var(--s2) 0 0;
  background: var(--accent, var(--hairline));
}

.section--light .rule--edition { background: var(--accent-deep, var(--hairline-ink)); }

/* Short accent label. Dark fields only. The light-field override returns to
 * Ink because an accent label on Bone fails AA at any size. */
.label--edition {
  display: block;
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent, var(--bone-quiet));
}

.section--light .label--edition { color: var(--ink-faint); }

/* ------------------------------------------------------------ stop list */
/* Walking order for a city route. Stop numbers are an accent job named in
 * Brand Foundation v2.0 section 05, so the number carries the edition cue
 * and the name stays in Bone.
 *
 * The list is measure-constrained rather than split into columns, so it
 * encodes nothing about how many stops a tour has. */

.stops {
  max-width: var(--measure);
  margin-top: var(--s4);
}

.stop {
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  gap: var(--s2);
  align-items: baseline;
  padding-block: var(--s2);
}

.stop + .stop { border-top: 1px solid var(--hairline); }

.section--light .stop + .stop { border-top-color: var(--hairline-ink); }

.stop__num {
  font-size: var(--text-small);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: var(--accent, var(--bone-faint));
}

.section--light .stop__num { color: var(--ink-faint); }

.stop__name {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--bone);
}

.section--light .stop__name { color: var(--ink); }

/* ------------------------------------------------------------------ faq */
/* Native details and summary, no JavaScript, matching the header menu.
 * Editorial hairlines rather than cards. */

.faq {
  max-width: var(--measure);
  margin-top: var(--s4);
}

.faq__item { border-top: 1px solid var(--hairline); }
.faq__item:last-child { border-bottom: 1px solid var(--hairline); }

.section--light .faq__item { border-top-color: var(--hairline-ink); }
.section--light .faq__item:last-child { border-bottom-color: var(--hairline-ink); }

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  min-height: 2.75rem;
  padding-block: var(--s2);
  font-weight: 600;
  color: var(--bone);
  cursor: pointer;
  list-style: none;
}

.faq__q::-webkit-details-marker { display: none; }

.section--light .faq__q { color: var(--ink); }

/* Chevron drawn from borders rather than a generated character, so no
 * decorative glyph reaches assistive technology. */
.faq__q::after {
  content: "";
  flex: 0 0 auto;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.25rem;
  border-right: 1.5px solid var(--accent, var(--bone-faint));
  border-bottom: 1.5px solid var(--accent, var(--bone-faint));
  transform: translateY(-0.15em) rotate(45deg);
  transition: transform var(--motion) var(--ease);
}

.faq__item[open] .faq__q::after { transform: translateY(0.1em) rotate(-135deg); }

.section--light .faq__q::after {
  border-right-color: var(--ink-faint);
  border-bottom-color: var(--ink-faint);
}

.faq__a {
  max-width: var(--measure);
  padding-bottom: var(--s3);
  color: var(--bone-quiet);
}

.section--light .faq__a { color: var(--ink-quiet); }

/* -------------------------------------------------------- pricing rows */
/* Local anchors first, then the Whisper Maps row. Editorial hairlines, not a
 * commodity price table: no zebra fill, no badges, no boxed cells.
 *
 * Amber is absent from this block. A comparison row is not an action, and
 * the purchase action stays with the existing .cta component. The edition
 * accent marks which row is ours, which is how it leads without borrowing
 * the action color. */

.price-rows {
  max-width: var(--measure);
  margin-top: var(--s4);
}

.price-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s2) var(--s3);
  align-items: baseline;
  padding-block: var(--s3);
  border-top: 1px solid var(--hairline);
}

.section--light .price-row { border-top-color: var(--hairline-ink); }

.price-row__label { color: var(--bone-quiet); }
.section--light .price-row__label { color: var(--ink-quiet); }

.price-row__value {
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--bone);
}

.section--light .price-row__value { color: var(--ink); }

.price-row--ours { border-top: 2px solid var(--accent, var(--hairline)); }

.section--light .price-row--ours { border-top-color: var(--accent-deep, var(--hairline-ink)); }

.price-row--ours .price-row__label { color: var(--bone); }
.section--light .price-row--ours .price-row__label { color: var(--ink); }

.price-row--ours .price-row__value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1;
}

/* Supporting per-person math. D89 keeps it inside pricing context and never
 * leading, so it sits quiet and below the row it supports. */
.price-row__note {
  grid-column: 1 / -1;
  margin-top: var(--s1);
  font-size: var(--text-small);
  color: var(--bone-faint);
}

.section--light .price-row__note { color: var(--ink-faint); }

/* ------------------------------------------------------- editorial list */
/* The base reset removes markers from every ul and ol, so a content list on
 * a new page would have none. This is the one shared list pattern the
 * mechanics and practicals sections need.
 *
 * The marker is a drawn rule rather than a character, so no dash-like glyph
 * enters the markup. .beats is not reused here because its marks are Amber,
 * which is action only and cannot decorate content. */

.editorial-list {
  display: grid;
  gap: var(--s2);
  max-width: var(--measure);
  margin-top: var(--s3);
}

.editorial-list > li {
  position: relative;
  padding-left: var(--s3);
  color: var(--bone-quiet);
}

.section--light .editorial-list > li { color: var(--ink-quiet); }

.editorial-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 0.5rem;
  height: 1px;
  background: var(--accent, var(--bone-faint));
}

.section--light .editorial-list > li::before { background: var(--ink-faint); }

/* A city page stacks the facts row and the sample block in one light field,
 * where they are adjacent siblings and would otherwise touch. The Home places
 * the same two components in separate grid columns, so this pair never matches
 * there and Home spacing is unchanged. The token matches the gap the featured
 * grid already uses to separate them. */
.facts-row + #listen { margin-top: var(--s5); }

/* --------------------------------------------------------- breakpoints */

@media (min-width: 44rem) {
  .wrap { padding-inline: var(--s4); }
  .beats { grid-template-columns: repeat(3, 1fr); gap: var(--s3); }
  /* auto-fit rather than a fixed three, because a 1fr track keeps an auto
   * minimum and cannot shrink below a card's min-content. Three cards need
   * about 1150px, so a fixed three overflowed the page from 704px to there.
   * The 22rem floor sits just above the widest card's min-content, so a track
   * is never narrower than the card in it. Three across still resolves at the
   * desktop widths the composition was accepted at. */
  .editions { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
  .site-footer__inner { grid-template-columns: 1fr auto; align-items: start; }
  .site-footer { padding-block: var(--s5); }
  .edition { grid-template-columns: 6rem 1fr; gap: var(--s3); padding: var(--s3); }
  .img-slot--poster { max-width: 24rem; }

  /* Desktop navigation returns, mobile menu goes away. Exactly one of the two
   * is in the accessibility tree at any width. */
  .menu { display: none; }
  .header-actions { display: flex; }

  /* Desktop restores copy first, poster second. */
  .hero__copy { order: 1; }
  .img-slot--hero { order: 2; }
}

@media (min-width: 62rem) {
  .section { padding-block: var(--s6); }
  .hero { padding-block: var(--s4) var(--s6); }
  /* Right column carries roughly half the inner hero, per the frozen desktop
   * composition. Hero slot only. Other poster slots are untouched. */
  .hero__grid { grid-template-columns: 1fr minmax(24rem, 34rem); gap: var(--s6); }
  .img-slot--hero { max-width: 34rem; }
  .featured__grid { grid-template-columns: 1.2fr minmax(15rem, 21rem) 1fr; gap: var(--s5); }
  .facts-row { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
  .edition { grid-template-columns: 8rem 1fr; }
  .img-slot--hero, .img-slot--poster { margin-inline: 0; }
}

/* ------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
