/* ==========================================================================
   Dukes — fresh UI candidate v2
   A compact original design system. Nothing here is inherited from the current
   Dukes site, from either earlier direction study, or from the Apex reference.

   Visual idea: a prepared property file. Warm bone paper, bottle-green ink,
   copper rules. Every section is opened by a numbered chapter rule; every image
   sits in a labelled mount; every claim carries a status plate.
   ========================================================================== */

/* --- Self-hosted text face. No font is requested from another domain. ------ */
@font-face {
  font-family: "Manrope";
  /* format("woff2") — NOT format("woff2-variations").
     The latter is a legacy alias only Chromium ever accepted. WebKit treats it
     as an unsupported format, so Safari was silently never loading Manrope at
     all: every Apple device fell back to system sans, and document.fonts.ready
     never settled, which is what left the homepage's load event hanging for
     30-50s and made the WebKit half of the test suite time out.
     The file is a variable woff2 either way; the axis range is declared by
     font-weight below, which is what actually enables the variation. */
  src: url("/assets/fonts/manrope-latin-var.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Surfaces */
  --bone: #f1eadc;
  --bone-raised: #faf6ed;
  --bone-sunk: #e4d7c1;
  --bottle: #12362b;
  --bottle-deep: #0b231c;

  /* Foregrounds */
  --ink: #111a16;
  --ink-soft: #4a554e;
  --on-deep: #f6f4ef;
  --on-deep-soft: #c9d2cb;

  /* Accents. Copper is a working colour on light surfaces (5.8:1 on bone);
     sand is its counterpart on the bottle surface (5.2:1). Crown gold from the
     logo is never used for text. */
  --copper: #8f5024;
  --copper-deep: #6f3d1b;
  --sand: #efc29a;

  /* The hero's depth is layered from the two greens the brand already owns —
     no third hue competes with them. Crest red is the red in the Dukes lion,
     allowed only as a 3px rule on an active route. */
  --forest-shade: #071a14;
  --crest: #7b1e2b;

  /* Lines */
  --rule: rgba(17, 26, 22, 0.16);
  --rule-strong: rgba(17, 26, 22, 0.42);
  --rule-on-deep: rgba(246, 244, 239, 0.24);

  /* Semantic roles, switched per surface by .on-deep */
  --fg: var(--ink);
  --fg-soft: var(--ink-soft);
  --accent: var(--copper);
  --line: var(--rule);
  --focus-ring: var(--ink);
  --focus-halo: rgba(143, 80, 36, 0.28);

  /* Space */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4rem;
  --s9: 6rem;
  --s10: 8rem;

  /* Structure */
  --inset: clamp(1.25rem, 4vw, 4.5rem);
  --measure: 68ch;
  --max: 1320px;
  --radius-structural: 0;
  --radius-control: 2px;
  --radius-mount: 4px;

  /* Type */
  --font-display: "Palatino Linotype", "Book Antiqua", Palatino, "Iowan Old Style",
    "Hoefler Text", Georgia, "Times New Roman", serif;
  --font-text: "Manrope", ui-sans-serif, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --t-hero: clamp(2.7rem, 1.5rem + 4.3vw, 5rem);
  --t-display: clamp(2.5rem, 1.5rem + 3.7vw, 4.6rem);
  --t-display-sm: clamp(2rem, 1.35rem + 2.6vw, 3.3rem);
  --t-section: clamp(1.5rem, 1.15rem + 1.5vw, 2.35rem);
  --t-group: clamp(1.125rem, 1rem + 0.5vw, 1.4rem);
  --t-body: 1.0625rem;
  --t-small: 0.9rem;
  --t-label: 0.75rem;

  /* Motion */
  --quick: 140ms;
  --standard: 220ms;
  --compose: 480ms;
  --slow: 700ms;
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-arrive: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
}

*,
*::before,
*::after { box-sizing: border-box; }

/* Component display rules are more specific than the UA rule for [hidden], so
   state this once rather than fighting it per component. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  /* Anchors land below the sticky header rather than under it. */
  --head-h: 61px;
  scroll-padding-top: calc(var(--head-h) + 1rem);
}
@media (min-width: 64em) {
  html { --head-h: 84px; }
}

/* A fallback for engines that ignore scroll-padding on a given navigation. */
:where(#dukes-receptionist, #enquiry, #compare, #how, #scope, #fees, #consider, [id^="gr-"], [id^="epc-"]) {
  scroll-margin-top: calc(var(--head-h) + 1rem);
}

body {
  margin: 0;
  background: var(--bone);
  color: var(--fg);
  font-family: var(--font-text);
  font-size: var(--t-body);
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; }

/* ------------------------------- Typography ------------------------------- */

h1, h2, h3, h4 {
  margin: 0 0 var(--s4);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

p { margin: 0 0 var(--s4); max-width: var(--measure); }

.h-display {
  font-family: var(--font-display);
  font-size: var(--t-display);
  line-height: 1.02;
  letter-spacing: -0.018em;
}
.h-display span { display: block; }
.h-display--sm { font-size: var(--t-display-sm); }

.h-hero {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-hero);
  line-height: 0.98;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.h-hero span { display: block; }

.h-section {
  font-family: var(--font-display);
  font-size: var(--t-section);
  line-height: 1.1;
}

.h-group {
  font-family: var(--font-text);
  font-size: var(--t-group);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.eyebrow {
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--copper);
}

.lede {
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  color: var(--fg-soft);
  max-width: 58ch;
}

.note {
  font-size: var(--t-small);
  color: var(--fg-soft);
  max-width: 62ch;
  border-left: 2px solid var(--line);
  padding-left: var(--s4);
}

.reviewed {
  font-size: var(--t-small);
  color: var(--fg-soft);
  font-style: italic;
}

.u-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------- Focus ---------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
  border-radius: var(--radius-control);
}

.skip {
  position: absolute;
  left: var(--s4);
  top: -4rem;
  z-index: 100;
  background: var(--bottle);
  color: var(--on-deep);
  padding: var(--s3) var(--s5);
  text-decoration: none;
  transition: top var(--quick) var(--ease-in-out);
}
.skip:focus { top: var(--s4); }

/* --------------------------------- Links ---------------------------------- */

a { color: inherit; }

.link {
  color: var(--copper-deep);
  text-decoration: none;
  font-weight: 600;
  position: relative;
  display: inline-block;
  padding: 2px 0;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(1);
  transform-origin: center;
  transition: transform var(--standard) var(--ease-in-out);
}
.link:hover::after { transform: scaleX(0.35); }
.link--arrow::before {
  content: "→";
  display: inline-block;
  margin-right: 0.5em;
  transition: transform var(--standard) var(--ease-in-out);
}
.link--arrow:hover::before { transform: translateX(3px); }

/* -------------------------------- Buttons --------------------------------- */

.btn {
  --btn-fill: var(--bottle);
  --btn-fg: var(--on-deep);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--s3) var(--s6);
  border: 1px solid var(--btn-fill);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--btn-fg);
  font: inherit;
  font-weight: 700;
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--quick) var(--ease-in-out), transform var(--quick) var(--ease-in-out);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-fill);
  transform: scaleY(1);
  transform-origin: center;
  transition: transform var(--standard) var(--ease-in-out);
}
/* A restrained edge light on hover and focus. No pulse, no bloom. */
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(143, 80, 36, 0);
  transition: box-shadow var(--standard) var(--ease-in-out);
  pointer-events: none;
}
.btn:hover::after { box-shadow: 0 0 0 4px rgba(143, 80, 36, 0.16), 0 6px 18px -12px rgba(17, 26, 22, 0.55); }
.btn--primary:hover::before { transform: scaleY(0.9); }
.btn--primary:hover { color: var(--btn-fg); }
.btn:active { transform: scale(0.985); }

.btn--quiet {
  --btn-fill: transparent;
  --btn-fg: var(--ink);
  border-color: var(--rule-strong);
}
.btn--quiet:hover { border-color: var(--copper); color: var(--copper-deep); }

.btn--ghost {
  --btn-fill: transparent;
  --btn-fg: var(--ink);
  border-color: var(--rule-strong);
  min-height: 44px;
  padding: var(--s2) var(--s5);
}
.btn--ghost:hover { border-color: var(--bottle); }

/* On dark surfaces the primary action is warm sand, and the secondary is a
   hairline outline that lights at its edge. */
.btn--gold {
  --btn-fill: var(--sand);
  --btn-fg: #0b231c;
  border-color: var(--sand);
  color: var(--btn-fg);
}
.btn--gold:hover::before { transform: scaleY(0.9); }
.btn--gold:hover::after { box-shadow: 0 0 0 4px rgba(239, 194, 154, 0.24), 0 8px 22px -14px rgba(0, 0, 0, 0.8); }

.btn--outline {
  --btn-fill: transparent;
  --btn-fg: var(--on-deep);
  border-color: rgba(246, 244, 239, 0.42);
}
.btn--outline:hover { border-color: var(--sand); color: var(--sand); }
.btn--outline:hover::after { box-shadow: 0 0 0 4px rgba(239, 194, 154, 0.18); }

/* -------------------------------- Header ---------------------------------- */

.site-head {
  /* Sticky, not a scripted hide/reveal: the browser's own compositor keeps it
     flush with the top, so it cannot lag the page or expose a strip. */
  position: sticky;
  top: 0;
  z-index: 1000;
  width: 100%;
  isolation: isolate;
  /* Warm beige into cream, opaque enough that moving film cannot bleed through. */
  background:
    radial-gradient(circle at 50% -70%, rgb(250 244 233 / 60%), transparent 52%),
    linear-gradient(100deg, #ddceb6 0%, #ece1cf 48%, #ded0b8 100%);
  border-bottom: 1px solid rgb(143 80 36 / 38%);
  box-shadow: 0 8px 24px -22px rgb(11 35 28 / 72%);
}
.site-head__inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--s2) var(--inset);
  display: flex;
  align-items: center;
  gap: var(--s5);
  min-height: 60px;
}
.brand {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: var(--s2);
  text-decoration: none;
  flex: 0 0 auto;
}
.brand__mark {
  display: block;
  width: auto;
  height: 42px;
  /* Genuine artwork: stationary, unchanged proportions, never recoloured. */
}
.brand__ring {
  position: absolute;
  inset: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  transition: border-color var(--standard) var(--ease-in-out), inset var(--standard) var(--ease-in-out);
}
.brand:hover .brand__ring,
.brand:focus-visible .brand__ring { border-color: var(--copper); inset: -2px; }

.nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: var(--s5);
  flex-wrap: wrap;
}
.nav__item { display: flex; align-items: baseline; gap: var(--s2); }
.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  font-weight: 600;
  font-size: var(--t-small);
  letter-spacing: 0.01em;
  border-bottom: 2px solid transparent;
  transition: border-color var(--standard) var(--ease-in-out), color var(--standard) var(--ease-in-out);
}
.nav__link:hover { border-color: var(--copper); }
.nav__link[aria-current="page"] { border-color: var(--bottle); }
.nav__flag {
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--copper);
  white-space: nowrap;
}
.nav--wide { display: none; margin-inline: auto; }
.site-head__cta { display: none; }

.menu { margin-left: auto; }
.menu__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 44px;
  min-width: 44px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  font-weight: 700;
  font-size: var(--t-small);
  cursor: pointer;
  list-style: none;
}
.menu__button::-webkit-details-marker { display: none; }
.menu__glyph {
  width: 16px; height: 2px;
  background: currentColor;
  box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor;
}
.menu[open] .menu__glyph { box-shadow: 0 0 0 currentColor; transform: rotate(45deg); }
.menu__panel {
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  max-height: calc(100svh - var(--head-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bone-raised);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: var(--s5) var(--inset) var(--s6);
}
.menu__panel .nav__list { flex-direction: column; gap: 0; }
.menu__panel .nav__item { border-bottom: 1px solid var(--line); }
.menu__panel .nav__link { min-height: 48px; font-size: 1rem; width: 100%; }
.menu__cta { margin-top: var(--s4); width: 100%; }

/* The prototype notice is a hairline strip, not a banner. */
.site-head__band {
  margin: 0;
  max-width: none;
  padding: 5px var(--inset);
  background: var(--bottle-deep);
  color: rgba(246, 244, 239, 0.62);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
}

/* --------------------------------- Layout --------------------------------- */

.main { display: block; }
.main:focus { outline: none; }

.band,
.hero,
.page-open,
.closing,
.steps,
.reception__inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(3rem, 7vw, 8rem) var(--inset);
}

.band { border-top: 0; }

/* Surface rhythm. Chapters alternate between the warm page, a raised panel and
   a full-bleed dark field so a long page never collapses into one beige column. */
.band--raised {
  max-width: none;
  background: var(--bone-sunk);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.band--raised > * { max-width: var(--max); margin-inline: auto; }

.band--dark {
  max-width: none;
  background:
    radial-gradient(70% 60% at 88% 10%, rgba(143, 80, 36, 0.28), transparent 62%),
    linear-gradient(180deg, #0b231c 0%, #12362b 100%);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
  --line: var(--rule-on-deep);
  --rule: var(--rule-on-deep);
  --rule-strong: rgba(246, 244, 239, 0.4);
}
.band--dark > * { max-width: var(--max); margin-inline: auto; }
.band--dark .chapter__index,
.band--dark .eyebrow { color: var(--sand); }
.band--dark .chapter__label { color: var(--on-deep-soft); }
.band--dark .evidence__record { background: rgba(246, 244, 239, 0.05); border-color: var(--rule-on-deep); }
.band--dark .plate { background: rgba(246, 244, 239, 0.06); }
.band--dark .plate--public .plate__tag { color: var(--sand); }
.band--dark .link { color: var(--sand); }

.band__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s5);
  margin-top: var(--s6);
  max-width: none;
}
.band__aside { font-size: var(--t-small); color: var(--fg-soft); }

.band__head { margin-bottom: var(--s6); }

.band__split {
  display: grid;
  gap: var(--s6);
  align-items: start;
}
.band__minor { min-width: 0; }
.band__major { min-width: 0; }

.split-two {
  display: grid;
  gap: var(--s5);
}

/* ---------------------------- Chapter rule -------------------------------- */

.chapter {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-bottom: var(--s6);
}
.chapter__index {
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--copper);
  letter-spacing: 0.04em;
}
.chapter__label {
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-soft);
  white-space: nowrap;
}
.chapter__rule {
  flex: 1 1 auto;
  height: 1px;
  background: var(--rule-strong);
  transform-origin: left center;
}

/* ---------------------------------- Hero ---------------------------------- */

.hero {
  padding-top: var(--s7);
  padding-bottom: var(--s8);
  display: grid;
  gap: var(--s6);
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4);
  margin: var(--s6) 0 0;
  max-width: none;
}

/* ---------------------- Home: the cinematic stage ------------------------- *
   Three panels. Two warm photographic side panels frame a centred film, and
   every word sits centred inside that film. The panels are atmosphere: they
   frame the work, they do not evidence it — the sourced reviews and the
   verified records below the hero do that.

   The film is contained at the aspect it was shot at, never cropped to fit and
   never enlarged past the resolution delivered.                              */

.hero--stage {
  /* 3456 × 2160: the master's true picture area, which is 16:10 rather than the
     16:9 its container implies. */
  --film-ar: 1.6;
  --stage-h: clamp(34rem, calc(78svh - 2.5rem), 48rem);
  --curtain-travel: 250%;

  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto auto auto;
  gap: 0;
  max-width: none;
  padding: 0;
  overflow: hidden;
  background: var(--bottle-deep);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.45);
  --line: var(--rule-on-deep);
}

/* The wrapper exists to carry the decorative role. Its three children take part
   in the hero's own grid so the copy can sit in the centre column. */
.stage { display: contents; }

/* ---- Side panels ---- */
/* The inner edge feathers away so the three panels read as one photograph
   rather than three tiles pushed together. */
.stage__curtain-media,
/* Deliberate focal points: the lit doorway on the left, the keys and folder on
   the right. Neither is cropped away at any column width. */

/* One grade shared by all three panels: bottle-green shadow, amber dusk
   highlight, and a soft inner edge so the photographs meet the film rather
   than butting against it. */



/* ---- The centre ---- */


/* The frame fills the centre column and the film is contained inside it, so the
   picture is shown whole at every width — never cropped, never stretched, and
   never scaled beyond the resolution that was encoded. The space it does not
   fill is the forest atmosphere behind it. */
.stage__poster,
.stage__poster img,
.stage__video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  /* Cover, with a deliberate focal point: the horizon and the sun stay in
     frame and the useful aerial detail is not cropped away. */
  object-fit: cover;
  object-position: 50% 44%;
}
.stage__video {
  opacity: 0;
  transition: opacity var(--slow) var(--ease-in-out);
}
.stage__video.is-playing { opacity: 1; }


/* The only green over the film: a restrained pool behind the centred copy. */

/* ---- The words ---- */
.hero__panel {
  position: relative;
  z-index: 4;
  width: min(760px, calc(100vw - var(--inset) * 2));
  margin: auto auto 0;
  padding: 0 0 clamp(2rem, 5vh, 3.25rem);
  gap: var(--s4);
  text-align: center;
  display: grid;
  gap: var(--s5);
  justify-items: center;
}
.hero__title,
.hero__copy { width: 100%; max-width: 40rem; margin: 0 auto; }
.hero__title { margin-bottom: var(--s5); }

.hero__eyebrow {
  display: inline-block;
  margin: 0 0 var(--s4);
  padding: 6px 14px;
  max-width: none;
  border: 1px solid rgba(239, 194, 154, 0.45);
  border-radius: var(--radius-control);
  background: rgba(11, 35, 28, 0.62);
  color: var(--sand);
  font-size: 0.875rem;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.hero--stage .h-hero {
  font-size: clamp(2.25rem, 1.1rem + 3.6vw, 4.25rem);
  text-shadow: 0 2px 26px rgba(6, 18, 14, 0.6);
}
.hero--stage .hero__lede {
  color: var(--on-deep);
  max-width: 42ch;
  margin-inline: auto;
  text-shadow: 0 1px 18px rgba(6, 18, 14, 0.6);
}
.hero--stage .hero__actions {
  margin-top: var(--s5);
  max-width: none;
  justify-content: center;
}
.hero__proof { margin: var(--s5) 0 0; font-size: var(--t-small); }
.hero--stage .link { color: var(--sand); }

/* ------------------------------ Route dock -------------------------------- *
   Four ruled zones on the lower edge of the film. Every row is one real link.  */

.dock {
  position: relative;
  z-index: 2;
  grid-row: 3;
  grid-column: 1;
  width: 100%;
  border-top: 1px solid rgba(239, 194, 154, 0.22);
  background: linear-gradient(180deg, rgba(11, 35, 28, 0.86) 0%, rgba(7, 26, 20, 0.96) 100%);
}
/* The photography drops down into the green rather than stopping at a hard
   edge: the dock rides up over the foot of all three panels. */
.dock::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 96px;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 0%, rgba(11, 20, 16, 0.34) 55%, rgba(11, 28, 22, 0.78) 100%);
}
.dock__list {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: var(--max);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.dock__item { border-top: 1px solid rgba(246, 244, 239, 0.14); }
.dock__item:nth-child(-n + 2) { border-top: 0; }
.dock__item:nth-child(2n) { border-left: 1px solid rgba(246, 244, 239, 0.14); }

.dock__link {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  /* Rows pack from the top so the audience label and the action sit on the same
     line across all four zones, whether or not a route carries a pending flag. */
  align-content: start;
  gap: 2px var(--s3);
  min-height: 76px;
  height: 100%;
  padding: var(--s3) var(--s4);
  text-decoration: none;
  color: var(--on-deep);
  transition: background-color 90ms var(--ease-in-out);
}
/* The one restrained crest-red note: an active rule, never a wash. */
.dock__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 3px;
  background: var(--crest);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 260ms var(--ease-in-out);
}
.dock__link:hover,
.dock__link:focus-visible { background: rgba(246, 244, 239, 0.07); }
.dock__link:hover::after,
.dock__link:focus-visible::after { transform: scaleX(1); }

.dock__label {
  grid-column: 1;
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin-bottom: 2px;
}
.dock__index {
  font-family: var(--font-display);
  font-size: 0.8125rem;
  color: var(--sand);
  letter-spacing: 0.06em;
}
.dock__audience {
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--sand);
}
.dock__action {
  grid-column: 1;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 0.95rem + 0.55vw, 1.6rem);
  line-height: 1.15;
  color: var(--on-deep);
}
.dock__flag {
  grid-column: 1;
  justify-self: start;
  margin-top: var(--s2);
  padding: 2px 7px;
  border: 1px solid rgba(246, 244, 239, 0.34);
  border-radius: var(--radius-control);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--on-deep-soft);
}
.dock__cue {
  grid-column: 2;
  grid-row: 1 / -1;
  align-self: center;
  color: var(--sand);
  font-size: 1.15rem;
  transition: transform 220ms var(--ease-in-out);
}
.dock__link:hover .dock__cue,
.dock__link:focus-visible .dock__cue { transform: translateX(4px); }

.hero__inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(2rem, 3.4vw, 3.25rem) var(--inset) 0;
  display: grid;
  gap: var(--s6);
  align-items: center;
}
.hero__copy { min-width: 0; }
.hero__lede {
  font-size: clamp(1.0625rem, 0.98rem + 0.55vw, 1.35rem);
  color: var(--on-deep-soft);
  max-width: 44ch;
  margin-top: var(--s4);
}
.hero__media { min-width: 0; }
.eyebrow--light { color: var(--sand); }

/* Landlords: a light hero whose decision module is the main event. */
.hero--service { display: block; max-width: none; padding: 0; background: var(--bone); }
.hero--service .hero__inner { padding-bottom: var(--s7); }

.chooser {
  list-style: none;
  margin: var(--s6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
  border-top: 1px solid var(--rule-strong);
}
.chooser__item { border-bottom: 1px solid var(--rule); }
.chooser__link {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s3) var(--s4);
  min-height: 60px;
  padding: var(--s3) var(--s3) var(--s3) 0;
  text-decoration: none;
  color: inherit;
  transition: padding-left var(--standard) var(--ease-in-out), background-color var(--standard) var(--ease-in-out);
}
.chooser__link:hover,
.chooser__link:focus-visible { padding-left: var(--s3); background: var(--bone-sunk); }
.chooser__name { font-weight: 700; font-size: 1.0625rem; }
.chooser__for { grid-column: 1 / -1; font-size: var(--t-small); color: var(--fg-soft); max-width: 48ch; }
.chooser__cue { color: var(--copper); transition: transform var(--standard) var(--ease-in-out); }
.chooser__link:hover .chooser__cue,
.chooser__link:focus-visible .chooser__cue { transform: translateX(4px); }

/* Properties: the search sits inside the hero scene rather than on a white slab. */
.hero--search {
  position: relative;
  display: block;
  max-width: none;
  padding: 0;
  background: #0b231c;
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
  overflow: hidden;
}
/* The search hero used to mount a media placeholder as its scene, which is why
   the page opened on a mushroom-grey slab wearing a "21:9" badge and a "mobile
   crop" guide. Those rules went with the mount; the replacement wash is in the
   search-hero block at the end of this sheet. */
.hero__inner--search { position: relative; display: block; padding-bottom: var(--s7); }
.hero--search .h-display,
.hero--search .h-display--sm { color: var(--on-deep); }

/* Scoped to the hero so these win over the standalone .search rules defined
   further down the sheet. */
.hero--search .search--hero {
  margin-top: var(--s5);
  background: rgba(11, 35, 28, 0.86);
  border-top: 3px solid var(--sand);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
}
.hero--search .form__label,
.hero--search .search__legend { color: var(--on-deep); }
.hero--search .form__control {
  background: rgba(246, 244, 239, 0.08);
  border-color: rgba(246, 244, 239, 0.34);
  color: var(--on-deep);
}
.hero--search .form__control:hover { border-color: var(--sand); }
.hero--search .form__control option { color: var(--ink); background: var(--bone-raised); }
.hero--search .btn--primary { --btn-fill: var(--sand); --btn-fg: #0b231c; border-color: var(--sand); color: #0b231c; }
.hero--search .btn--quiet { --btn-fg: var(--on-deep); border-color: rgba(246, 244, 239, 0.42); }
.hero--search .btn--quiet:hover { border-color: var(--sand); color: var(--sand); }
.hero--search .search__note,
.hero--search .search__toggle { color: var(--on-deep-soft); }
.hero--search .search__flag { color: var(--sand); }
.hero--search .plate { background: rgba(246, 244, 239, 0.08); border-left-color: var(--sand); }
.hero--search .plate__tag { color: var(--sand); }
.hero--search .plate__detail { color: var(--on-deep-soft); }

.page-open {
  display: grid;
  gap: var(--s6);
  padding-top: var(--s7);
}
.page-open--tight { padding-bottom: var(--s6); }

.anchors { list-style: none; margin: var(--s5) 0; padding: 0; display: grid; gap: var(--s2); }
.anchors--row {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--inset) var(--s5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

.whatnext {
  margin: var(--s5) 0;
  padding-left: 1.2em;
  color: var(--fg-soft);
  max-width: 46ch;
}

/* ------------------------- Designed media mount --------------------------- */

/* The mount holds the space a photograph or film will occupy. The default state
   is an art-directed storyboard surface with crop guides; the written brief sits
   behind a closed inspector so the page reads as a website, not a worksheet. */
.mount {
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius-mount);
  background: var(--bone-raised);
  overflow: hidden;
  container-type: inline-size;
}

.mount__scene {
  position: relative;
  aspect-ratio: var(--mount-ar-mobile, 1.5);
  display: grid;
  place-items: center;
  overflow: hidden;
  color: var(--sand);
  background:
    radial-gradient(120% 90% at 22% 12%, rgba(239, 194, 154, 0.16), transparent 60%),
    radial-gradient(100% 80% at 88% 88%, rgba(143, 80, 36, 0.28), transparent 62%),
    linear-gradient(158deg, #0b231c 0%, #12362b 52%, #1d3a2c 78%, #2a3a2c 100%);
}
.mount__art {
  width: min(58%, 15rem);
  height: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.32;
}

/* Crop guides: corner marks, a thirds grid and the mobile crop band. */
.mount__guide {
  position: absolute;
  width: 22px; height: 22px;
  border: 0 solid rgba(239, 194, 154, 0.5);
}
.mount__guide--tl { top: 14px; left: 14px; border-top-width: 1px; border-left-width: 1px; }
.mount__guide--tr { top: 14px; right: 14px; border-top-width: 1px; border-right-width: 1px; }
.mount__guide--bl { bottom: 14px; left: 14px; border-bottom-width: 1px; border-left-width: 1px; }
.mount__guide--br { bottom: 14px; right: 14px; border-bottom-width: 1px; border-right-width: 1px; }
.mount__thirds {
  position: absolute;
  inset: 14px;
  background:
    linear-gradient(90deg, transparent calc(33.33% - 0.5px), rgba(246, 244, 239, 0.09) calc(33.33% - 0.5px) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px)),
    linear-gradient(90deg, transparent calc(66.66% - 0.5px), rgba(246, 244, 239, 0.09) calc(66.66% - 0.5px) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px)),
    linear-gradient(180deg, transparent calc(33.33% - 0.5px), rgba(246, 244, 239, 0.09) calc(33.33% - 0.5px) calc(33.33% + 0.5px), transparent calc(33.33% + 0.5px)),
    linear-gradient(180deg, transparent calc(66.66% - 0.5px), rgba(246, 244, 239, 0.09) calc(66.66% - 0.5px) calc(66.66% + 0.5px), transparent calc(66.66% + 0.5px));
}
.mount__crop {
  position: absolute;
  top: 14px; bottom: 14px;
  left: 50%;
  width: min(34%, 9rem);
  transform: translateX(-50%);
  border-left: 1px dashed rgba(239, 194, 154, 0.42);
  border-right: 1px dashed rgba(239, 194, 154, 0.42);
  display: none;
}
.mount__crop-label {
  position: absolute;
  bottom: 6px; left: 50%;
  transform: translateX(-50%);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(239, 194, 154, 0.75);
  white-space: nowrap;
}
.mount__ratio {
  position: absolute;
  top: 14px; left: 50%;
  transform: translateX(-50%);
  font-size: 0.5625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(246, 244, 239, 0.55);
}

/* The plate is always a bone surface, so it resets the surface tokens rather
   than inheriting the dark-band foregrounds it may be sitting inside. */
.mount__plate {
  padding: var(--s4) var(--s5) var(--s5);
  display: grid;
  gap: var(--s2);
  background: var(--bone-raised);
  border-top: 1px solid rgba(17, 26, 22, 0.16);
  color: var(--ink);
  --fg: var(--ink);
  --fg-soft: var(--ink-soft);
  --rule: rgba(17, 26, 22, 0.16);
  --rule-strong: rgba(17, 26, 22, 0.42);
  --line: rgba(17, 26, 22, 0.16);
  --focus-ring: var(--ink);
  --focus-halo: rgba(143, 80, 36, 0.28);
}
.mount__banner {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
  max-width: none;
}
.mount__flag {
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--copper-deep);
}
.mount__id {
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  padding: 3px 8px;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  color: var(--fg-soft);
}
.mount__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.25;
  color: var(--ink);
  max-width: 34ch;
}
.mount__meta,
.mount__replace {
  margin: 0;
  font-size: var(--t-small);
  color: var(--fg-soft);
  max-width: 46ch;
}
.mount__replace { color: var(--copper-deep); }

.mount__inspect { margin-top: var(--s2); }
.mount__summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--fg-soft);
  cursor: pointer;
  list-style: none;
}
.mount__summary::-webkit-details-marker { display: none; }
.mount__summary::after { content: "+"; color: var(--copper); font-size: 1.1rem; }
.mount__inspect[open] .mount__summary::after { content: "–"; }
.mount__spec {
  margin: 0 0 var(--s2);
  display: grid;
  gap: 2px;
  font-size: 0.8125rem;
  color: var(--fg-soft);
}
.mount__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
}
.mount__row dt {
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--copper-deep);
  font-weight: 700;
}
.mount__row dd { margin: 0; }

/* A card cover slot is a quiet frame, not a feature. */
.mount--card .mount__plate,
.mount--gallery .mount__plate { padding: var(--s3) var(--s4) var(--s4); }
.mount--card .mount__title,
.mount--gallery .mount__title { font-size: 1rem; }

/* --------------------------- Route selector ------------------------------- */

.routes { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-strong); }
.routes__item { border-bottom: 1px solid var(--line); }
.routes__link {
  display: grid;
  grid-template-columns: 2.5rem 1fr 1.5rem;
  align-items: center;
  gap: var(--s4);
  min-height: 72px;
  padding: var(--s4) 0;
  text-decoration: none;
  color: inherit;
}
.routes__index {
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--copper);
  transition: transform var(--standard) var(--ease-in-out);
}
.routes__body { display: grid; gap: 2px; }
.routes__label { font-weight: 700; font-size: 1.0625rem; }
.routes__outcome { font-size: var(--t-small); color: var(--fg-soft); }
.routes__cue {
  justify-self: end;
  width: 1.25rem;
  height: 1px;
  background: var(--rule-strong);
  transition: width var(--standard) var(--ease-in-out), background-color var(--standard) var(--ease-in-out);
}
.routes__link:hover .routes__index,
.routes__link:focus-visible .routes__index { transform: translateX(4px); }
.routes__link:hover .routes__cue,
.routes__link:focus-visible .routes__cue { width: 2rem; background: var(--copper); }
.routes__note {
  margin: 0 0 var(--s3);
  padding-left: 3.4rem;
  font-size: var(--t-small);
  color: var(--fg-soft);
}

/* ------------------------------- Hero stage ------------------------------- *
   One uninterrupted film across the full width. No side photographs, no seams,
   no coloured glow anywhere. The only things over the film are a localised
   readability veil and two painted shutters that open once and then belong to
   the scroll position.                                                        */

.hero--stage {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  max-width: none;
  padding: 0;
  gap: 0;
  min-height: clamp(540px, calc(74svh - 40px), 760px);
  overflow: hidden;
  background: #0c0f0d;
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.45);
}

.stage { position: absolute; inset: 0; display: block; background: #0b0e0c; }
.stage__film {
  max-width: 2304px;
  margin-inline: auto;
  inset: 0;
}
.stage__film { position: absolute; inset: 0; overflow: hidden; }
.stage__poster,
.stage__film img,
.stage__video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}
.stage__video { opacity: 0; transition: opacity var(--slow) var(--ease-in-out); }
.stage[data-film-state="playing"] .stage__video { opacity: 1; }

/* Readability where the copy sits, not a filter over the whole picture. */
.stage__veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(38% 52% at 50% 46%, rgba(8, 11, 9, 0.82) 0%, rgba(8, 11, 9, 0.62) 46%, rgba(8, 11, 9, 0.18) 78%, transparent 100%),
    linear-gradient(180deg, rgba(8, 11, 9, 0.42) 0%, transparent 26%, transparent 62%, rgba(8, 11, 9, 0.5) 100%);
}

/* Painted shutters. Cream board, a fine paper tooth, one brass keyline on the
   inner edge. No photograph, no glow, nothing left visible when open. */
.shutter {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50.5%;
  z-index: 3;
  pointer-events: none;
  background-color: #efe7d8;
  background-image:
    linear-gradient(180deg, rgba(255, 253, 247, 0.9) 0%, rgba(226, 214, 195, 0.9) 100%),
    repeating-linear-gradient(92deg, rgba(143, 80, 36, 0.035) 0 2px, transparent 2px 5px);
  transform: translate3d(-101%, 0, 0);
}
.shutter--left { left: 0; border-right: 1px solid rgba(168, 124, 62, 0.55); }
.shutter--right { right: 0; border-left: 1px solid rgba(168, 124, 62, 0.55); transform: translate3d(101%, 0, 0); }
/* A neutral contact shadow, only while they are actually moving. */
[data-curtains="opening"] .shutter,
[data-curtains="scroll"] .shutter { box-shadow: 0 0 40px -12px rgba(18, 16, 13, 0.55); }

@media (min-width: 48em) {
  .page--home .shutter--left { animation: shutter-open-left 940ms cubic-bezier(0.4, 0, 0.2, 1) 120ms both; }
  .page--home .shutter--right { animation: shutter-open-right 940ms cubic-bezier(0.4, 0, 0.2, 1) 120ms both; }
}
@keyframes shutter-open-left {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-101%, 0, 0); }
}
@keyframes shutter-open-right {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(101%, 0, 0); }
}
/* Once the scroll controller owns them, the entry animation must not fight it. */
[data-curtains="scroll"] .shutter { animation: none !important; }
/* No shutters on a phone or under reduced motion: just the film. */
@media (max-width: 47.99em) {
  .shutter { display: none; }
}
[data-motion="static"] .shutter { display: none !important; }

/* ----------------------------- Scroll stage ------------------------------- *
   The section below the hero tilts up into place as it is scrolled to. One
   progress value, one transform, no layout properties.                       */
.stagewrap {
  perspective: 1400px;
  perspective-origin: 50% 0%;
  /* clip, not hidden: hidden would create a scroll container and break the
     sticky header above it. */
  overflow-x: clip;
}
[data-enhanced][data-motion="full"] .stagewrap__inner {
  transform-origin: 50% 0%;
  transform:
    rotateX(calc((1 - var(--stage-progress, 1)) * 14deg))
    scale(calc(0.94 + var(--stage-progress, 1) * 0.06))
    translateY(calc((1 - var(--stage-progress, 1)) * 48px));
  opacity: calc(0.45 + var(--stage-progress, 1) * 0.55);
  will-change: transform;
}
[data-motion="static"] .stagewrap__inner {
  transform: none !important;
  opacity: 1 !important;
}

/* ---------------------------- Journey gallery ----------------------------- *
   A service gateway, not a mood board: four landscape routes visible together,
   each one card, one link, one decision. The photograph carries the
   recognition; a localised scrim at the foot carries the words.             */

.band--journeys .band__head,
.gallery,
.gallery__aside,
.gallery__note {
  width: min(1480px, calc(100vw - var(--inset) * 2 - 1rem));
  margin-inline: auto;
}
.band--journeys .h-section { font-size: clamp(2.75rem, 4vw, 4.75rem); line-height: 1.02; }
.band--journeys .chapter__index { font-size: 1.35rem; }
.band--journeys .chapter__label { font-size: 0.875rem; letter-spacing: 0.2em; }
.band--journeys .lede { font-size: clamp(1.125rem, 0.95rem + 0.5vw, 1.4rem); max-width: 46ch; }

.gallery {
  list-style: none;
  margin: var(--s7) auto 0;
  padding: 0;
  display: grid;
  gap: 22px;
}
.gcard { min-width: 0; }

.gcard__link {
  position: relative;
  display: block;
  height: clamp(9.5rem, 42vw, 11.25rem);
  overflow: hidden;
  border: 1px solid rgba(143, 80, 36, 0.34);
  border-radius: var(--radius-mount);
  background: var(--bottle-deep);
  text-decoration: none;
  color: var(--on-deep);
  transition:
    transform var(--standard) var(--ease-in-out),
    border-color var(--standard) var(--ease-in-out);
}

.gcard__media {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
}
.gcard__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* One slow editorial move toward the focal point, nothing more. */
  transition: transform 560ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Only the text zone is protected; the photograph itself is never washed. */
.gcard__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Localised to the text zone only: the top half of every photograph is left
     completely alone, but the copy holds against a bright interior. */
  background: linear-gradient(
    180deg,
    transparent 0%,
    transparent 26%,
    rgba(11, 35, 28, 0.44) 50%,
    rgba(11, 35, 28, 0.84) 76%,
    rgba(11, 35, 28, 0.94) 100%
  );
  transition: opacity var(--standard) var(--ease-in-out);
}
.gcard__link:hover .gcard__scrim,
.gcard__link:focus-visible .gcard__scrim { opacity: 1; }

.gcard__body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  gap: 2px;
  padding: var(--s4) var(--s5) var(--s4);
}
.gcard__audience {
  font-size: 0.8125rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.gcard__title {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 3.25rem);
  line-height: 1.1;
  color: var(--on-deep);
}
.gcard__line {
  font-size: clamp(1rem, 0.94rem + 0.2vw, 1.125rem);
  line-height: 1.5;
  color: rgba(246, 244, 239, 0.86);
  max-width: 40ch;
}
/* Composed, not a warning chip. */
.gcard__status {
  justify-self: start;
  margin-top: var(--s2);
  padding-left: var(--s3);
  border-left: 2px solid var(--sand);
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  color: var(--sand);
}
.gcard__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s4);
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--on-deep);
}
.gcard__cta-label { border-bottom: 1px solid rgba(239, 194, 154, 0.6); padding-bottom: 2px; }
.gcard__arrow { color: var(--sand); font-size: 1.2em; transition: transform 210ms var(--ease-in-out); }

.gcard__link:hover,
.gcard__link:focus-visible {
  transform: translateY(-2px);
  border-color: var(--sand);
  box-shadow: 0 12px 30px -24px rgba(6, 18, 14, 0.9);
  cursor: pointer;
}
/* The action underline resolves from a hairline into a copper rule, so the
   card visibly answers the pointer rather than only moving. */
.gcard__cta-label {
  background-image: linear-gradient(var(--sand), var(--sand));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size 260ms var(--ease-in-out);
}
.gcard__link:hover .gcard__cta-label,
.gcard__link:focus-visible .gcard__cta-label { background-size: 100% 2px; }
.gcard__link:hover .gcard__media img,
.gcard__link:focus-visible .gcard__media img { transform: scale(1.035) translate3d(-6px, -4px, 0); }
.gcard__link:hover .gcard__arrow,
.gcard__link:focus-visible .gcard__arrow { transform: translateX(6px); }

/* A planned route keeps the same quality; only its language differs. */
.gcard--planned .gcard__link { border-style: dashed; }

.gallery__aside {
  list-style: none;
  margin: var(--s4) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s3);
}
.gaside {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 72px;
  padding: var(--s4) var(--s6);
  font-size: 1.125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-mount);
  background: var(--bone-raised);
  text-decoration: none;
  color: inherit;
  font-weight: 600;
  transition: border-color var(--standard) var(--ease-in-out);
}
.gaside:hover,
.gaside:focus-visible {
  border-color: var(--copper);
  background: var(--bone-sunk);
  box-shadow: inset 3px 0 0 var(--copper);
  cursor: pointer;
}
.gaside__arrow { color: var(--copper); transition: transform 210ms var(--ease-in-out); }
.gaside:hover .gaside__arrow,
.gaside:focus-visible .gaside__arrow { transform: translateX(6px); }

.gallery__note {
  margin: var(--s5) auto 0;
  font-size: 1rem;
  color: var(--fg-soft);
  max-width: 68ch;
}


/* The gateway: all four routes visible together from tablet upward, so the
   choice is a comparison rather than a scroll. */
@media (min-width: 48em) {
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
  .gcard__link { height: clamp(16.25rem, 30vw, 20rem); }
  .gcard__body { padding: var(--s6) var(--s6) var(--s5); }
  .gallery__aside { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 64em) {
  .gcard__link { height: clamp(24rem, 29vw, 26.875rem); }
  .gcard__body { padding: 32px; }
}
@media (max-width: 47.99em) {
  .gcard__link { height: clamp(9.375rem, 44vw, 11.25rem); }
  .gcard__body { padding: var(--s4); }
  .gcard__line { display: none; }
}

/* ------------------------------ Welcome ----------------------------------- */

.welcome__photo,
.welcome__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 52% 60%;
}
.welcome__photo { aspect-ratio: 4 / 5; border-radius: var(--radius-mount); overflow: hidden; }
.welcome__principles {
  list-style: none;
  margin: var(--s5) 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
  border-top: 1px solid var(--rule);
}
.welcome__principles li {
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--rule);
  font-weight: 600;
}
.welcome__record { margin: var(--s5) 0 0; font-size: var(--t-small); }

.welcome__grid { display: grid; gap: var(--s6); align-items: center; }
.welcome__media { min-width: 0; }
.welcome__media .mount { border-radius: var(--radius-mount); }
.welcome__copy { min-width: 0; }
.welcome__copy .h-section { font-size: clamp(2rem, 1.4rem + 2vw, 3.25rem); }
.welcome__copy p { font-size: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem); line-height: 1.65; }
.welcome__facts {
  margin: var(--s5) 0;
  padding: var(--s4) var(--s5);
  border-left: 3px solid var(--copper);
  background: var(--bone-raised);
  display: grid;
  gap: var(--s2);
  font-size: var(--t-small);
}
.welcome__facts dt { font-weight: 700; }
.welcome__facts dd { margin: 0; color: var(--fg-soft); }
.welcome__facts > div { display: grid; grid-template-columns: 12rem 1fr; gap: var(--s3); }
.welcome__actions { display: flex; flex-wrap: wrap; gap: var(--s4); margin-top: var(--s5); }

@media (min-width: 64em) {
  .welcome__grid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: var(--s8); }
}
@media (max-width: 47.99em) {
  .welcome__facts > div { grid-template-columns: 1fr; gap: 2px; }
}

/* ---------------------------- Service spectrum ---------------------------- */

.spectrum { position: relative; margin: var(--s6) 0 0; }
.spectrum__scale { position: relative; height: 1px; margin-bottom: var(--s3); }
.spectrum__line {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--rule) 0%, var(--copper) 100%);
  transform-origin: left center;
}
.spectrum__ends {
  display: flex;
  justify-content: space-between;
  gap: var(--s4);
  margin: 0 0 var(--s5);
  max-width: none;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-soft);
}
.spectrum__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
.spectrum__step {
  position: relative;
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
}
.spectrum__dot {
  position: absolute;
  top: -5px;
  left: 0;
  width: 9px;
  height: 9px;
  border: 1px solid var(--copper);
  background: var(--bone);
  border-radius: 50%;
}
.spectrum__index {
  display: block;
  font-family: var(--font-display);
  font-size: 0.9rem;
  color: var(--copper);
  margin-bottom: 2px;
}
.spectrum__name { margin: 0 0 var(--s1); font-size: 1.0625rem; font-weight: 700; }
.spectrum__state { margin: 0; font-size: var(--t-small); color: var(--copper-deep); }
.spectrum__aside {
  margin-top: var(--s7);
  padding: var(--s5);
  border-left: 3px solid var(--copper);
  background: var(--bone-raised);
}
.spectrum__aside p { font-size: var(--t-small); color: var(--fg-soft); }

/* --------------------------- Editorial panels ----------------------------- */

.editorials { display: grid; gap: var(--s6); }
.editorial {
  display: grid;
  gap: 0;
  overflow: hidden;
  border: 1px solid var(--line);
}
.editorial__media { min-width: 0; background: var(--bottle-deep); }
.editorial__media .mount { border: 0; border-radius: 0; height: 100%; }
.editorial__body {
  min-width: 0;
  display: grid;
  align-content: center;
  gap: var(--s3);
  padding: var(--s6) var(--s5);
}
.editorial--light { background: var(--bone-raised); }
.editorial--deep {
  background: linear-gradient(160deg, #12362b 0%, #0b231c 100%);
  border-color: var(--rule-on-deep);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --line: var(--rule-on-deep);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
}
.editorial--deep .editorial__eyebrow { color: var(--sand); }
.editorial--deep .link { color: var(--sand); }
.editorial--deep .plate { background: rgba(246, 244, 239, 0.07); border-left-color: var(--sand); }
.editorial--deep .plate__tag { color: var(--sand); }
.editorial--deep .plate__detail { color: var(--on-deep-soft); }
.editorial__eyebrow {
  margin: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--copper-deep);
}
.editorial__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2.1rem);
  line-height: 1.12;
}
.editorial__lede { margin: 0; color: var(--fg-soft); }

/* ------------------------------ Credentials ------------------------------- */

.creds { position: relative; display: grid; gap: var(--s7); padding-top: var(--s5); }
/* Drawn once, and only to connect the groups: it carries no meaning on its own. */
.creds__line {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--sand) 18%, var(--sand) 82%, transparent 100%);
  opacity: 0.5;
  transform-origin: left center;
}
.creds__group { min-width: 0; }
.creds__title {
  margin: 0 0 var(--s2);
  font-family: var(--font-text);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.creds__meaning { font-size: var(--t-small); color: var(--fg-soft); max-width: 52ch; }
.creds__list { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s4); }
.creds__record {
  padding: var(--s4);
  border: 1px solid var(--rule-on-deep);
  background: rgba(246, 244, 239, 0.05);
}
.creds__record--pending { border-style: dashed; background: transparent; }
.creds__org { margin: 0 0 var(--s1); font-size: 1rem; font-weight: 700; }
.creds__what { margin: 0 0 var(--s3); font-size: var(--t-small); color: var(--fg-soft); }
.creds__pending { margin: 0; font-size: var(--t-small); color: var(--sand); }

/* ---------------------------- Action panels ------------------------------- */

.actions-pair { display: grid; gap: var(--s5); }
.action-panel {
  position: relative;
  padding: var(--s6) var(--s5) var(--s5);
  background: var(--bone-raised);
  border-top: 3px solid var(--rule-strong);
  transition: border-color var(--standard) var(--ease-in-out);
}
.action-panel--lead { border-top-color: var(--bottle); }
.action-panel:hover { border-top-color: var(--copper); }
/* .btn--outline is authored for dark surfaces: cream label, cream hairline. This
   panel is a light bone surface, so without this reset the button renders cream
   on cream — measured at 1.06:1, which is invisible rather than merely low. It
   takes the ink treatment here, the same way .rcard resets its own foregrounds. */
.action-panel .btn--outline {
  --btn-fg: var(--ink);
  border-color: rgba(17, 26, 22, 0.32);
}
.action-panel .btn--outline:hover {
  border-color: var(--copper-deep);
  color: var(--copper-deep);
}
.action-panel__index {
  position: absolute;
  top: var(--s3);
  right: var(--s4);
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--copper);
}
.action-panel__title { margin: 0 0 var(--s3); font-family: var(--font-display); font-size: 1.5rem; }
.action-panel__body { color: var(--fg-soft); }
.action-panel__cta { margin: var(--s5) 0 0; max-width: none; }

/* ------------------------------- Ledger ----------------------------------- */

.ledger { list-style: none; margin: var(--s5) 0; padding: 0; border-top: 1px solid var(--rule-strong); }
.ledger__row { padding: var(--s4) 0; border-bottom: 1px solid var(--line); }
.ledger__name { margin: 0 0 var(--s1); font-size: 1.0625rem; font-weight: 700; }
.ledger__for { margin: 0 0 var(--s2); color: var(--fg-soft); }
.ledger__state {
  margin: 0;
  font-size: var(--t-small);
  color: var(--copper-deep);
}
.ledger__row--withheld .ledger__name { color: var(--fg-soft); text-decoration: line-through; }
.ledger__tag {
  margin: var(--s2) 0 0;
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--copper-deep);
}
.ledger--services .ledger__row {
  display: grid;
  gap: var(--s1);
  padding: var(--s4) 0;
  transition: padding-left var(--standard) var(--ease-in-out);
}
.ledger--services .ledger__row:hover { padding-left: var(--s3); }

/* Numbered tiles: a distinct silhouette from cards and panels. */
.tile {
  position: relative;
  padding: var(--s6) var(--s5) var(--s5);
  background: var(--bone-raised);
  border-top: 3px solid var(--bottle);
}
.tile__index {
  position: absolute;
  top: var(--s3); right: var(--s4);
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  /* Decorative, but it still has to pass contrast rather than lean on opacity. */
  color: var(--copper);
}

.facts { margin: var(--s5) 0; display: grid; gap: 0; border-top: 1px solid var(--rule-strong); }
.facts__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.facts__row dt { font-size: var(--t-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-soft); font-weight: 700; }
.facts__row dd { margin: 0; }
.facts__pending { color: var(--copper-deep); font-weight: 600; }

.themes { margin: var(--s5) 0; padding-left: 1.1em; color: var(--fg-soft); max-width: 56ch; }
.themes li { margin-bottom: var(--s2); }

.linklist { margin: var(--s4) 0; padding-left: 1.1em; max-width: var(--measure); }
.linklist li { margin-bottom: var(--s2); }

.prose { max-width: 72ch; }

/* ------------------------------ Status plate ------------------------------ */

.plate {
  display: grid;
  gap: var(--s1);
  margin: var(--s4) 0;
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--copper);
  background: var(--bone-raised);
  max-width: 62ch;
}
.plate__tag {
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--copper-deep);
}
.plate__detail { font-size: var(--t-small); color: var(--fg-soft); }
.plate--public { border-left-color: var(--bottle); }
.plate--public .plate__tag { color: var(--bottle); }
.plate--demo { border-left-color: var(--ink); }

/* --------------------------------- Cards ---------------------------------- */

.card {
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--radius-structural);
  background: var(--bone-raised);
}
.card--action {
  transition: border-color var(--standard) var(--ease-in-out);
}
.card--action:hover { border-color: var(--rule-strong); }

.panel {
  padding: var(--s5);
  border-top: 3px solid var(--bottle);
  background: var(--bone-raised);
}
.panel--check { border-top-color: var(--copper); }
.panel__list { margin: 0; padding-left: 1.1em; }
.panel__list li { margin-bottom: var(--s3); }

.pending {
  margin: var(--s6) 0;
  padding: var(--s5);
  border: 1px dashed var(--copper);
  background: var(--bone-raised);
}
.pending__list { margin: var(--s4) 0 0; padding-left: 1.1em; }
.pending__list li { margin-bottom: var(--s2); }

/* Sales: a restrained curtain. Deliberately quiet, deliberately not a service. */
.curtain {
  max-width: none;
  margin: 0;
  padding: clamp(3.5rem, 8vw, 7rem) var(--inset);
  background:
    radial-gradient(80% 70% at 12% 0%, rgba(143, 80, 36, 0.24), transparent 60%),
    linear-gradient(180deg, #0b231c 0%, #12362b 100%);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
}
.curtain__inner { max-width: var(--max); margin: 0 auto; }
.curtain__tag {
  margin: 0 0 var(--s5);
  padding-bottom: var(--s3);
  border-bottom: 1px solid rgba(239, 194, 154, 0.35);
  display: inline-block;
  font-size: var(--t-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.curtain__title { color: var(--on-deep); max-width: 18ch; }
.curtain__body { color: var(--on-deep-soft); max-width: 54ch; font-size: 1.15rem; }
.curtain__foot {
  margin-top: var(--s7);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule-on-deep);
  font-size: var(--t-small);
  color: rgba(246, 244, 239, 0.55);
  max-width: 58ch;
}

/* About: portrait-led composition. */
.hero--person { display: block; max-width: none; padding: 0; background: var(--bone); }
.hero__inner--person { padding-bottom: var(--s7); align-items: center; }
.hero__portrait { min-width: 0; }
.hero__story { min-width: 0; }
/* Labelled synthesis, deliberately not styled as a quotation. */
.hero__pull {
  margin: var(--s5) 0;
  padding-left: var(--s5);
  border-left: 3px solid var(--copper);
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 42ch;
}
.hero__pull-label {
  display: block;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--copper-deep);
  margin-bottom: var(--s1);
}

/* -------------------------------- Matrix ---------------------------------- */

.groups { display: grid; gap: var(--s7); }
.group { min-width: 0; }
.group__intro { color: var(--fg-soft); font-size: var(--t-small); }
.group__pending { font-size: var(--t-small); color: var(--fg-soft); max-width: 62ch; margin-top: var(--s3); }
.group[hidden] { display: none; }
.group--dim { opacity: 0.55; transition: opacity var(--standard) var(--ease-in-out); }

.matrix {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
  margin: var(--s4) 0;
}
.matrix th,
.matrix td {
  text-align: left;
  padding: var(--s3);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.matrix thead th {
  border-bottom: 1px solid var(--rule-strong);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.matrix tbody th { font-weight: 600; }
.matrix td { color: var(--copper-deep); }
.matrix--fees td { color: var(--fg-soft); }
.matrix--fees tbody th { color: var(--ink); }

.package-grid { display: grid; gap: var(--s5); }
.package {
  padding: var(--s5);
  border-top: 3px solid var(--bottle);
  background: var(--bone-raised);
}
.package__name { margin: 0 0 var(--s2); font-family: var(--font-display); font-size: 1.4rem; }
.package__for { color: var(--fg-soft); font-size: var(--t-small); }
.package__fields { margin: var(--s4) 0; display: grid; gap: 0; }
.package__fields > div {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-small);
}
.package__fields dt { font-weight: 700; }
.package__fields dd { margin: 0; color: var(--copper-deep); text-align: right; }

.scope { margin: var(--s5) 0; border-top: 1px solid var(--rule-strong); }
.scope__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s4);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.scope__topic { font-weight: 600; }
.scope__state { margin: 0; color: var(--copper-deep); font-size: var(--t-small); text-align: right; }

/* -------------------------------- Process --------------------------------- */

.process { position: relative; margin: var(--s6) 0; }
.process__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
.process__step { padding-left: var(--s6); position: relative; }
.process__step::before {
  content: "";
  position: absolute;
  left: 7px; top: 12px;
  width: 9px; height: 9px;
  border: 1px solid var(--copper);
  background: var(--bone);
  border-radius: 50%;
}
.process__index {
  display: block;
  font-family: var(--font-display);
  font-size: 0.9rem;
  color: var(--copper);
  margin-bottom: 2px;
}
.process__title { margin: 0 0 var(--s1); font-size: 1.0625rem; font-weight: 700; }
.process__detail { margin: 0; color: var(--fg-soft); font-size: var(--t-small); }
.process__line {
  position: absolute;
  left: 11px; top: 12px; bottom: 12px;
  width: 1px;
  background: var(--rule-strong);
  transform: scaleY(1);
  transform-origin: top center;
}

/* --------------------------------- Reviews -------------------------------- */

.review { max-width: var(--max); }
.review__head { margin-bottom: var(--s5); }
.review__count { font-size: var(--t-small); color: var(--fg-soft); }
.review__stage { position: relative; }
.review__list { list-style: none; margin: 0; padding: 0; }
.review__slide[hidden] { display: none; }
.review__card {
  margin: 0;
  padding: var(--s6) var(--s5);
  border-top: 3px solid var(--bottle);
  background: var(--bone-raised);
  display: grid;
  gap: var(--s4);
}
.review__initials {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--copper);
  letter-spacing: 0.06em;
}
.review__quote { margin: 0; }
.review__quote p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.05rem + 1vw, 1.8rem);
  line-height: 1.3;
  max-width: 40ch;
}
.review__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s4);
  font-size: var(--t-small);
  color: var(--fg-soft);
}
.review__name { font-style: normal; font-weight: 700; color: var(--ink); }
.review__controls {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-top: var(--s4);
  flex-wrap: wrap;
}
.review__position { margin: 0; font-size: var(--t-small); color: var(--fg-soft); }
.review__hint { margin: var(--s3) 0 0; font-size: var(--t-small); color: var(--fg-soft); }

/* Scrubber: a fine rule with a small handle, not a media-player control. */
.review__scrub { flex: 1 1 12rem; display: flex; align-items: center; min-height: 44px; }
.review__range {
  width: 100%;
  height: 44px;
  margin: 0;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.review__range::-webkit-slider-runnable-track { height: 1px; background: var(--rule-strong); }
.review__range::-moz-range-track { height: 1px; background: var(--rule-strong); }
.review__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px; height: 14px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--copper);
  border: 0;
}
.review__range::-moz-range-thumb {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--copper);
  border: 0;
}
.review__range:focus-visible { outline-offset: -4px; }

/* Partial sight of the next card. Decorative and aria-hidden. */
.review__peek { display: none; }
.review__peek-initials { font-family: var(--font-display); color: var(--copper); font-size: 1.15rem; }
.review__peek-quote {
  margin: var(--s3) 0 0;
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.3;
  color: var(--fg-soft);
}
.review__aggregate,
.review__more { font-size: var(--t-small); color: var(--fg-soft); margin-top: var(--s4); }

.ctrl {
  min-width: 44px;
  min-height: 44px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--t-small);
  font-weight: 700;
  cursor: pointer;
  transition: border-color var(--quick) var(--ease-in-out);
}
.ctrl:hover { border-color: var(--copper); }
.ctrl--wide { padding-inline: var(--s5); }

.reviewlist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
.reviewlist__card {
  margin: 0;
  padding: var(--s5);
  border-left: 3px solid var(--copper);
  background: var(--bone-raised);
  display: grid;
  gap: var(--s3);
}
.reviewlist__initials { font-family: var(--font-display); color: var(--copper); font-size: 1.15rem; }
.reviewlist__quote { margin: 0; }
.reviewlist__quote p { margin: 0; }
.reviewlist__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  font-size: var(--t-small);
  color: var(--fg-soft);
}
.reviewlist__meta cite { font-style: normal; font-weight: 700; color: var(--ink); }

/* ------------------------------ Review wall ------------------------------- *
   A full-bleed deep bottle-green chapter: a calm rating anchor beside a slowly
   moving wall of the reviewers' own words. The boldness of this chapter is the
   wall; everything around it stays quiet.

   The layout is the same whether the wall moves or not. Only the window height,
   the mask and the animation are added on top, so no JavaScript, reduced motion
   and Save-Data all resolve to the same complete, readable collection.        */

.band--reviews {
  max-width: none;
  background:
    radial-gradient(80% 70% at 88% 4%, rgba(143, 80, 36, 0.2), transparent 62%),
    linear-gradient(180deg, #0b231c 0%, #12362b 58%, #0b231c 100%);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
  --line: var(--rule-on-deep);
  --rule: var(--rule-on-deep);
  --rule-strong: rgba(246, 244, 239, 0.4);
}
.band--reviews > * { max-width: var(--max); margin-inline: auto; }
.band--reviews .chapter__index { color: var(--sand); }
.band--reviews .chapter__label { color: var(--on-deep-soft); }

.rwall__inner { display: grid; gap: var(--s7); align-items: start; }

.rwall__eyebrow {
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.rwall__title {
  margin: 0 0 var(--s3);
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.2vw, 3.25rem);
  line-height: 1.05;
  color: var(--on-deep);
}
.rwall__lede { margin: 0; color: var(--on-deep-soft); max-width: 34ch; font-size: 1.125rem; }
.rwall__provenance {
  margin: var(--s4) 0 0;
  padding-left: var(--s4);
  border-left: 2px solid var(--sand);
  font-size: var(--t-small);
  color: rgba(246, 244, 239, 0.9);
  max-width: 40ch;
}

/* The card foot carries the destination host itself: the proof that these are
   Google entries is that you can see, and check, where each one goes. */
.rcard__link {
  display: grid;
  gap: 2px;
  align-content: center;
}
.rcard__go { display: block; }
.rcard__host {
  font-family: var(--font-text);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  border-bottom: 0;
}

/* The aggregate anchor. Large, calm, and clearly a profile total rather than a
   count of the excerpts beside it. */
.score {
  margin-top: var(--s6);
  padding: var(--s5);
  border: 1px solid var(--rule-on-deep);
  border-left: 3px solid var(--sand);
  background: rgba(246, 244, 239, 0.05);
}
.score__source {
  display: grid;
  gap: 1px;
  margin: 0 0 var(--s4);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule-on-deep);
}
.score__source-label {
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--on-deep-soft);
}
.score__source-name {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--on-deep);
}
.score__value {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(3rem, 2rem + 3vw, 4.5rem);
  line-height: 0.95;
  color: var(--on-deep);
}
.score__stars { margin: var(--s2) 0 0; font-size: 1.05rem; letter-spacing: 0.22em; color: var(--sand); }
/* The aggregate reads as a citation rather than a badge: label on the left,
   value on the right, hairline between each fact. Two columns collapse to one
   only when the label and value can no longer share a line. */
.score__ledger {
  margin: var(--s4) 0 0;
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-on-deep);
  display: grid;
  gap: 0;
}
.score__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--rule-on-deep);
}
.score__row:last-child { border-bottom: 0; }
.score__row dt {
  font-size: var(--t-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-deep-soft);
}
.score__row dd {
  margin: 0;
  text-align: right;
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--on-deep);
}
.score__row dd strong { color: var(--sand); }
.score__count,
.score__captured { margin: 0; }
.score__open { margin: var(--s4) 0 0; }
.score .link { color: var(--sand); }
.score__note {
  margin: var(--s4) 0 0;
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-on-deep);
  font-size: var(--t-small);
  color: var(--on-deep-soft);
}
.score__note strong { color: var(--on-deep); }

/* ---- The wall ---- */
.rwall__window {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s5);
  align-items: start;
}
.rwall__col { min-width: 0; }
.rwall__col--2,
.rwall__col--3 { display: none; }

.rwall__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s5);
}

/* ---- A card ---- */
.rcard {
  position: relative;
  display: grid;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid rgba(17, 26, 22, 0.14);
  border-radius: 12px;
  background: var(--bone-raised);
  color: var(--ink);
  /* The card is a warm bone surface inside a dark chapter, so it resets the
     surface tokens rather than inheriting the field's foregrounds. */
  --fg: var(--ink);
  --fg-soft: var(--ink-soft);
  --focus-ring: var(--ink);
  --focus-halo: rgba(143, 80, 36, 0.28);
  transition:
    transform var(--standard) var(--ease-in-out),
    border-color var(--standard) var(--ease-in-out),
    box-shadow var(--standard) var(--ease-in-out);
}
.rcard__head { display: flex; align-items: center; gap: var(--s3); }
.rcard__initials {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--copper);
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  color: var(--copper-deep);
}
.rcard__who { min-width: 0; }
/* Source stamped on every card, using the same flag idiom as the route dock so
   it reads as part of this system rather than a pasted-in third-party widget. */
.rcard__src {
  flex: 0 0 auto;
  align-self: flex-start;
  margin-left: auto;
  padding: 2px 7px;
  border: 1px solid rgba(17, 26, 22, 0.22);
  border-radius: var(--radius-control);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-soft);
  white-space: nowrap;
}
.rcard__name { margin: 0; font-size: 1rem; font-weight: 700; color: var(--ink); }
.rcard__meta { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); font-size: var(--t-small); }
.rcard__stars { color: var(--copper); letter-spacing: 0.14em; }
.rcard__when { color: var(--ink-soft); }
.rcard__quote { margin: 0; }
.rcard__quote p {
  margin: 0;
  /* Moving text has to stay comfortably readable. */
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink);
  max-width: none;
}
.rcard__link {
  justify-self: start;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--copper-deep);
  text-decoration: none;
  border-bottom: 1px solid rgba(111, 61, 27, 0.4);
}
/* One real anchor, and the whole card opens it. */
.rcard__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }

.rcard:hover,
.rcard:focus-within {
  transform: translateY(-3px);
  border-color: rgba(143, 80, 36, 0.55);
  box-shadow: 0 10px 26px -18px rgba(6, 18, 14, 0.75);
}
/* The crown red appears once, as a hairline endpoint on the active card. */
.rcard:hover::before,
.rcard:focus-within::before {
  content: "";
  position: absolute;
  left: var(--s5);
  right: var(--s5);
  bottom: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--copper) 0%, var(--crest) 100%);
  border-radius: 2px;
}

.rwall__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4) var(--s5);
  margin-top: var(--s5);
}
.rwall__toggle { min-height: 44px; border-color: var(--rule-on-deep); color: var(--on-deep); }
.rwall__toggle:hover { border-color: var(--sand); color: var(--sand); }
.rwall__controls .link { color: var(--sand); }
/* The verification claim closes the chapter, set quietly under a hairline so it
   reads as a footnote to the wall rather than another piece of marketing. */
/* Nothing to pause when nothing moves. */
[data-wall-state="static"] .rwall__toggle { display: none; }

/* ---- The moving state ---- *
   Added only when the enhancement layer is present and motion is wanted, so the
   static composition above is what everyone else keeps. */
[data-enhanced][data-motion="full"] .rwall__window {
  height: clamp(34rem, 60vw, 44rem);
  overflow: hidden;
  /* Cards appear to continue beyond the window rather than being cut off. */
  mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
}
[data-enhanced][data-motion="full"] .rwall__col { height: 100%; overflow: hidden; }
[data-enhanced][data-motion="full"] .rwall__track {
  padding-bottom: var(--s5);
  will-change: transform;
  animation: wall-travel var(--wall-duration, 36s) linear infinite;
  animation-play-state: paused;
}
/* The middle column travels the other way. */
[data-enhanced][data-motion="full"] .rwall__col--2 .rwall__track { animation-direction: reverse; }
/* Column two starts part-way down so the rows never line up into a grid. */
[data-enhanced][data-motion="full"] .rwall__col--2 { padding-top: var(--s7); }
[data-enhanced][data-motion="full"] .rwall__col--3 { padding-top: var(--s5); }

[data-wall-running="true"] .rwall__track { animation-play-state: running !important; }

@keyframes wall-travel {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(0, -50%, 0); }
}

/* -------------------------------- Evidence -------------------------------- */

.evidence { display: grid; gap: var(--s7); }
.evidence__meaning { color: var(--fg-soft); font-size: var(--t-small); }
.evidence__list { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s5); }
.evidence__record {
  padding: var(--s5);
  border: 1px solid var(--line);
  background: var(--bone-raised);
}
.evidence__org { margin: 0 0 var(--s2); font-size: 1.0625rem; font-weight: 700; }
.evidence__what { color: var(--fg-soft); font-size: var(--t-small); }
.evidence__fields { margin: var(--s4) 0; display: grid; gap: 0; }
.evidence__fields > div {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  font-size: var(--t-small);
}
.evidence__fields dt { font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-soft); font-weight: 700; }
.evidence__fields dd { margin: 0; overflow-wrap: anywhere; }
.evidence__caution,
.evidence__noaction { font-size: var(--t-small); color: var(--fg-soft); }

/* ------------------------------- Trust rail ------------------------------- */

.rail {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bone-sunk);
  padding: var(--s6) var(--inset);
}
.rail__title {
  max-width: var(--max);
  margin: 0 auto var(--s2);
  font-family: var(--font-text);
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--fg-soft);
}
.rail__intro {
  max-width: var(--max);
  margin: 0 auto var(--s4);
  font-size: var(--t-small);
  color: var(--fg-soft);
}
.rail__viewport { max-width: var(--max); margin: 0 auto; overflow: hidden; }
.rail__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}
.rail__link {
  display: grid;
  gap: 2px;
  min-height: 44px;
  padding: var(--s2) var(--s4);
  border: 1px solid var(--rule);
  background: var(--bone-raised);
  text-decoration: none;
  transition: border-color var(--standard) var(--ease-in-out);
}
.rail__link:hover { border-color: var(--copper); }
.rail__category { font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-soft); }
.rail__org { font-weight: 700; font-size: var(--t-small); }
.rail__toggle { max-width: var(--max); margin: var(--s4) auto 0; display: block; }

/* -------------------------------- Next steps ------------------------------ */

.steps { padding-top: var(--s7); padding-bottom: var(--s7); border-top: 1px solid var(--line); }
.steps__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.steps__link {
  display: grid;
  gap: var(--s2);
  padding: var(--s5);
  border: 1px solid var(--line);
  background: var(--bone-raised);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--standard) var(--ease-in-out), transform var(--standard) var(--ease-in-out);
}
.steps__link:hover { border-color: var(--rule-strong); transform: translateY(-2px); }
.steps__label { font-weight: 700; font-size: 1.0625rem; }
.steps__blurb { color: var(--fg-soft); font-size: var(--t-small); }
.steps__action { color: var(--copper-deep); font-weight: 700; font-size: var(--t-small); }
.steps__arrow { display: inline-block; margin-left: 0.4em; transition: transform var(--standard) var(--ease-in-out); }
.steps__link:hover .steps__arrow { transform: translateX(3px); }
.steps__item--lead .steps__link { border-top: 3px solid var(--bottle); }

/* ---------------------------------- Forms --------------------------------- */

.closing { border-top: 1px solid var(--line); }
.closing__grid { display: grid; gap: var(--s7); }
.closing__alt { font-size: var(--t-small); color: var(--fg-soft); margin-top: var(--s4); }

.contact__intro { font-size: var(--t-small); color: var(--fg-soft); }
.contact__list { margin: var(--s4) 0 0; border-top: 1px solid var(--rule-strong); }
.contact__row { padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.contact__row dt { font-size: var(--t-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-soft); font-weight: 700; margin-bottom: 2px; }
.contact__row dd { margin: 0; display: grid; gap: 2px; }
.contact__pending { color: var(--copper-deep); font-weight: 600; }
.contact__value { font-weight: 600; }
.contact__note { font-size: var(--t-small); color: var(--fg-soft); }

.form {
  padding: var(--s5);
  border-top: 3px solid var(--bottle);
  background: var(--bone-raised);
}
.form__intro { font-size: var(--t-small); color: var(--fg-soft); }
.form__preset {
  display: grid;
  gap: 2px;
  margin: var(--s4) 0;
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--copper);
  background: var(--bone-sunk);
  max-width: none;
}
.form__preset-label { font-size: var(--t-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-soft); font-weight: 700; }
.form__preset-value { font-weight: 700; }
.form__preset-note { font-size: var(--t-small); color: var(--fg-soft); }

.form__grid { display: grid; gap: var(--s4); }
.form__field { margin: 0; display: grid; gap: var(--s2); max-width: none; }
.form__label { font-weight: 700; font-size: var(--t-small); }
.form__opt { font-weight: 400; color: var(--fg-soft); }
.form__control {
  width: 100%;
  min-height: 48px;
  padding: var(--s3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: var(--bone-raised);
  color: var(--ink);
  font: inherit;
  transition: border-color var(--quick) var(--ease-in-out);
}
textarea.form__control { min-height: 7rem; resize: vertical; }
.form__control:hover { border-color: var(--copper); }
.form__hint { font-size: var(--t-small); color: var(--fg-soft); }

.form__consent { margin: var(--s5) 0; display: grid; gap: var(--s4); }
.form__privacy { font-size: var(--t-small); color: var(--fg-soft); margin: 0; }

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s3);
  align-items: start;
  min-height: 44px;
  padding: var(--s2) 0;
  cursor: pointer;
}
.check__input { position: absolute; opacity: 0; width: 24px; height: 24px; }
.check__box {
  width: 24px; height: 24px;
  border: 2px solid var(--ink);
  border-radius: var(--radius-control);
  background: var(--bone-raised);
  display: grid;
  place-items: center;
  margin-top: 2px;
}
.check__input:checked + .check__box::after {
  content: "";
  width: 12px; height: 7px;
  border-left: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: rotate(-45deg) translate(1px, -2px);
}
.check__input:focus-visible + .check__box {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}
.check__label { font-size: var(--t-small); color: var(--fg-soft); }

.form__notconnected {
  margin: var(--s5) 0 var(--s4);
  padding: var(--s3) var(--s4);
  border: 1px dashed var(--copper);
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--copper-deep);
  max-width: none;
}
.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4); }
.form__status { margin: 0; font-size: var(--t-small); color: var(--copper-deep); font-weight: 600; }

/* -------------------------------- Needs / stages -------------------------- */

.needs { margin: var(--s5) 0 var(--s6); }
.needs__set { border: 0; margin: 0; padding: 0; }
.needs__legend { font-weight: 700; font-size: var(--t-small); padding: 0; margin-bottom: var(--s3); }
.needs__options { display: grid; gap: var(--s2); }
.needs__option {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--s3);
  min-height: 44px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--line);
  background: var(--bone-raised);
  cursor: pointer;
}
.needs__input { position: absolute; opacity: 0; width: 22px; height: 22px; }
.needs__box {
  width: 22px; height: 22px;
  border: 2px solid var(--ink);
  border-radius: var(--radius-control);
  display: grid; place-items: center;
}
.needs__input:checked + .needs__box::after {
  content: "";
  width: 11px; height: 6px;
  border-left: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: rotate(-45deg) translate(1px, -2px);
}
.needs__input:focus-visible + .needs__box {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}
.needs__text { font-size: var(--t-small); font-weight: 600; }
.needs__status { margin: var(--s3) 0 0; font-size: var(--t-small); color: var(--fg-soft); }

.stages { display: grid; gap: var(--s6); }
.stages__progress { margin: 0; font-size: var(--t-small); font-weight: 700; color: var(--copper-deep); }
.stage {
  border: 0;
  border-top: 1px solid var(--rule-strong);
  margin: 0;
  padding: var(--s5) 0 0;
}
.stage[hidden] { display: none; }
.stage__legend { padding: 0; display: grid; gap: 2px; margin-bottom: var(--s4); }
.stage__step { font-size: var(--t-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-soft); font-weight: 700; }
.stage__title { font-family: var(--font-display); font-size: 1.35rem; }
.stages__nav { display: flex; gap: var(--s4); flex-wrap: wrap; }

.summary {
  margin: var(--s5) 0;
  padding: var(--s5);
  border-left: 3px solid var(--copper);
  background: var(--bone-sunk);
}
.summary__note { font-size: var(--t-small); color: var(--fg-soft); }
.summary__list { margin: var(--s4) 0 0; border-top: 1px solid var(--rule); }
.summary__row {
  display: grid;
  gap: 2px;
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--rule);
}
.summary__row dt {
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-soft);
  font-weight: 700;
}
.summary__row dd { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4); }
.summary__edit {
  min-height: 44px;
  padding: var(--s1) var(--s3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--copper-deep);
  font: inherit;
  font-size: var(--t-small);
  font-weight: 700;
  cursor: pointer;
}
.summary__edit:hover { border-color: var(--copper); }

.cards { border: 0; margin: 0 0 var(--s4); padding: 0; display: grid; gap: var(--s3); }
.cards__legend { font-weight: 700; font-size: var(--t-small); padding: 0; margin-bottom: var(--s3); }
.cards__card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s2);
  padding: var(--s5);
  border: 1px solid var(--rule-strong);
  background: var(--bone-raised);
  cursor: pointer;
  transition: border-color var(--standard) var(--ease-in-out), background-color var(--standard) var(--ease-in-out);
}
.cards__input { position: absolute; opacity: 0; }
.cards__name { font-weight: 700; display: block; }
.cards__name::before {
  content: "";
  display: inline-block;
  width: 14px; height: 14px;
  margin-right: var(--s3);
  border: 2px solid var(--ink);
  border-radius: 50%;
  vertical-align: baseline;
}
.cards__detail { display: block; font-size: var(--t-small); color: var(--fg-soft); }
.cards__card:has(.cards__input:checked) { border-color: var(--bottle); background: var(--bone-sunk); }
.cards__card:has(.cards__input:checked) .cards__name::before { background: var(--bottle); box-shadow: inset 0 0 0 2px var(--bone-raised); }
.cards__card:has(.cards__input:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}
.cards__card--conditional { border-style: dashed; }

/* --------------------------------- Search --------------------------------- */

.search {
  padding: var(--s5);
  border-top: 3px solid var(--bottle);
  background: var(--bone-raised);
  display: grid;
  gap: var(--s5);
}
.search__mode { border: 0; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s4); align-items: center; }
.search__legend { font-weight: 700; font-size: var(--t-small); padding: 0; width: 100%; margin-bottom: var(--s3); }
.search__radio { display: inline-flex; align-items: center; gap: var(--s2); min-height: 44px; font-size: var(--t-small); }
.search__flag { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--copper); }
.search__grid { display: grid; gap: var(--s4); }
.search__field { margin: 0; display: grid; gap: var(--s2); max-width: none; }
.search__actions { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: start; }
.search__toggle { display: inline-flex; align-items: center; gap: var(--s3); min-height: 44px; font-size: var(--t-small); }
.search__maplink { margin: 0; display: grid; justify-items: start; gap: var(--s2); flex: 0 1 22rem; }
.search__note { font-size: var(--t-small); color: var(--fg-soft); }

/* Native controls, sized so the box itself is reachable rather than relying on
   the label row alone. */
.search__toggle input[type="checkbox"],
.search__radio input[type="radio"] {
  width: 22px;
  height: 22px;
  margin: 0;
  accent-color: var(--copper);
  flex: 0 0 auto;
}

.results { margin-top: var(--s6); }
.results__summary { font-weight: 700; }
.results__nojs { font-size: var(--t-small); color: var(--fg-soft); }
.results__grid { display: grid; gap: var(--s5); margin-top: var(--s5); }
.results__empty { padding: var(--s5); border: 1px dashed var(--copper); }
.results__empty .btn { margin-right: var(--s4); }

.chips { margin: var(--s4) 0; }
.chips__title {
  margin: 0 0 var(--s2);
  font-family: var(--font-text);
  font-size: var(--t-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--fg-soft);
}
.chips__list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  padding: var(--s2) var(--s4);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: var(--bone-raised);
  color: inherit;
  font: inherit;
  font-size: var(--t-small);
  cursor: pointer;
  transition: border-color var(--quick) var(--ease-in-out);
}
.chip:hover { border-color: var(--copper); }
.chip__x { color: var(--copper); font-size: 1.1rem; line-height: 1; }
.results__map { margin-top: var(--s5); padding: var(--s5); border: 1px dashed var(--rule-strong); }
.results__mapnote { margin: 0; font-size: var(--t-small); color: var(--fg-soft); }

.prop {
  border: 1px solid var(--line);
  background: var(--bone-raised);
  display: grid;
}
.prop[hidden] { display: none; }
.prop__media { padding: var(--s3) var(--s3) 0; }
.prop__body { padding: var(--s4); display: grid; gap: var(--s2); }
.prop__flag {
  margin: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--copper-deep);
}
.prop__title { margin: 0; font-size: 1.0625rem; font-weight: 700; }
.prop__link { text-decoration: none; border-bottom: 1px solid var(--copper); }
.prop__area { margin: 0; font-size: var(--t-small); color: var(--fg-soft); }
.prop__facts { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s4); font-size: var(--t-small); }
.prop__rent { margin: 0; font-weight: 700; color: var(--copper-deep); }
.prop__rent--lead { font-size: 1.15rem; }
.prop__status { margin: 0; font-size: var(--t-small); color: var(--fg-soft); }

.demo-banner {
  background: var(--bottle-deep);
  color: var(--on-deep);
  padding: var(--s4) var(--inset);
}
.demo-banner p { margin: 0 auto; max-width: var(--max); font-size: var(--t-small); }

/* ---------------------------------- EPC ----------------------------------- */

.epc { list-style: none; margin: var(--s5) 0; padding: 0; display: grid; gap: 4px; max-width: 44rem; }
.epc__band {
  display: grid;
  grid-template-columns: 3rem 5rem 1fr;
  align-items: center;
  gap: var(--s3);
  min-height: 48px;
  padding: var(--s2) var(--s4);
  color: var(--ink);
  border: 1px solid var(--rule-strong);
}
.epc__letter { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; }
.epc__range { font-size: var(--t-small); font-weight: 700; }
.epc__meaning { font-size: var(--t-small); }
.epc__band--a { background: #cfe4d2; }
.epc__band--b { background: #d9e7cd; }
.epc__band--c { background: #e6ecc8; }
.epc__band--d { background: #f2eec6; }
.epc__band--e { background: #f4e3c4; }
.epc__band--f { background: #f2d6c2; }
.epc__band--g { background: #eec8c2; }

/* ------------------------------ Breadcrumbs ------------------------------- */

.crumbs {
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--s4) var(--inset) 0;
}
.crumbs__list {
  list-style: none;
  margin: 0; padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  font-size: var(--t-small);
}
.crumbs__item + .crumbs__item::before { content: "/"; margin-right: var(--s3); color: var(--fg-soft); }
.crumbs__link { text-decoration: none; border-bottom: 1px solid var(--rule); }
.crumbs__current { color: var(--fg-soft); }

/* --------------------------------- FAQs ----------------------------------- */

.faq { display: grid; border-top: 1px solid var(--rule-strong); max-width: 72ch; }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 56px;
  padding: var(--s3) 0;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after { content: "+"; font-size: 1.3rem; color: var(--copper); }
.faq__item[open] .faq__q::after { content: "–"; }
.faq__a { padding-bottom: var(--s4); color: var(--fg-soft); }
.faq__a p { margin: 0; }

/* ------------------------------ Receptionist ------------------------------ */

.reception {
  background: var(--bottle);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.35);
  --line: var(--rule-on-deep);
}
.reception__eyebrow {
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.reception .h-section { color: var(--on-deep); }
.reception__notice { color: var(--on-deep-soft); max-width: 62ch; }
.reception__demo {
  border: 1px dashed var(--sand);
  padding: var(--s3) var(--s4);
  color: var(--sand);
  font-size: var(--t-small);
  font-weight: 700;
  max-width: 62ch;
}
.reception__inner { display: grid; gap: var(--s6); align-items: start; }
.reception__intro { min-width: 0; }
.reception__routes { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-on-deep); min-width: 0; }
.reception__route { border-bottom: 1px solid var(--rule-on-deep); }
.reception__summary {
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  align-items: center;
  gap: var(--s4);
  min-height: 60px;
  padding: var(--s3) 0;
  cursor: pointer;
  list-style: none;
  font-weight: 700;
}
.reception__summary::-webkit-details-marker { display: none; }
.reception__index { font-family: var(--font-display); color: var(--sand); }
.reception__body { padding: 0 0 var(--s5) 3.4rem; display: grid; gap: var(--s3); }
.reception__outcome { margin: 0; color: var(--on-deep-soft); }
.reception__safety {
  margin: 0;
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--sand);
  color: var(--sand);
  font-size: var(--t-small);
}
.reception__flag { margin: 0; font-size: var(--t-small); color: var(--sand); }
.reception__asks { margin: 0; font-size: var(--t-small); color: var(--on-deep-soft); }
.reception__questions { margin: 0; padding-left: 1.1em; color: var(--on-deep); font-size: var(--t-small); }
.reception__questions li { margin-bottom: var(--s1); }
.reception__end { margin: var(--s2) 0 0; font-size: var(--t-small); color: var(--on-deep-soft); }

/* --------------------------------- Launcher ------------------------------- */

/* Without the enhancement layer the launcher is an ordinary link at the end of
   the document, so it can never sit on top of anything. */
.launcher {
  position: relative;
  display: grid;
  gap: 2px;
  min-height: 56px;
  padding: var(--s3) var(--s5);
  margin: 0;
  background: var(--bottle-deep);
  color: var(--on-deep);
  text-decoration: none;
  border: 1px solid var(--bottle-deep);
  border-radius: var(--radius-control);
  overflow: hidden;
}
[data-enhanced] .launcher {
  position: fixed;
  right: max(var(--s4), env(safe-area-inset-right));
  bottom: max(var(--s4), env(safe-area-inset-bottom));
  z-index: 40;
  max-width: calc(100vw - 2 * var(--s4));
  transition: opacity var(--standard) var(--ease-in-out), transform var(--standard) var(--ease-in-out);
}
/* Stowed whenever it would otherwise cover an action, a control or a consent row. */
[data-enhanced] .launcher.is-stowed {
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
}
.launcher__glint {
  position: absolute;
  inset: 0 auto 0 -40%;
  width: 30%;
  background: linear-gradient(90deg, transparent, rgba(239, 194, 154, 0.28), transparent);
  transform: translateX(-100%);
}
.launcher[data-glint="on"] .launcher__glint { animation: glint 450ms var(--ease-in-out) 1; }
@keyframes glint {
  from { transform: translateX(-100%); }
  to { transform: translateX(520%); }
}
.launcher__glyph { display: none; }
.launcher__glyph svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
.launcher__label { display: grid; gap: 2px; }
.launcher__text { font-weight: 700; font-size: var(--t-small); }
.launcher__sub { font-size: 0.6875rem; color: var(--on-deep-soft); letter-spacing: 0.06em; }
.launcher:focus-visible { outline-color: var(--on-deep); }

/* ------------------------- Receptionist sheet ----------------------------- */

.sheet {
  width: min(34rem, calc(100vw - 2rem));
  max-height: min(80vh, 40rem);
  margin: auto auto 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-mount) var(--radius-mount) 0 0;
  background: var(--bottle);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.4);
  overflow: auto;
  overscroll-behavior: contain;
}
.sheet::backdrop { background: rgba(11, 35, 28, 0.62); }
.sheet__head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding: var(--s5) var(--s5) var(--s3);
  background: var(--bottle);
  border-bottom: 1px solid var(--rule-on-deep);
}
.sheet__title { margin: 0; font-family: var(--font-display); font-size: 1.5rem; color: var(--on-deep); }
.sheet__close {
  min-width: 44px; min-height: 44px;
  border: 1px solid var(--rule-on-deep);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--on-deep);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}
.sheet__close:hover { border-color: var(--sand); color: var(--sand); }
.sheet__notice { margin: var(--s4) var(--s5) 0; font-size: var(--t-small); color: var(--on-deep-soft); }
.sheet__routes { list-style: none; margin: var(--s4) 0 0; padding: 0 var(--s5); display: grid; gap: var(--s2); }
.sheet__route {
  width: 100%;
  min-height: 60px;
  padding: var(--s3) var(--s4);
  display: grid;
  gap: 2px;
  text-align: left;
  border: 1px solid var(--rule-on-deep);
  border-radius: var(--radius-control);
  background: rgba(246, 244, 239, 0.05);
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: border-color var(--quick) var(--ease-in-out), background-color var(--quick) var(--ease-in-out);
}
.sheet__route:hover { border-color: var(--sand); background: rgba(246, 244, 239, 0.1); }
.sheet__route-name { font-weight: 700; }
.sheet__route-detail { font-size: var(--t-small); color: var(--on-deep-soft); }
.sheet__demo {
  margin: var(--s5);
  padding: var(--s3) var(--s4);
  border: 1px dashed var(--sand);
  color: var(--sand);
  font-size: var(--t-small);
}

/* ---------------------------------- Footer -------------------------------- */

.site-foot {
  background: var(--bottle-deep);
  color: var(--on-deep);
  --fg: var(--on-deep);
  --fg-soft: var(--on-deep-soft);
  --focus-ring: var(--on-deep);
  --focus-halo: rgba(239, 194, 154, 0.35);
  /* Extra room at the foot so the fixed launcher never sits over the last links. */
  padding: var(--s8) var(--inset) calc(var(--s6) + 5rem);
  margin-top: var(--s8);
}
@media (min-width: 64em) {
  .site-foot { padding-bottom: var(--s6); }
}
.site-foot__inner {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  gap: var(--s7);
}
.site-foot__mark { height: 62px; width: auto; display: block; }
.site-foot__position { margin-top: var(--s4); color: var(--on-deep-soft); font-size: var(--t-small); max-width: 34ch; }
.site-foot__nav { display: grid; gap: var(--s6); }
.site-foot__heading {
  margin: 0 0 var(--s3);
  font-family: var(--font-text);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--sand);
}
.site-foot__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.site-foot__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  font-size: var(--t-small);
  border-bottom: 1px solid transparent;
}
.site-foot__link:hover { border-color: var(--sand); }
.site-foot__legal p { font-size: var(--t-small); margin-bottom: var(--s2); max-width: 46ch; }
.site-foot__caution { color: var(--on-deep-soft); }
.site-foot__legal .link { color: var(--sand); }
.site-foot__stamp {
  max-width: var(--max);
  margin: var(--s7) auto 0;
  padding-top: var(--s4);
  border-top: 1px solid var(--rule-on-deep);
  font-size: var(--t-small);
  color: var(--on-deep-soft);
}

/* ================================ Responsive ============================== */

@container (min-width: 26rem) {
  .mount__row { grid-template-columns: 9rem 1fr; gap: var(--s3); }
  .mount__crop { display: block; }
  .mount__title { font-size: 1.3rem; }
}

/* From tablet upward the composition becomes three panels: warm image, film,
   warm image — with the copy centred inside the film. */
@media (min-width: 48em) {
  .hero--stage {
    grid-template-columns: 14% 72% 14%;
    grid-template-rows: 1fr auto;
    min-height: var(--stage-h);
  }
  .hero__panel { grid-column: 2; padding: var(--s7) var(--s5); }
  .dock { grid-column: 1 / -1; grid-row: 2; }

  .mount__scene { aspect-ratio: var(--mount-ar, 1.5); }
  .split-two { grid-template-columns: 1fr 1fr; gap: var(--s6); }
  .results__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .package-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .needs__options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form__field--wide { grid-column: 1 / -1; }
  .search__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .facts__row { grid-template-columns: 14rem 1fr; gap: var(--s4); }
  .site-foot__nav { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .evidence__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .steps__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .process__list { gap: var(--s6); }
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 64em) {
  .nav--wide { display: block; }
  .menu { display: none; }
  .site-head__cta { display: inline-flex; margin-left: auto; }
  .site-head__inner { padding-block: var(--s2); min-height: 76px; }
  .brand__mark { height: 52px; }

  .hero { grid-template-columns: 1.05fr 1fr; align-items: center; gap: var(--s8); }

  /* Film hero: the copy holds the dark left, the status plate moves out of the
     reading path, and the dock becomes four equal ruled zones. */
  /* `.hero` turns into a two-column grid with a gap at this width for the other
     heroes. The stage is a single column that owns its own spacing, so it has
     to say so after that rule rather than before it. */
  .hero--stage {
    grid-template-columns: 19% 62% 19%;
    grid-template-rows: 1fr auto;
    align-items: stretch;
    gap: 0;
  }
  .hero__panel { padding: var(--s7) var(--s6); }

  .dock__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .dock__item { border-top: 0; border-left: 1px solid rgba(246, 244, 239, 0.14); }
  .dock__item:first-child { border-left: 0; }
  .dock__link { min-height: 104px; padding: var(--s4) var(--s5); }

  .hero--service .hero__inner { grid-template-columns: 1.15fr 0.85fr; align-items: start; gap: clamp(2.5rem, 4vw, 4.5rem); }
  .chooser { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s6); }
  .hero__inner--search { max-width: var(--max); }
  .hero__inner--person { grid-template-columns: 0.8fr 1.2fr; gap: clamp(2.5rem, 4vw, 4.5rem); }
  .search--hero .search__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .page-open { grid-template-columns: 1.1fr 0.9fr; align-items: start; gap: var(--s8); }
  .page-open--search { grid-template-columns: 1fr 1.2fr; }
  .band__split { grid-template-columns: 1.25fr 0.75fr; gap: var(--s8); }
  .band__split--reverse .band__minor { order: -1; }
  .band__split--reverse { grid-template-columns: 0.75fr 1.25fr; }
  .closing__grid { grid-template-columns: 0.85fr 1.15fr; }
  .results__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .search__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .package-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .evidence__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .steps__item--lead { grid-row: span 1; }
  .reception__inner { grid-template-columns: 0.85fr 1.15fr; gap: var(--s8); }
  .site-foot__inner { grid-template-columns: 0.8fr 1.6fr 1fr; }
  .site-foot__nav { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .process__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .process__line { left: 11px; right: 11px; top: 12px; bottom: auto; height: 1px; width: auto; transform-origin: left center; }
  .process__step::before { top: 8px; }
  .process__step { padding-left: var(--s5); padding-top: var(--s5); }
  .process__step::before { top: 4px; left: 0; }
}

@media (min-width: 90em) {
  .review__quote p { max-width: 34ch; }
  /* AX-014: roughly 12–18% of the neighbouring card is visible so movement
     is legible before it happens. */
  .review__stage { display: grid; grid-template-columns: 1fr 0.18fr; gap: 0; align-items: stretch; }
  .review__peek {
    display: block;
    overflow: hidden;
    padding: var(--s6) var(--s4);
    border-top: 3px solid var(--rule);
    background: var(--bone-raised);
    opacity: 0.5;
    mask-image: linear-gradient(90deg, #000 0%, transparent 92%);
    -webkit-mask-image: linear-gradient(90deg, #000 0%, transparent 92%);
  }
}

/* Wider than 2:1 — ultra-wide desktops and short wide laptops. The frame stops
   growing with the viewport and contains the film at its own ratio; the space
   either side becomes the composed atmosphere rather than black bars. */
@media (min-aspect-ratio: 2/1) and (min-width: 48em) {
  .dock__list {
    max-width: none;
    padding-inline: clamp(2rem, 5vw, 7rem);
  }

  /* The copy sits over the atmosphere at these proportions, so the veil no
     longer needs to fight the film for the left third. */
  .stage__veil {
    background:
      linear-gradient(
        96deg,
        rgba(7, 26, 20, 0.9) 0%,
        rgba(11, 35, 28, 0.7) 22%,
        rgba(15, 44, 34, 0.36) 42%,
        rgba(11, 35, 28, 0.12) 62%,
        rgba(11, 35, 28, 0) 82%
      ),
      linear-gradient(180deg, rgba(6, 18, 14, 0.42) 0%, rgba(6, 18, 14, 0) 42%, rgba(6, 18, 14, 0.72) 100%);
  }
}

/* Very large displays: let the stage grow so the contained film keeps presence
   without ever being asked for more pixels than were encoded. */
@media (min-width: 120em) {
  .hero--stage { --stage-h: clamp(37rem, calc(72svh - 2.5rem), 51rem); }
}

/* Short laptop screens. The hero still opens the page, but it gives way rather
   than pushing its own route dock off the bottom of the viewport. */
@media (min-width: 48em) and (max-height: 50rem) {
  .hero--stage { --stage-h: auto; min-height: 0; }
  .hero--stage .h-hero { font-size: clamp(2.2rem, 1rem + 3.4vh, 3.4rem); }
  .hero__panel { padding-block: var(--s5); }
  .hero--stage .hero__actions { margin-top: var(--s4); }
  .hero__title { margin-bottom: var(--s4); }
  .hero__proof { margin-top: var(--s4); }
  .dock__link { min-height: 84px; padding-block: var(--s3); }
}

/* Below the desktop breakpoint the curtains come off entirely and the dedicated
   portrait crop carries the hero, with the copy centred beneath it. */
@media (max-width: 47.99em) {
  .hero--stage { --film-ar: 0.8; }
  /* The copy sits beneath the film here, so the film keeps its own light: only
     a soft foot to carry it into the panel below. */
  .hero__panel { grid-row: 2; padding: var(--s6) var(--inset) var(--s7); }
  .hero--stage .h-hero { font-size: clamp(2.1rem, 1.2rem + 3.6vw, 2.8rem); }
  .hero--stage .hero__lede { font-size: 1.0625rem; }
  .hero--stage .hero__actions { gap: var(--s3); }
  .hero--stage .hero__actions .btn { flex: 1 1 100%; }
  .hero__eyebrow { font-size: 0.8125rem; padding: 5px 10px; letter-spacing: 0.08em; }
  .dock { grid-row: 3; }
  .dock__action { font-size: 1.0625rem; }
  .dock__link { min-height: 72px; padding: var(--s3); }
}


/* Review wall responsive: three columns, two, then one. */
@media (min-width: 48em) {
  .rwall__window { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rwall__col--2 { display: block; }
}
@media (min-width: 64em) {
  .rwall__inner { grid-template-columns: minmax(0, 30fr) minmax(0, 66fr); gap: var(--s8); }
  /* Large screens only, and only within its own chapter. */
  .rwall__anchor { position: sticky; top: var(--s6); }
}
/* The third column waits until there is room for it to stay readable, so 1024
   keeps two generous columns rather than three cramped ones. */
@media (min-width: 75em) {
  .rwall__window { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .rwall__col--3 { display: block; }
}
@media (max-width: 47.99em) {
  [data-enhanced][data-motion="full"] .rwall__window { height: clamp(30rem, 84vw, 34rem); }
  .score { padding: var(--s4); }
  .score__source {
  display: grid;
  gap: 1px;
  margin: 0 0 var(--s4);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule-on-deep);
}
.score__source-label {
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--on-deep-soft);
}
.score__source-name {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--on-deep);
}
.score__value { font-size: 2.75rem; }
  /* A compact horizontal score panel above the wall. */
  .score__stars { display: inline-block; margin-left: var(--s3); }
  .rcard { padding: var(--s4); }
}

/* Narrow screens: tables stack into labelled records. */
@media (max-width: 47.99em) {
  .matrix,
  .matrix thead,
  .matrix tbody,
  .matrix tr,
  .matrix th,
  .matrix td { display: block; width: 100%; }
  .matrix thead { display: none; }
  .matrix tbody tr {
    border-top: 1px solid var(--rule-strong);
    padding: var(--s3) 0;
  }
  .matrix tbody th { padding: 0 0 var(--s2); }
  .matrix tbody td { padding: 2px 0; border: 0; }
  .matrix tbody td[data-label]::before {
    content: attr(data-label) ": ";
    font-weight: 700;
    color: var(--ink);
  }
  .scope__row,
  .package__fields > div { grid-template-columns: 1fr; }
  .scope__state,
  .package__fields dd { text-align: left; }
}

/* 200% zoom and very narrow viewports keep everything in one column. */
@media (max-width: 22.5em) {
  :root { --inset: 1rem; }
  .brand__mark { height: 38px; }
  .routes__link { grid-template-columns: 2rem 1fr; }
  .routes__cue { display: none; }
}

/* Below the desktop breakpoint the launcher becomes a 56px control so it takes
   as little of a small viewport as possible, and it stows over any text. */
@media (max-width: 63.99em) {
  [data-enhanced] .launcher {
    width: 56px;
    height: 56px;
    min-height: 56px;
    padding: 0;
    place-items: center;
    border-radius: 50%;
    border-color: var(--sand);
  }
  [data-enhanced] .launcher .launcher__glyph { display: grid; place-items: center; color: var(--sand); }
  [data-enhanced] .launcher .launcher__label {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* =============================== Motion modes ============================= */

/* One-time entrances only run once the enhancement layer marks the document. */
[data-enhanced] [data-reveal="headline"] span {
  display: block;
  opacity: 0;
  transform: translateY(0.4em);
}
[data-enhanced] [data-reveal="headline"].is-in span {
  opacity: 1;
  transform: none;
  transition: opacity var(--compose) var(--ease-arrive), transform var(--compose) var(--ease-arrive);
}
[data-enhanced] [data-reveal="headline"].is-in span:nth-child(2) { transition-delay: 60ms; }

/* The hero settles as one composed group — eyebrow, headline, lede, actions,
   proof link — and the dock follows it once. Everything resolves inside the
   first second, with no overshoot and nothing that replays. */
[data-enhanced] [data-reveal="hero"] > *,
[data-enhanced] [data-reveal="hero-copy"] > * {
  opacity: 0;
  transform: translateY(10px);
}
/* The stage hero opens with its own CSS sequence below, so the JavaScript
   reveal must not hold its contents hidden as well. */
[data-enhanced] .hero--stage [data-reveal="hero"] > *,
[data-enhanced] .hero--stage [data-reveal="hero-copy"] > *,
[data-enhanced] .hero--stage [data-reveal="headline"] span,
[data-enhanced] .hero--stage [data-reveal="dock"] {
  opacity: 1;
  transform: none;
}
[data-enhanced] [data-reveal="hero"].is-in > *,
[data-enhanced] [data-reveal="hero-copy"].is-in > * {
  opacity: 1;
  transform: none;
  transition: opacity 420ms var(--ease-arrive), transform 420ms var(--ease-arrive);
}
[data-enhanced] [data-reveal="hero"].is-in > *:nth-child(2) { transition-delay: 70ms; }
[data-enhanced] [data-reveal="hero-copy"].is-in > *:nth-child(1) { transition-delay: 140ms; }
[data-enhanced] [data-reveal="hero-copy"].is-in > *:nth-child(2) { transition-delay: 200ms; }
[data-enhanced] [data-reveal="hero-copy"].is-in > *:nth-child(3) { transition-delay: 250ms; }

/* Journey cards and editorial panels: one reveal each, never repeated. */
[data-enhanced] .gallery .gcard { opacity: 0; transform: translateY(14px); }
[data-enhanced] .gallery.is-in .gcard {
  opacity: 1;
  transform: none;
  transition: opacity 300ms var(--ease-arrive), transform 300ms var(--ease-arrive);
}
[data-enhanced] .gallery.is-in .gcard:nth-child(2) { transition-delay: 50ms; }
[data-enhanced] .gallery.is-in .gcard:nth-child(3) { transition-delay: 100ms; }
[data-enhanced] .gallery.is-in .gcard:nth-child(4) { transition-delay: 100ms; }

[data-enhanced] [data-reveal="card"] {
  opacity: 0;
  transform: translateY(12px);
}
[data-enhanced] [data-reveal="card"].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--compose) var(--ease-arrive), transform var(--compose) var(--ease-arrive);
}

/* A single connecting rule that draws itself once. */
[data-enhanced] [data-reveal="draw"] { transform: scaleX(0); }
[data-enhanced] [data-reveal="draw"].is-in {
  transform: scaleX(1);
  transition: transform var(--slow) var(--ease-arrive);
}

[data-enhanced] [data-reveal="dock"] {
  opacity: 0;
  transform: translateY(14px);
}
[data-enhanced] [data-reveal="dock"].is-in {
  opacity: 1;
  transform: none;
  transition: opacity 420ms var(--ease-arrive) 300ms, transform 420ms var(--ease-arrive) 300ms;
}

[data-enhanced] .chapter__rule { transform: scaleX(0); }
[data-enhanced] .chapter.is-in .chapter__rule {
  transform: scaleX(1);
  transition: transform var(--compose) var(--ease-arrive);
}

[data-enhanced] [data-reveal="mount"] { clip-path: inset(0 0 12% 0); opacity: 0.001; }
[data-enhanced] [data-reveal="mount"].is-in {
  clip-path: inset(0 0 0 0);
  opacity: 1;
  transition: clip-path var(--slow) var(--ease-arrive), opacity var(--compose) var(--ease-arrive);
}

[data-enhanced] .process__line { transform: scaleY(0); }
[data-enhanced] .process.is-in .process__line {
  transform: scaleY(1);
  transition: transform var(--compose) var(--ease-arrive);
}
@media (min-width: 64em) {
  [data-enhanced] .process__line { transform: scaleX(0); }
  [data-enhanced] .process.is-in .process__line { transform: scaleX(1); }
}

[data-enhanced] .epc__band { opacity: 0; transform: translateX(-6px); }
[data-enhanced] .epc.is-in .epc__band {
  opacity: 1;
  transform: none;
  transition: opacity var(--standard) var(--ease-arrive), transform var(--standard) var(--ease-arrive);
  transition-delay: calc(var(--epc-index) * 45ms);
}

/* Reduced motion and Save-Data: every final state renders immediately. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-enhanced] [data-reveal="headline"] span,
  [data-enhanced] [data-reveal="hero"] > *,
  [data-enhanced] [data-reveal="hero-copy"] > *,
  [data-enhanced] [data-reveal="card"],
  [data-enhanced] [data-reveal="dock"],
  [data-enhanced] .epc__band { opacity: 1; transform: none; }
  [data-enhanced] .chapter__rule,
  [data-enhanced] [data-reveal="draw"],
  [data-enhanced] .process__line { transform: none; }
  [data-enhanced] [data-reveal="mount"] { clip-path: none; opacity: 1; }
}

/* Save-Data parity. The JavaScript layer reads navigator.connection.saveData,
   which is not available in every engine, so the media query carries the same
   rule for engines that expose the preference instead. */
@media (prefers-reduced-data: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  [data-enhanced] [data-reveal="headline"] span,
  [data-enhanced] [data-reveal="hero"] > *,
  [data-enhanced] [data-reveal="hero-copy"] > *,
  [data-enhanced] [data-reveal="card"],
  [data-enhanced] [data-reveal="dock"],
  [data-enhanced] .epc__band { opacity: 1; transform: none; }
  [data-enhanced] .chapter__rule,
  [data-enhanced] [data-reveal="draw"],
  [data-enhanced] .process__line { transform: none; }
  [data-enhanced] [data-reveal="mount"] { clip-path: none; opacity: 1; }
  .review__peek { display: none !important; }
}

[data-motion="static"] .gallery .gcard { opacity: 1 !important; transform: none !important; }
[data-motion="static"] .gcard__link:hover,
[data-motion="static"] .gcard__link:focus-visible { transform: none !important; }
[data-motion="static"] .gcard__link:hover .gcard__cta-label,
[data-motion="static"] .gcard__link:focus-visible .gcard__cta-label { background-size: 100% 2px; }
[data-motion="static"] .gcard__link:hover .gcard__media img,
[data-motion="static"] .gcard__link:focus-visible .gcard__media img { transform: none !important; }
[data-motion="static"] .gcard__link:hover .gcard__arrow,
[data-motion="static"] .gcard__link:focus-visible .gcard__arrow { transform: none !important; }

[data-motion="static"] [data-reveal="headline"] span,
[data-motion="static"] [data-reveal="hero"] > *,
[data-motion="static"] [data-reveal="hero-copy"] > *,
[data-motion="static"] [data-reveal="card"],
[data-motion="static"] [data-reveal="dock"],
[data-motion="static"] .epc__band { opacity: 1 !important; transform: none !important; }
[data-motion="static"] .chapter__rule,
[data-motion="static"] [data-reveal="draw"],
[data-motion="static"] .process__line { transform: none !important; }
[data-motion="static"] [data-reveal="mount"] { clip-path: none !important; opacity: 1 !important; }


/* ======================= The homepage opening ============================= *
   One sequence, once, entirely in CSS — so a visitor who prefers reduced
   motion, or whose JavaScript never runs, is handed the finished composition
   instead of a hidden one. Transforms, clipping and opacity only; no width
   animation, no blur animation, no overshoot, and nothing repeats.

   Header 0–420ms · curtains 180–880ms · film 520–1020ms · headline 760–1280ms
   · copy 980–1400ms · dock 1120–1540ms.                                     */

@media (prefers-reduced-motion: no-preference) {
  .page--home .hero__title {
    animation: mask-up 520ms var(--ease-arrive) 760ms both;
  }
  .page--home .hero__copy {
    animation: settle 420ms var(--ease-arrive) 980ms both;
  }
  .page--home .dock {
    animation: dock-rise 540ms var(--ease-arrive) 1180ms both;
  }
}

@keyframes __dead_curtain_left {
  from { transform: translate3d(var(--curtain-travel), -10px, 0); }
  to { transform: translate3d(0, 0, 0); }
}
@keyframes __dead_curtain_right {
  from { transform: translate3d(calc(var(--curtain-travel) * -1), -10px, 0); }
  to { transform: translate3d(0, 0, 0); }
}
@keyframes stage-open {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes mask-up {
  from { clip-path: inset(0 0 100% 0); opacity: 0; }
  to { clip-path: inset(0 0 0 0); opacity: 1; }
}
@keyframes settle {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@keyframes dock-rise {
  from { opacity: 0; transform: translateY(100%); }
  to { opacity: 1; transform: none; }
}

/* Save-Data gets the finished composition too. */
@media (prefers-reduced-data: reduce) {
  .page--home .stage__curtain--left,
  .page--home .stage__curtain--right,
  .page--home .stage__centre,
  .page--home .hero__title,
  .page--home .hero__copy,
  .page--home .dock { animation: none !important; }
}
/* And so does anyone the enhancement layer has put into static mode. */
[data-curtains="scroll"] .stage__curtain--left,

/* Velocity-linked edge softness, driven by a single custom property that the
   controller sets. Zero at rest, and never applied to anything but the
   photographs themselves. */
@media (hover: none), (prefers-reduced-motion: reduce) {
}

[data-motion="static"] .stage__curtain--left,
[data-motion="static"] .stage__curtain--right,
[data-motion="static"] .stage__centre,
[data-motion="static"] .hero__title,
[data-motion="static"] .hero__copy,
[data-motion="static"] .dock { animation: none !important; }

/* ================================== Print ================================= */

.printmark { display: none; }

@media print {
  .site-head__band,
  .launcher,
  .rail,
  .reception,
  .steps,
  .closing,
  .form__actions,
  .needs,
  .chips,
  .mount,
  .stage__atmos,
  .stage__veil,
  .stage__grade,
  .menu { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }

  /* On paper the hero is its words and its four routes, not a film. */
  .hero--stage {
    min-height: 0 !important;
    background: #fff !important;
    color: #000 !important;
  }
  .__unused,
  .hero--stage .hero__lede,
  .dock__action { color: #000 !important; text-shadow: none !important; }
  .hero__eyebrow {
    background: #fff !important;
    color: #000 !important;
    border-color: #000 !important;
  }
  .dock__audience,
  .dock__cue { color: #000 !important; }
  .dock { background: #fff !important; border-top: 1px solid #000; }
  .dock__link { color: #000 !important; min-height: 0 !important; }
  .dock__flag { color: #000 !important; border-color: #000 !important; }
  .site-foot { background: #fff; color: #000; }
  .faq__item > .faq__a { display: block !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }

  /* The schedule keeps its table shape on paper and repeats its headers, whatever
     the paper width would do to the screen breakpoints. */
  .matrix,
  .matrix thead,
  .matrix tbody,
  .matrix tr,
  .matrix th,
  .matrix td { display: revert !important; width: auto !important; }
  .matrix { width: 100% !important; border-collapse: collapse; }
  .matrix thead { display: table-header-group !important; }
  .matrix tr { page-break-inside: avoid; }
  .matrix tbody td[data-label]::before { content: none !important; }

  .group--dim { opacity: 1 !important; }
  .package, .panel, .pending, .plate { break-inside: avoid; }

  /* Identity, version and review date travel with any printed page. */
  .printmark {
    display: block !important;
    margin-top: 1.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid #000;
    font-size: 9pt;
  }
  .printmark p { margin: 0 0 2px; max-width: none; }
}

/* ============================ Forced colours ============================== */

@media (forced-colors: active) {
  .btn,
  .ctrl,
  .form__control,
  .check__box,
  .needs__box { border: 1px solid ButtonText; }
  .chapter__rule,
  .process__line { background: CanvasText; }
  .launcher__glint { display: none; }
  /* The film cannot be relied on for contrast in a forced palette, so the dock
     states its own boundaries instead. */
  .dock__item { border-color: CanvasText; }
  .dock__link:hover,
  .dock__link:focus-visible { outline: 2px solid Highlight; }
  .stage__veil,
}


/* Hero typography at the corrected, more cinematic scale. */
.hero--stage .h-hero {
  font-size: clamp(2.6rem, 4.6vw, 5.25rem);
  line-height: 1.0;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.hero--stage .hero__lede {
  font-size: clamp(1.05rem, 0.98rem + 0.35vw, 1.2rem);
  line-height: 1.55;
  color: rgba(250, 248, 244, 0.96);
  max-width: 52ch;
  margin-inline: auto;
}
.hero--stage .hero__actions { justify-content: center; }
.hero--stage .link { color: var(--sand); }

/* The dock overlaps the film and is separated by a copper hairline, not a glow. */
.hero--stage .dock {
  position: relative;
  z-index: 4;
  margin-top: -36px;
  border-top: 1px solid rgba(168, 124, 62, 0.6);
  box-shadow: none;
}
.hero--stage .dock::before { display: none; }


/* Hero action group — one baseline, one weight, premium restraint. */
.hero--stage .hero__actions {
  gap: var(--s3);
  margin-top: var(--s5);
  align-items: stretch;
}
.hero--stage .hero__actions .btn {
  min-height: 54px;
  padding-inline: var(--s6);
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  border-radius: 2px;
}
.hero--stage .btn--gold {
  --btn-fill: var(--sand);
  --btn-fg: #14261d;
  border-color: var(--sand);
  font-weight: 700;
}
.hero--stage .btn--gold:hover::after { box-shadow: none; }
.hero--stage .btn--gold:hover::before { transform: none; }
.hero--stage .btn--gold:hover { background: rgba(244, 210, 178, 0.12); }
.hero--stage .btn--outline {
  --btn-fg: #fbf9f5;
  border-color: rgba(251, 249, 245, 0.62);
  background: rgba(10, 14, 11, 0.34);
  font-weight: 600;
}
.hero--stage .btn--outline:hover,
.hero--stage .btn--outline:focus-visible {
  border-color: var(--sand);
  background: rgba(10, 14, 11, 0.52);
  color: var(--sand);
}
.hero--stage .btn--outline:hover::after { box-shadow: none; }
.hero__proof { margin-top: var(--s4); font-size: 0.875rem; }
.hero--stage .hero__proof .link { color: rgba(246, 244, 239, 0.82); }
.hero--stage .hero__proof .link:hover { color: var(--sand); }

/* 6) The dock stops being a heavy green slab: a translucent deep panel that
   lets the film through, with one copper hairline and no glow. */
.hero--stage .dock {
  margin-top: -30px;
  background: linear-gradient(180deg, rgba(9, 24, 19, 0.62) 0%, rgba(7, 20, 16, 0.86) 100%);
  border-top: 1px solid rgba(196, 148, 88, 0.5);
  backdrop-filter: saturate(115%) blur(2px);
}
.hero--stage .dock__link { min-height: 88px; padding-block: var(--s3); }
.hero--stage .dock__action { font-size: clamp(1.05rem, 0.9rem + 0.4vw, 1.35rem); }
.hero--stage .dock__audience { font-size: 0.6875rem; letter-spacing: 0.18em; }
.hero--stage .dock__item { border-color: rgba(246, 244, 239, 0.1); }


/* --------------------- Hero side columns: real voices --------------------- *
   The space beside the film is filled with sourced customer language instead of
   black. Decorative duplicates only — the accessible records are in the review
   chapter, so nothing here is tabbable or announced twice.                    */
.heroaside { display: none; }

@media (min-width: 75em) {
  .heroaside {
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: 2;
    display: block;
    width: 18.5%;
    overflow: hidden;
    pointer-events: none;
    background: linear-gradient(180deg, #0e1a15 0%, #0a1511 100%);
    /* Fades at both ends so the column reads as continuous, not clipped. */
    mask-image: linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
  }
  .heroaside--left { left: 0; }
  .heroaside--right { right: 0; }

  .heroaside__track {
    display: grid;
    gap: var(--s4);
    padding: var(--s5) var(--s5) 0;
    animation: wall-travel 62s linear infinite;
  }
  .heroaside__track--reverse { animation-direction: reverse; }

  .heroaside__card {
    display: grid;
    gap: 6px;
    padding: var(--s4);
    border: 1px solid rgba(239, 194, 154, 0.16);
    border-left: 2px solid rgba(196, 148, 88, 0.6);
    background: rgba(246, 244, 239, 0.05);
  }
  .heroaside__stars { color: var(--sand); font-size: 0.75rem; letter-spacing: 0.18em; }
  .heroaside__quote {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: rgba(246, 244, 239, 0.86);
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .heroaside__name {
    font-size: 0.6875rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(239, 194, 154, 0.8);
  }
}
[data-motion="static"] .heroaside__track { animation: none !important; }

/* The descender on "clearly." was being clipped by a 1.0 line box. */
.hero--stage .h-hero {
  line-height: 1.08;
  padding-bottom: 0.12em;
}
.hero--stage .h-hero span { display: block; overflow: visible; }

/* Less black, less glow: the veil only does the work it has to. */
.stage__veil {
  background:
    radial-gradient(36% 44% at 50% 46%, rgba(8, 11, 9, 0.7) 0%, rgba(8, 11, 9, 0.44) 52%, transparent 100%),
    linear-gradient(180deg, rgba(8, 11, 9, 0.3) 0%, transparent 24%, transparent 66%, rgba(8, 11, 9, 0.42) 100%);
}


/* More air between the rule, the heading and the content it introduces. */
.chapter { margin-bottom: clamp(2rem, 3.4vw, 3.25rem); }
.band__head { margin-bottom: clamp(2.25rem, 3.6vw, 3.5rem); }
.band__head .lede { margin-top: var(--s4); }

.welcome__grid { gap: clamp(2.5rem, 5vw, 5.5rem); align-items: center; }
.welcome__copy .h-section { margin-bottom: var(--s5); }
.welcome__copy p { margin-bottom: var(--s5); }
.welcome__principles { margin-block: var(--s6); }
.welcome__principles li { padding: var(--s4) 0; }
.welcome__actions { margin-top: var(--s6); gap: var(--s4); }

.gallery { margin-top: clamp(2rem, 3vw, 3rem); }
.gallery__aside { margin-top: clamp(1.5rem, 2.4vw, 2.25rem); }

/* The hero copy stack breathes instead of stacking tight against the film. */
.hero--stage .hero__panel { gap: var(--s5); }
.hero--stage .hero__lede { margin-top: var(--s5); }
.hero--stage .hero__actions { margin-top: var(--s6); }
.hero--stage .hero__proof { margin-top: var(--s5); }


/* ---------------- Hero side columns meet the film cleanly ----------------- *
   No black void between the picture and the voices beside it: the film fills
   the space between the two panels exactly, and a single brass keyline does the
   separating — the same joinery detail used elsewhere in the system.         */
@media (min-width: 75em) {
  .stage__film {
    left: 18.5%;
    right: 18.5%;
    max-width: none;
    margin-inline: 0;
  }
  .heroaside--left { border-right: 1px solid rgba(196, 148, 88, 0.62); }
  .heroaside--right { border-left: 1px solid rgba(196, 148, 88, 0.62); }
  /* A soft inner shadow so the panel reads as set back from the film rather
     than butted against it. */
  .heroaside--left::after,
  .heroaside--right::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 26px;
    pointer-events: none;
  }
  .heroaside--left::after { right: 0; background: linear-gradient(90deg, transparent, rgba(4, 8, 6, 0.55)); }
  .heroaside--right::after { left: 0; background: linear-gradient(270deg, transparent, rgba(4, 8, 6, 0.55)); }
}

/* -------------------------- Route dock, corrected ------------------------- *
   Centred on the same grid as the rest of the page, bigger, and unmistakably
   three separate choices rather than one continuous strip.                   */
.hero--stage .dock__list {
  max-width: var(--max);
  margin-inline: auto;
  gap: 1px;
  background: rgba(196, 148, 88, 0.22);
  padding: 0;
}
.hero--stage .dock__item {
  border: 0;
  background: linear-gradient(180deg, rgba(9, 24, 19, 0.82) 0%, rgba(7, 20, 16, 0.94) 100%);
}
.hero--stage .dock__link {
  min-height: 104px;
  padding: var(--s4) var(--s5);
  align-content: center;
  justify-items: start;
  text-align: left;
}
.hero--stage .dock__label { margin-bottom: var(--s2); }
.hero--stage .dock__audience { font-size: 0.75rem; letter-spacing: 0.2em; color: var(--sand); }
.hero--stage .dock__index { font-size: 0.9rem; }
.hero--stage .dock__action { font-size: clamp(1.2rem, 1rem + 0.5vw, 1.55rem); line-height: 1.15; }
.hero--stage .dock__cue { font-size: 1.3rem; }
/* Each choice answers on its own, so it is obvious which one is being chosen. */
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: rgba(246, 244, 239, 0.09); }
.hero--stage .dock__link::after { height: 2px; background: var(--sand); }

@media (min-width: 48em) {
  .hero--stage .dock__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}


/* --------------------- The dock joins the cream frame -------------------- *
   A deep-green slab under the film, immediately followed by a bright page, was
   the jarring part: two unrelated surfaces meeting at a hard edge. The dock is
   now the same warm parchment as the header, so the film sits inside one
   continuous cream frame — and dark ink on parchment is far easier to read than
   cream text on translucent green over moving video.                        */
.hero--stage .dock {
  margin-top: 0;
  background:
    radial-gradient(circle at 50% -120%, rgb(250 244 233 / 55%), transparent 46%),
    linear-gradient(180deg, #ece1cf 0%, #e2d5bd 100%);
  border-top: 1px solid rgb(143 80 36 / 34%);
  backdrop-filter: none;
  box-shadow: none;
}
.hero--stage .dock__list {
  background: rgb(143 80 36 / 22%);
}
.hero--stage .dock__item {
  background: linear-gradient(180deg, #ece1cf 0%, #e2d5bd 100%);
}
.hero--stage .dock__link { color: var(--ink); }
.hero--stage .dock__audience { color: var(--copper-deep); }
.hero--stage .dock__index { color: var(--copper); }
.hero--stage .dock__action { color: var(--bottle); }
.hero--stage .dock__cue { color: var(--copper); }
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: rgb(255 252 245 / 62%); }
.hero--stage .dock__link::after { background: var(--copper); }
.hero--stage .dock__link:focus-visible { outline-color: var(--ink); }

/* The film no longer needs a dark lead-in to a dark dock. */
.hero--stage .dock::before { display: none; }

/* The side review panels keep the deep green, so the composition still has a
   dark anchor either side of the film rather than losing it entirely. */


/* ------------------- Hero actions: weight, not decoration ----------------- */
.hero--stage .hero__actions { gap: var(--s4); margin-top: var(--s6); }
.hero--stage .hero__actions .btn {
  min-height: 62px;
  padding-inline: clamp(1.75rem, 2.6vw, 2.75rem);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 1px;
  border-width: 1px;
}
/* Solid sand with a darker edge, so it has an object quality rather than
   reading as a flat coloured rectangle. */
.hero--stage .btn--gold {
  --btn-fill: #f0c9a2;
  --btn-fg: #16281f;
  border-color: #d8a877;
  box-shadow: inset 0 -2px 0 rgba(143, 80, 36, 0.28);
}
.hero--stage .btn--gold:hover,
.hero--stage .btn--gold:focus-visible {
  --btn-fill: #f6d7b6;
  border-color: #c99560;
}
/* The secondary sits on a real surface instead of floating transparent over
   moving footage, so its label stays crisp on every frame. */
.hero--stage .btn--outline {
  --btn-fg: #fdfbf7;
  border-color: rgba(253, 251, 247, 0.72);
  background: rgba(9, 16, 12, 0.46);
  box-shadow: inset 0 -2px 0 rgba(253, 251, 247, 0.18);
}
.hero--stage .btn--outline:hover,
.hero--stage .btn--outline:focus-visible {
  border-color: #f0c9a2;
  color: #f6d7b6;
  background: rgba(9, 16, 12, 0.62);
}

/* The supporting line reads as composed editorial copy, not a caption. */
.hero--stage .hero__lede {
  font-size: clamp(1.15rem, 1rem + 0.55vw, 1.4rem);
  line-height: 1.62;
  letter-spacing: 0.004em;
  color: #f7f3ec;
  max-width: 44ch;
  text-shadow: 0 1px 20px rgba(6, 12, 9, 0.55);
}

/* Dock numerals: larger and legible on parchment rather than pale gold. */
.hero--stage .dock__index {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--copper-deep);
  letter-spacing: 0.02em;
}
.hero--stage .dock__audience {
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  color: var(--copper-deep);
}
.hero--stage .dock__label { gap: var(--s3); align-items: baseline; }


/* ------------------- Reviews: three spacious cards ----------------------- *
   One horizontal rail on a warm surface. Score panel left, readable cards
   right — not three vertical columns of clamped text, and not pure white.   */
.band--reviews {
  background: linear-gradient(180deg, var(--bone-sunk) 0%, var(--bone) 100%);
  color: var(--ink);
  --fg: var(--ink);
  --fg-soft: var(--ink-soft);
  --focus-ring: var(--ink);
  --focus-halo: rgba(143, 80, 36, 0.28);
  --line: var(--rule);
  --rule-strong: rgba(17, 26, 22, 0.42);
}
.band--reviews .chapter__index { color: var(--copper); }
.band--reviews .chapter__label { color: var(--ink-soft); }

.rwall__inner { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
.rwall__title { color: var(--ink); font-size: clamp(2.25rem, 1.6rem + 2vw, 3.5rem); }
.rwall__eyebrow { color: var(--copper-deep); }
.rwall__lede, .rwall__provenance { display: none; }

.score {
  margin-top: var(--s5);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--copper);
  background: var(--bone-raised);
}
.score__source { display: none; }
.score__value { color: var(--ink); font-size: clamp(3rem, 2rem + 2.4vw, 4rem); }
.score__stars { color: var(--copper); }
.score__count { color: var(--ink); }
.score__captured { color: var(--ink-soft); }
.score__note { display: none; }
.rwall__links { margin: var(--s4) 0 0; font-size: var(--t-small); }
.rwall__toggle {
  margin-top: var(--s5);
  border-color: var(--rule-strong);
  color: var(--ink);
}
.rwall__toggle:hover { border-color: var(--copper); color: var(--copper-deep); }

.rwall__window { overflow: hidden; }
.rwall__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: var(--s5);
  width: max-content;
}


.rcard {
  background: var(--bone-raised);
  border: 1px solid rgba(17, 26, 22, 0.14);
  border-radius: 4px;
  padding: var(--s6);
  gap: var(--s4);
  min-height: 19rem;
  align-content: start;
}
.rcard__quote p { font-size: 1.0625rem; line-height: 1.6; }

@media (min-width: 64em) {
  .rwall__inner { grid-template-columns: minmax(17rem, 20rem) minmax(0, 1fr); }
}

/* Horizontal travel for the rail, replacing the vertical column motion. */
/* Symmetrical: fading only the right edge left the LEFT edge as a razor cut
   that sawed words in half beside the score panel. */
[data-enhanced][data-motion="full"] .rwall__window { height: auto; mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 88%, transparent 100%); -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 88%, transparent 100%); }
[data-enhanced][data-motion="full"] .rwall__col { height: auto; }
[data-enhanced][data-motion="full"] .rwall__track {
  animation-name: rail-travel;
  padding-bottom: 0;
}
@keyframes rail-travel {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-50%, 0, 0); }
}
[data-wall-state="static"] .rwall__track { flex-wrap: wrap; width: auto; }


/* The rail must never widen its own column. */
.rwall__wall, .rwall__window { min-width: 0; max-width: 100%; overflow: hidden; }
.rwall__track > .rcard { flex: 0 0 auto; }

/* Exactly three cards in view on desktop, two at tablet, one on mobile. */
@media (min-width: 64em) {
  .rwall__track > .rcard { width: clamp(15rem, 20vw, 19rem); }
}
@media (min-width: 48em) and (max-width: 63.99em) {
  .rwall__track > .rcard { width: clamp(15rem, 34vw, 19rem); }
}
@media (max-width: 47.99em) {
  .rwall__track > .rcard { width: min(20rem, calc(100vw - var(--inset) * 2 - 1rem)); }
  .rcard { min-height: 0; padding: var(--s5); }
}


/* ===================== Hero: cinematic centre, proof wings ================ */

.hero--stage {
  min-height: clamp(640px, calc(100svh - var(--head-h)), 920px);
}
@media (min-width: 64em) and (min-height: 46rem) {
  .hero--stage { min-height: clamp(700px, calc(100svh - var(--head-h)), 920px); }
}
/* The short-laptop reset used to collapse the opening; the clamp above already
   protects short viewports, so it is no longer wanted. */
@media (min-width: 48em) and (max-height: 50rem) {
  .hero--stage { --stage-h: auto; min-height: clamp(640px, calc(100svh - var(--head-h)), 920px); }
}

.wing { display: none; }
.stage__film { left: 0; right: 0; }

@media (min-width: 75em) {
  .stage__film { left: 16%; right: 16%; }
  .wing {
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 16%;
    padding: var(--s6) clamp(1rem, 1.6vw, 2rem);
    background: linear-gradient(180deg, #0d2019 0%, #0a1a14 100%);
    pointer-events: none;
    overflow: hidden;
  }
  .wing--left { left: 0; border-right: 1px solid rgba(196, 148, 88, 0.4); }
  .wing--right { right: 0; border-left: 1px solid rgba(196, 148, 88, 0.4); }
}
@media (min-width: 90em) {
  .stage__film { left: 20%; right: 20%; }
  .wing { width: 20%; }
}

/* One quotation at a time, printed on the green — no card, no outline. */
.wing__inner { position: relative; width: 100%; display: grid; }
.wing__quote {
  grid-area: 1 / 1;
  margin: 0;
  display: grid;
  gap: var(--s3);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 550ms cubic-bezier(0.4, 0, 0.2, 1), transform 550ms cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.wing__quote[data-active] { opacity: 1; transform: none; }
.wing__index {
  margin: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  color: rgba(246, 244, 239, 0.5);
}
.wing__stars { margin: 0; font-size: 0.8125rem; letter-spacing: 0.24em; color: var(--sand); }
.wing__text { margin: 0; padding-top: var(--s3); border-top: 1px solid rgba(196, 148, 88, 0.42); }
.wing__text p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 0.85rem + 0.35vw, 1.2rem);
  line-height: 1.5;
  color: rgba(250, 246, 237, 0.94);
}
.wing__by { display: grid; gap: 2px; }
.wing__name { font-size: 0.8125rem; font-weight: 700; color: rgba(250, 246, 237, 0.92); }
.wing__source { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(239, 194, 154, 0.78); }
[data-motion="static"] .wing__quote { opacity: 0; transform: none; transition: none; }
[data-motion="static"] .wing__quote[data-active] { opacity: 1; }

/* ------------------------- Dock: back to deep green ---------------------- */
.hero--stage .dock {
  background: linear-gradient(180deg, #12362b 0%, #0b231c 100%);
  border-top: 1px solid rgba(196, 148, 88, 0.5);
}
.hero--stage .dock__list { background: rgba(196, 148, 88, 0.24); }
.hero--stage .dock__item { background: linear-gradient(180deg, #12362b 0%, #0b231c 100%); }
.hero--stage .dock__link { color: var(--on-deep); }
.hero--stage .dock__index,
.hero--stage .dock__audience { color: var(--sand); }
.hero--stage .dock__action { color: #faf6ed; }
.hero--stage .dock__cue { color: var(--sand); }
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: rgba(250, 246, 237, 0.08); }
.hero--stage .dock__link::after { background: var(--sand); }
.hero--stage .dock__link:focus-visible { outline-color: var(--on-deep); }

/* -------------------- The property dossier rises over it ------------------ */
.hero--stage { padding-bottom: 42px; }
/* Full-bleed warm lip rising over the foot of the film, with one copper
   hairline and a barely-there paper grain. The dock sits clear above it. */
.hero--stage::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 42px;
  z-index: 5;
  pointer-events: none;
  border-top: 1px solid rgba(143, 80, 36, 0.34);
  background:
    repeating-linear-gradient(102deg, rgba(143, 80, 36, 0.018) 0 2px, transparent 2px 6px),
    var(--bone);
}
.hero--stage + .band,
.hero--stage + .stagewrap { padding-top: clamp(2rem, 4vw, 4rem); }

/* Tablet and below: no wings, a compact sourced score under the actions. */
.hero__score { display: flex; }
@media (min-width: 75em) { .hero__score { display: none; } }
.hero__score {
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  margin-top: var(--s5);
  font-size: 0.875rem;
  color: rgba(250, 246, 237, 0.9);
}
.hero__score strong { font-size: 1.15rem; color: #faf6ed; }
.hero__score span { color: var(--sand); letter-spacing: 0.16em; }


/* ================= Hero centre: a film title sequence ==================== */

/* Eyebrow: small caps between two hairlines. No badge, no plate. */
.hero--stage .hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s4);
  justify-content: center;
  margin: 0 0 var(--s5);
  padding: 0;
  border: 0;
  background: none;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #e8c8a3;
}
.hero--stage .hero__eyebrow::before,
.hero--stage .hero__eyebrow::after {
  content: "";
  height: 1px;
  width: clamp(1.5rem, 4vw, 3.5rem);
  background: rgba(196, 148, 88, 0.62);
}

/* Two lines, warm ivory, held to a title-card measure. */
.hero--stage .h-hero {
  font-size: clamp(4rem, 4.6vw, 5.25rem);
  line-height: 0.99;
  letter-spacing: -0.022em;
  color: #f6f0e4;
  max-width: 760px;
  margin-inline: auto;
  text-shadow: 0 1px 24px rgba(6, 16, 12, 0.42);
  padding-bottom: 0.1em;
}
.hero--stage .h-hero span { display: block; }

.hero--stage .hero__lede {
  max-width: 560px;
  margin: var(--s5) auto 0;
  font-size: clamp(1.125rem, 1rem + 0.35vw, 1.25rem);
  line-height: 1.5;
  color: rgba(246, 240, 228, 0.9);
  text-shadow: 0 1px 18px rgba(6, 16, 12, 0.4);
}

/* One primary action; the second becomes a quiet directional link. */
.hero--stage .hero__actions { gap: var(--s5); align-items: center; }
.hero--stage .btn--gold {
  --btn-fill: #f0e3cd;
  --btn-fg: #12362b;
  border-color: rgba(143, 80, 36, 0.55);
  box-shadow: none;
  min-height: 56px;
}
.hero--stage .btn--gold:hover,
.hero--stage .btn--gold:focus-visible { --btn-fill: #f7eeddff; border-color: var(--copper); }
.hero__second {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #f6f0e4;
  text-decoration: none;
  border-bottom: 1px solid rgba(246, 240, 228, 0.42);
  padding-bottom: 2px;
}
.hero__second span { transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1); display: inline-block; }
.hero__second:hover,
.hero__second:focus-visible { color: #f0c9a2; border-color: #f0c9a2; }
.hero__second:hover span,
.hero__second:focus-visible span { transform: translateX(2px); }

/* Localised vignette only — the film keeps its own contrast everywhere else. */
.stage__veil {
  background:
    radial-gradient(
      ellipse 42% 46% at 50% 46%,
      rgba(7, 26, 20, 0.68) 0%,
      rgba(7, 26, 20, 0.4) 48%,
      rgba(7, 26, 20, 0.08) 74%,
      transparent 100%
    ),
    linear-gradient(180deg, rgba(7, 26, 20, 0.26) 0%, transparent 22%, transparent 74%, rgba(7, 26, 20, 0.34) 100%);
}

/* Joinery, not glow: one warm-bronze line where film meets proof wing. */
@media (min-width: 75em) {
  .wing--left { border-right: 1px solid rgba(176, 132, 78, 0.72); box-shadow: none; }
  .wing--right { border-left: 1px solid rgba(176, 132, 78, 0.72); box-shadow: none; }
  .wing--left::after, .wing--right::after { display: none; }
}

/* Entrance: rules and eyebrow, then the title, then copy and actions. */
[data-enhanced][data-motion="full"] .hero--stage .hero__eyebrow { opacity: 0; animation: hero-in 640ms cubic-bezier(0.4, 0, 0.2, 1) 80ms forwards; }
[data-enhanced][data-motion="full"] .hero--stage .h-hero { opacity: 0; animation: hero-rise 720ms cubic-bezier(0.4, 0, 0.2, 1) 220ms forwards; }
[data-enhanced][data-motion="full"] .hero--stage .hero__copy { opacity: 0; animation: hero-in 680ms cubic-bezier(0.4, 0, 0.2, 1) 420ms forwards; }
@keyframes hero-in { to { opacity: 1; } }
@keyframes hero-rise { from { transform: translateY(16px); } to { opacity: 1; transform: none; } }
[data-motion="static"] .hero--stage .hero__eyebrow,
[data-motion="static"] .hero--stage .h-hero,
[data-motion="static"] .hero--stage .hero__copy { opacity: 1 !important; animation: none !important; transform: none !important; }

@media (max-width: 63.99em) { .hero--stage .h-hero { font-size: clamp(2.9rem, 7vw, 4rem); } }
@media (max-width: 47.99em) { .hero--stage .h-hero { font-size: clamp(2.6rem, 9vw, 3.25rem); max-width: 100%; } }


/* At the largest sizes the 760px measure forces a third line; the title keeps
   its two-line composition instead. */
@media (min-width: 90em) {
  .hero--stage .h-hero { max-width: 940px; font-size: clamp(4rem, 4.2vw, 5rem); }
}


/* ---------------- Hero: smaller, and legible over every frame ------------ */

.hero--stage { min-height: clamp(580px, calc(88svh - var(--head-h)), 800px); }
@media (min-width: 64em) and (min-height: 46rem) {
  .hero--stage { min-height: clamp(600px, calc(86svh - var(--head-h)), 800px); }
}
@media (min-width: 48em) and (max-height: 50rem) {
  .hero--stage { min-height: clamp(560px, calc(90svh - var(--head-h)), 800px); }
}

/* A touch smaller, so the film carries more of the frame. */
.hero--stage .h-hero { font-size: clamp(3.4rem, 3.9vw, 4.5rem); }
@media (min-width: 90em) { .hero--stage .h-hero { font-size: clamp(3.6rem, 3.6vw, 4.4rem); max-width: 880px; } }
@media (max-width: 63.99em) { .hero--stage .h-hero { font-size: clamp(2.7rem, 6.2vw, 3.5rem); } }
@media (max-width: 47.99em) { .hero--stage .h-hero { font-size: clamp(2.4rem, 8.4vw, 3rem); } }

/* The scrim reached only the title. It now covers the whole copy column,
   including the actions, which is where the film was brightest. */
.stage__veil {
  background:
    radial-gradient(
      ellipse 48% 62% at 50% 52%,
      rgba(7, 26, 20, 0.8) 0%,
      rgba(7, 26, 20, 0.58) 42%,
      rgba(7, 26, 20, 0.26) 68%,
      rgba(7, 26, 20, 0.05) 86%,
      transparent 100%
    ),
    linear-gradient(180deg, rgba(7, 26, 20, 0.3) 0%, transparent 20%, transparent 60%, rgba(7, 26, 20, 0.46) 100%);
}

.hero--stage .hero__lede {
  color: #f2ecdf;
  text-shadow: 0 1px 16px rgba(5, 14, 10, 0.72);
}
.hero--stage .h-hero { text-shadow: 0 2px 28px rgba(5, 14, 10, 0.6); }

/* The secondary link was disappearing into bright rooftops. */
.hero__second {
  padding: 10px 14px;
  border: 1px solid rgba(246, 240, 228, 0.34);
  border-bottom-color: rgba(246, 240, 228, 0.34);
  background: rgba(7, 20, 15, 0.42);
  text-shadow: 0 1px 12px rgba(5, 14, 10, 0.6);
}
.hero__second:hover,
.hero__second:focus-visible { background: rgba(7, 20, 15, 0.6); border-color: #f0c9a2; }

/* The primary reads as parchment, not a plain white slab. */
.hero--stage .btn--gold { --btn-fill: #efe0c6; border-color: rgba(143, 80, 36, 0.6); }


/* The copy block sat low against the dock; it lifts into the upper-middle of
   the film, with the scrim following it so the protection stays aligned. */
.hero--stage .hero__panel {
  margin: auto auto 0;
  padding-bottom: clamp(4.5rem, 11vh, 8.5rem);
}
.stage__veil {
  background:
    radial-gradient(
      ellipse 48% 60% at 50% 45%,
      rgba(7, 26, 20, 0.8) 0%,
      rgba(7, 26, 20, 0.58) 42%,
      rgba(7, 26, 20, 0.26) 68%,
      rgba(7, 26, 20, 0.05) 86%,
      transparent 100%
    ),
    linear-gradient(180deg, rgba(7, 26, 20, 0.3) 0%, transparent 20%, transparent 60%, rgba(7, 26, 20, 0.46) 100%);
}


/* ======================= Header: wider navigation ======================== */
@media (min-width: 64em) {
  .site-head__inner {
    max-width: 1840px;
    padding-inline: clamp(32px, 4.5vw, 88px);
    display: grid;
    grid-template-columns: 180px minmax(620px, 860px) 190px;
    justify-content: space-between;
    align-items: center;
    min-height: 86px;
    gap: var(--s5);
    transition: min-height 350ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .nav--wide { display: block; margin: 0; justify-self: center; width: 100%; }
  .nav--wide .nav__list {
    width: clamp(580px, 46vw, 840px);
    margin-inline: auto;
    display: flex;
    justify-content: space-between;
    gap: var(--s4);
    flex-wrap: nowrap;
  }
  .nav__link {
    font-size: 0.9688rem;
    font-weight: 500;
    letter-spacing: 0.005em;
    border-bottom: 0;
    position: relative;
    white-space: nowrap;
  }
  /* Underline grows from the left rather than switching on. */
  .nav__link::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 10px;
    height: 2px;
    width: 32px;
    max-width: 100%;
    background: var(--copper);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .nav__link:hover::after,
  .nav__link:focus-visible::after { transform: scaleX(1); }
  .nav__link[aria-current="page"]::after { transform: scaleX(1); background: var(--bottle); }
  .site-head__cta { justify-self: end; margin: 0; }
  .brand { justify-self: start; }
  /* Compressed state on scroll. */
  [data-scrolled="true"] .site-head__inner { min-height: 74px; }
  [data-scrolled="true"] .brand__mark { height: 48px; transition: height 350ms cubic-bezier(0.4, 0, 0.2, 1); }
  .brand__mark { transition: height 350ms cubic-bezier(0.4, 0, 0.2, 1); }
}
@media (min-width: 64em) and (max-width: 68.75em) {
  .site-head__inner { grid-template-columns: 150px minmax(0, 1fr) 170px; padding-inline: clamp(20px, 3vw, 40px); }
  .nav--wide .nav__list { width: 100%; gap: var(--s3); }
  .nav__link { font-size: 0.9rem; }
}

/* ==================== Route dock: quieter wayfinding ===================== */
.hero--stage .dock__link {
  min-height: 112px;
  padding: 22px clamp(30px, 2.4vw, 38px);
}
.hero--stage .dock__index { font-size: 0.8125rem; font-weight: 700; }
.hero--stage .dock__audience { font-size: 0.78rem; letter-spacing: 0.11em; }
.hero--stage .dock__action {
  font-size: clamp(1.5rem, 1.3rem + 0.35vw, 1.85rem);
  line-height: 1.1;
  color: #f6f0e4;
}
.hero--stage .dock__cue { font-size: 1.15rem; }
.hero--stage .dock__link:hover .dock__cue,
.hero--stage .dock__link:focus-visible .dock__cue { transform: translateX(5px); }
.hero--stage .dock__link {
  transition: background-color 275ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: rgba(246, 240, 228, 0.07); }
.hero--stage .dock__link:focus-visible { outline: 2px solid var(--sand); outline-offset: -4px; }

/* ================== Why Dukes: the dossier opening ====================== */
/* The band itself no longer carries an arrival of its own: it is the scroll
   stage now, and its opacity and transform are driven by scroll progress at the
   end of this file. Two systems on one element would fight, and the one tied to
   the reader's own scrolling is the one worth keeping. Its contents — rule,
   photograph, copy — still arrive on the observer. */

[data-enhanced][data-motion="full"] .band--dossier .chapter__rule { transform: scaleX(0); transform-origin: left center; }
[data-enhanced][data-motion="full"] .band--dossier.is-in .chapter__rule {
  transform: scaleX(1);
  transition: transform 550ms cubic-bezier(0.4, 0, 0.2, 1) 120ms;
}

[data-enhanced][data-motion="full"] .band--dossier .welcome__photo {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.015);
}
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__photo {
  clip-path: inset(0 0 0 0);
  transform: none;
  transition: clip-path 800ms cubic-bezier(0.4, 0, 0.2, 1) 100ms, transform 800ms cubic-bezier(0.4, 0, 0.2, 1) 100ms;
}

/* The copy lifts; it does not also fade. The band around it is the scroll stage
   now and already carries opacity 0.75 → 1, so fading each line from zero on
   top of that multiplied out to roughly a third — the heading read as washed
   out for half a second at exactly the moment it is meant to land. One fade,
   on the chapter, and a quiet stagger of lifts inside it. */
[data-enhanced][data-motion="full"] .band--dossier .welcome__copy > * {
  transform: translateY(14px);
}
/* The larger offset belongs to the starting state. It used to sit on the
   settled rule, which left the second line permanently 18px low. */
[data-enhanced][data-motion="full"] .band--dossier .welcome__copy > *:nth-child(2) {
  transform: translateY(18px);
}
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *,
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *:nth-child(2) {
  transform: none;
  transition: transform 520ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *:nth-child(1) { transition-delay: 180ms; }
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *:nth-child(2) { transition-delay: 250ms; }
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *:nth-child(n+3) { transition-delay: 330ms; }
[data-enhanced][data-motion="full"] .band--dossier.is-in .welcome__copy > *:nth-child(n+5) { transition-delay: 400ms; }

[data-motion="static"] .band--dossier,
[data-motion="static"] .band--dossier .welcome__copy > * {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}
[data-motion="static"] .band--dossier .welcome__photo { clip-path: none !important; transform: none !important; }
[data-motion="static"] .band--dossier .chapter__rule { transform: none !important; }


/* ================= Hero materials: contrast, not more green ============== */
:root {
  --smoked-ink: #161b18;
  --smoked-ink-raised: #1d2420;
  --champagne: #e8dcc4;
  --parchment: #f3ebdd;
  --warm-ivory: #f6f0e4;
}

body { background: var(--parchment); }
.hero--stage::after { background: var(--parchment); }

/* Review wings become smoked editorial folios rather than green slabs. */
@media (min-width: 75em) {
  .wing {
    background: linear-gradient(180deg, var(--smoked-ink) 0%, #121715 100%);
    padding: var(--s7) clamp(1.25rem, 2vw, 2.25rem);
  }
  .wing--left { border-right: 1px solid rgba(143, 80, 36, 0.55); }
  .wing--right { border-left: 1px solid rgba(143, 80, 36, 0.55); }
}
.wing__inner { position: relative; }
.wing__inner::before {
  content: "\201C";
  position: absolute;
  top: -0.5em;
  left: -0.05em;
  font-family: var(--font-display);
  font-size: 6rem;
  line-height: 1;
  color: rgba(239, 194, 154, 0.13);
  pointer-events: none;
}
.wing__text { border-top: 1px solid rgba(143, 80, 36, 0.55); padding-top: var(--s4); }
.wing__text p {
  font-size: clamp(1.05rem, 0.85rem + 0.55vw, 1.45rem);
  line-height: 1.5;
  color: var(--warm-ivory);
}
.wing__name { font-size: 0.8125rem; font-weight: 500; color: rgba(246, 240, 228, 0.92); }
.wing__source { font-size: 0.6563rem; letter-spacing: 0.16em; color: rgba(246, 240, 228, 0.62); }
.wing__index { font-size: 0.6563rem; color: rgba(246, 240, 228, 0.45); letter-spacing: 0.16em; }
.wing__stars { color: var(--sand); font-size: 0.75rem; }
.wing__quote { transition: opacity 550ms cubic-bezier(0.4, 0, 0.2, 1), transform 550ms cubic-bezier(0.4, 0, 0.2, 1); }
.wing__quote:not([data-active]) { transform: translateY(-8px); }
.wing__quote[data-active] { transform: translateY(0); }
.wing__quote[data-active] .wing__by { transition-delay: 70ms; }

/* Neutral smoked vignette; the film keeps its own colour. */
.stage__veil {
  background:
    radial-gradient(
      ellipse 46% 58% at 50% 45%,
      rgba(12, 15, 14, 0.72) 0%,
      rgba(12, 15, 14, 0.38) 50%,
      rgba(12, 15, 14, 0.08) 74%,
      transparent 100%
    ),
    linear-gradient(180deg, rgba(12, 15, 14, 0.26) 0%, transparent 20%, transparent 64%, rgba(12, 15, 14, 0.34) 100%);
}
.stage__video, .stage__poster img { filter: saturate(0.94) contrast(0.97) brightness(1.03); }

/* Eyebrow as a film credit. */
.hero--stage .hero__eyebrow {
  max-width: 520px;
  margin-inline: auto;
  font-size: 0.75rem;
  letter-spacing: 0.13em;
  color: #e5c49c;
}
.hero--stage .hero__eyebrow::before,
.hero--stage .hero__eyebrow::after { width: clamp(1.5rem, 3vw, 2.75rem); }
.hero--stage .hero__eyebrow::before { background: linear-gradient(90deg, transparent, rgba(196, 148, 88, 0.75)); }
.hero--stage .hero__eyebrow::after { background: linear-gradient(270deg, transparent, rgba(196, 148, 88, 0.75)); }

/* Headline: one masked two-line reveal. */
.hero--stage .h-hero { color: var(--warm-ivory); font-size: clamp(3.4rem, 3.9vw, 4.6rem); line-height: 0.98; }
[data-enhanced][data-motion="full"] .hero--stage .h-hero {
  animation: none;
  opacity: 1;
  clip-path: inset(0 0 100% 0);
  transform: translateY(18px);
  transition: clip-path 800ms cubic-bezier(0.4, 0, 0.2, 1) 260ms, transform 800ms cubic-bezier(0.4, 0, 0.2, 1) 260ms;
}
[data-enhanced][data-motion="full"] .hero--stage.is-lit .h-hero { clip-path: inset(0 0 0 0); transform: none; }

.hero--stage .hero__lede {
  font-size: clamp(1.0625rem, 1rem + 0.2vw, 1.1875rem);
  max-width: 590px;
  line-height: 1.5;
  color: rgba(246, 240, 228, 0.86);
}

/* CTAs: one champagne control, one refined text link. */
.hero--stage .btn--gold {
  --btn-fill: var(--champagne);
  --btn-fg: var(--bottle-deep);
  border: 1px solid rgba(143, 80, 36, 0.5);
  min-height: 50px;
  padding-inline: 27px;
  font-size: 0.9688rem;
  font-weight: 500;
  box-shadow: none;
  transition: background-color 220ms cubic-bezier(0.4, 0, 0.2, 1), border-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero--stage .btn--gold:hover,
.hero--stage .btn--gold:focus-visible { --btn-fill: #efe4cf; border-color: var(--copper); }
.hero__second {
  border: 0;
  background: none;
  padding: 12px 2px;
  min-height: 44px;
  color: var(--warm-ivory);
  font-weight: 500;
  position: relative;
  text-shadow: 0 1px 14px rgba(8, 12, 10, 0.75);
}
.hero__second::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 8px;
  height: 1px;
  background: rgba(239, 194, 154, 0.85);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 240ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero__second:hover::after, .hero__second:focus-visible::after { transform: scaleX(1); }
.hero__second:hover, .hero__second:focus-visible { color: var(--sand); background: none; }

/* Route rail: champagne wayfinding, not an extension of the green. */
.hero--stage .dock,
.hero--stage .dock__item { background: var(--champagne); }
.hero--stage .dock { border-top: 1px solid rgba(143, 80, 36, 0.42); }
.hero--stage .dock__list { background: rgba(18, 54, 43, 0.18); }
.hero--stage .dock__link {
  min-height: 92px;
  padding: 16px 29px;
  color: var(--ink);
  transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero--stage .dock__index,
.hero--stage .dock__audience { font-size: 0.6875rem; letter-spacing: 0.11em; color: var(--copper-deep); font-weight: 700; }
.hero--stage .dock__action { font-size: clamp(1.375rem, 1.2rem + 0.35vw, 1.625rem); line-height: 1.1; color: var(--ink); }
.hero--stage .dock__cue { font-size: 1.05rem; color: var(--copper); }
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: #ded0b7; }
.hero--stage .dock__link::after { background: var(--bottle); height: 2px; }
.hero--stage .dock__link:focus-visible { outline: 2px solid var(--bottle); outline-offset: -4px; }

[data-motion="static"] .hero--stage .h-hero { clip-path: none !important; transform: none !important; }

/* A small lift when the pointer rests on a review. The transform sits on the
   container, not the quote, so it cannot fight the crossfade already animating
   the quote's own transform. The wings hold no links or focusable content, so
   accepting pointer events here still cannot steal a click or a focus. */
@media (min-width: 75em) and (hover: hover) and (pointer: fine) {
  .wing { pointer-events: auto; }
  .wing__inner { transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1); will-change: transform; }
  .wing:hover .wing__inner { transform: translateY(-4px); }
}
[data-motion="static"] .wing:hover .wing__inner { transform: none !important; }


/* ========================= Header navigation ============================= */
.site-head__actions { display: none; }

@media (min-width: 64em) {
  .site-head__inner {
    grid-template-columns: 170px minmax(0, 1fr) auto;
    gap: clamp(1rem, 2.4vw, 2.5rem);
  }
  .site-head__cta { display: none; }
  .site-head__actions { display: flex; align-items: center; gap: var(--s3); justify-self: end; }

  .nav--wide .nav__list { width: auto; justify-content: center; gap: clamp(0.75rem, 2vw, 2.25rem); }
  .nav__item { position: static; }
  .nav__link,
  .nav__link--trigger {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    padding: 0 2px;
    background: none;
    border: 0;
    font: inherit;
    font-size: 0.9688rem;
    font-weight: 500;
    color: var(--ink);
    cursor: pointer;
  }
  .nav__caret {
    width: 6px; height: 6px;
    border-right: 1.5px solid var(--copper);
    border-bottom: 1.5px solid var(--copper);
    transform: rotate(45deg) translateY(-1px);
    transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  [aria-expanded="true"] .nav__caret { transform: rotate(-135deg) translateY(-2px); }

  .mega {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 30;
    background: var(--parchment);
    border-top: 1px solid rgba(143, 80, 36, 0.5);
    border-bottom: 1px solid rgba(17, 26, 22, 0.12);
    box-shadow: 0 18px 34px -30px rgba(17, 26, 22, 0.6);
  }
  .mega[data-open] { animation: mega-in 240ms cubic-bezier(0.4, 0, 0.2, 1) both; }
  @keyframes mega-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

  .mega__inner {
    max-width: 1840px;
    margin-inline: auto;
    padding: clamp(1.75rem, 3vw, 2.75rem) clamp(32px, 4.5vw, 88px);
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr) auto;
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: start;
  }
  .mega__intro {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    line-height: 1.4;
    color: var(--bottle);
    max-width: 26ch;
  }
  .mega__links { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
  .mega__link {
    display: grid;
    gap: 2px;
    min-height: 44px;
    align-content: center;
    padding: var(--s2) var(--s3);
    margin-left: calc(var(--s3) * -1);
    text-decoration: none;
    color: var(--ink);
    transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .mega__link:hover, .mega__link:focus-visible { background: rgba(232, 220, 196, 0.6); }
  .mega__label { font-weight: 600; font-size: 1rem; display: inline-flex; align-items: center; gap: 8px; }
  .mega__arrow { color: var(--copper); transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1); }
  .mega__link:hover .mega__arrow, .mega__link:focus-visible .mega__arrow { transform: translateX(4px); }
  .mega__note { font-size: var(--t-small); color: var(--ink-soft); }
  .mega__cta { margin: 0; justify-self: end; }

  .headact {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--s5);
    font-size: 0.9375rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 220ms cubic-bezier(0.4, 0, 0.2, 1), border-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .headact--utility { color: var(--bottle); border: 1px solid rgba(18, 54, 43, 0.28); background: rgba(250, 246, 237, 0.7); }
  .headact--utility:hover { border-color: var(--bottle); background: #faf6ed; }
  .headact--primary { color: var(--bottle-deep); background: var(--champagne); border: 1px solid rgba(143, 80, 36, 0.5); }
  .headact--primary:hover { background: #efe4cf; border-color: var(--copper); }
}

@media (prefers-reduced-motion: reduce) {
  .mega[data-open] { animation: none; }
}

/* -------------------------- Mobile accordions ---------------------------- */
.mnav { list-style: none; margin: 0; padding: 0; }
.mnav__item { border-bottom: 1px solid var(--rule); }
.mnav__summary,
.mnav__link--top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  text-decoration: none;
}
.mnav__summary::-webkit-details-marker { display: none; }
.mnav__caret {
  width: 7px; height: 7px;
  border-right: 1.5px solid var(--copper);
  border-bottom: 1.5px solid var(--copper);
  transform: rotate(45deg);
  transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.mnav__group[open] .mnav__caret { transform: rotate(-135deg); }
.mnav__sub { list-style: none; margin: 0 0 var(--s3); padding: 0 0 0 var(--s4); display: grid; }
.mnav__link {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  text-decoration: none;
}
.mnav__link:hover { color: var(--copper-deep); }


/* ===================== Dukes navy: the missing colour ==================== */
:root {
  --dukes-navy: #0b223b;
  --dukes-navy-deep: #07182a;
  --brand-brass: #b6873e;
  --brand-parchment: #e9dcc4;
  --brand-ivory: #f7f1e6;
}

body { background: var(--brand-ivory); }
.hero--stage::after { background: var(--brand-ivory); }

/* ---- Review wings: navy editorial panels ---- */
@media (min-width: 75em) {
  .wing {
    background: linear-gradient(180deg, var(--dukes-navy) 0%, var(--dukes-navy-deep) 100%);
    padding: var(--s7) clamp(1.5rem, 2.2vw, 2.5rem);
  }
  .wing--left { border-right: 1px solid rgba(182, 135, 62, 0.5); }
  .wing--right { border-left: 1px solid rgba(182, 135, 62, 0.5); }
}
/* The oversized quotation mark goes: it competed with the film. */
.wing__inner::before { content: none; }
.wing__text { border-top: 1px solid rgba(182, 135, 62, 0.45); padding-top: var(--s4); }
.wing__text p { color: var(--brand-ivory); line-height: 1.55; }
.wing__stars { color: var(--brand-brass); }
.wing__name { color: rgba(247, 241, 230, 0.94); }
.wing__source, .wing__index { color: rgba(182, 135, 62, 0.85); }

/* ---- Eyebrow: a readable navy label, not faint tracking ---- */
.hero--stage .hero__eyebrow {
  display: inline-flex;
  padding: 7px 15px;
  background: rgba(11, 34, 59, 0.82);
  border: 1px solid rgba(182, 135, 62, 0.5);
  color: #f0d9b4;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  max-width: none;
}
.hero--stage .hero__eyebrow::before,
.hero--stage .hero__eyebrow::after { content: none; }

/* ---- Headline: descender never clipped ---- */
.hero--stage .h-hero {
  font-size: clamp(3.2rem, 3.7vw, 4.35rem);
  line-height: 1.04;
  max-width: 900px;
  overflow: visible;
  padding-bottom: 0.14em;
  color: var(--brand-ivory);
}
[data-enhanced][data-motion="full"] .hero--stage .h-hero {
  clip-path: none;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 800ms cubic-bezier(0.4, 0, 0.2, 1) 260ms, transform 800ms cubic-bezier(0.4, 0, 0.2, 1) 260ms;
}
[data-enhanced][data-motion="full"] .hero--stage.is-lit .h-hero { opacity: 1; transform: none; }
.hero--stage .hero__lede { max-width: 56ch; line-height: 1.58; color: rgba(247, 241, 230, 0.9); }

/* ---- Primary CTA: navy rises behind the label ---- */
.hero--stage .btn--gold {
  position: relative;
  overflow: hidden;
  --btn-fill: var(--brand-parchment);
  --btn-fg: var(--dukes-navy);
  border: 1px solid rgba(182, 135, 62, 0.65);
  border-radius: 2px;
  transition: color 240ms cubic-bezier(0.4, 0, 0.2, 1), transform 140ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero--stage .btn--gold::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--dukes-navy);
  transform: translateY(101%);
  transition: transform 240ms cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: none;
}
.hero--stage .btn--gold:hover,
.hero--stage .btn--gold:focus-visible { color: var(--brand-ivory); }
.hero--stage .btn--gold:hover::after,
.hero--stage .btn--gold:focus-visible::after { transform: translateY(0); }
.hero--stage .btn--gold:active { transform: translateY(1px); }

/* ---- Secondary: a real outlined control ---- */
.hero__second {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 50px;
  padding: 0 22px;
  border: 1px solid rgba(247, 241, 230, 0.58);
  border-radius: 2px;
  background: rgba(11, 34, 59, 0.3);
  color: var(--brand-ivory);
  transition: background-color 240ms cubic-bezier(0.4, 0, 0.2, 1), border-color 240ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero__second::after { content: none; }
.hero__second span { transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1); }
.hero__second:hover, .hero__second:focus-visible {
  background: rgba(11, 34, 59, 0.62);
  border-color: var(--brand-ivory);
  color: var(--brand-ivory);
}
.hero__second:hover span, .hero__second:focus-visible span { transform: translateX(4px); }

/* ---- Journey dock: navy, brass-ruled, no numerals ---- */
.hero--stage .dock,
.hero--stage .dock__item {
  background: linear-gradient(180deg, var(--dukes-navy) 0%, var(--dukes-navy-deep) 100%);
}
.hero--stage .dock { border-top: 1px solid var(--brand-brass); box-shadow: none; }
.hero--stage .dock__list { background: rgba(247, 241, 230, 0.12); max-width: var(--max); }
.hero--stage .dock__link {
  min-height: 88px;
  padding: 14px 28px;
  color: var(--brand-ivory);
  transition: background-color 240ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero--stage .dock__audience {
  font-size: 0.6875rem;
  letter-spacing: 0.15em;
  color: rgba(214, 174, 116, 0.95);
  font-weight: 700;
}
.hero--stage .dock__action { font-size: clamp(1.3rem, 1.15rem + 0.3vw, 1.5rem); color: var(--brand-ivory); }
.hero--stage .dock__cue { color: var(--brand-brass); }
.hero--stage .dock__link:hover,
.hero--stage .dock__link:focus-visible { background: rgba(247, 241, 230, 0.06); }
.hero--stage .dock__link::after { background: var(--brand-brass); height: 1px; }
.hero--stage .dock__link:hover::after,
.hero--stage .dock__link:focus-visible::after { height: 2px; transform: scaleX(1); }
.hero--stage .dock__link:focus-visible { outline: 2px solid var(--brand-brass); outline-offset: -4px; }


/* ============ The scroll transition: hero lets go, chapter lands ========== *
   One event in two halves, both driven by the same scroll range from
   scroll-stage.mjs. Nothing here is a keyframe or a timeline; every value is a
   function of a progress custom property, so scrolling back up reverses it
   exactly and stopping half way holds a real intermediate state.

   Deliberately NOT here: the route dock. It is wayfinding sitting on the seam
   between the film and the page, and wayfinding that drifts while you are
   reaching for it is worse than wayfinding that stays still.                 */

/* --- Half one: the hero lets go ---------------------------------------- */

/* Declared, not just defaulted in each var(): the hero reads as un-departed
   before a single frame of script has run. */
.hero--stage { --hero-exit: 0; }

/* The cream shutters close over the FILM, not over the whole hero. They were
   built when the hero was one full-bleed film and nothing else, so they ran
   from the viewport edges; once navy review panels arrived either side of the
   film, that meant cream slabs travelling across those panels and guillotining
   the quotations mid-word half way through the scroll. They now live inside
   `.stage__film`, whose `overflow: hidden` gives them exactly the right extent
   for free — so their own geometry goes back to the simple full-width pair,
   measured against the film rather than the viewport. */

/* The film recedes by 1.5%. Its own surround shows for a few pixels at the
   edges as it does, so that surround has to belong to the palette rather than
   being the black it was inheriting from the video element. */
/* Scoped to the hero. `.stage` is also the valuation form's fieldset class,
   and an unscoped rule here painted that form navy. */
[data-hero-stage] { background: var(--dukes-navy-deep); }

[data-enhanced][data-motion="full"] .hero--stage .stage__film {
  transform: scale(calc(1 - var(--hero-exit, 0) * 0.015));
  /* Anchored at the top edge so no gap can open under the sticky header; the
     bottom edge travels up behind the opaque dock, where it is never seen. */
  transform-origin: 50% 0%;
}

/* The copy leaves first and furthest — it is what the reader has finished
   with. 18px, inside the 16–20px the brief allows. */
[data-enhanced][data-motion="full"] .hero--stage .hero__panel {
  transform: translate3d(0, calc(var(--hero-exit, 0) * -18px), 0);
}

/* The proof wings part outward and dim to 0.82. The drift is on the printed
   contents, not on the panels: the panels are butted against the film edge, and
   moving those would open a seam where the joinery keyline is. `overflow:
   hidden` on the panel clips the drift cleanly. */
@property --wing-lift {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
[data-enhanced][data-motion="full"] .wing__inner {
  opacity: calc(1 - var(--hero-exit, 0) * 0.18);
}
[data-enhanced][data-motion="full"] .wing--left .wing__inner {
  transform: translate3d(calc(var(--hero-exit, 0) * -12px), var(--wing-lift, 0px), 0);
}
[data-enhanced][data-motion="full"] .wing--right .wing__inner {
  transform: translate3d(calc(var(--hero-exit, 0) * 12px), var(--wing-lift, 0px), 0);
}

/* The hover lift becomes a transitioned custom property rather than a second
   transform, so the pointer response and the scroll drift compose instead of
   overwriting each other. A transition on `transform` would also have dragged
   the scroll-linked drift 320ms behind the reader's own scrolling. */
@media (min-width: 75em) and (hover: hover) and (pointer: fine) {
  .wing__inner {
    transition: --wing-lift 320ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: auto;
  }
  /* The two rules above are more specific than this one, so the lift arrives
     purely as a change to the property they both already read. */
  .wing:hover .wing__inner { --wing-lift: -4px; }
}

/* The dock is the one thing in the hero that must not move: it is wayfinding
   sitting on the seam between the film and the page, and wayfinding that drifts
   while you are reaching for it is worse than wayfinding that stays still. */
[data-enhanced][data-motion="full"] .hero--stage .dock { transform: none; }

/* --- Half two: the chapter lands --------------------------------------- */

/* 32px, 0.975→1, 3°, 0.75→1. The earlier 14° and 0.94 read as a slide deck
   flying in; at 3° the page simply arrives level, which is the difference
   between a premium settle and a transition effect.

   Order matters: translate, then scale, then rotate. The rotation is applied
   last so the 32px is travelled in screen space rather than along an axis that
   is itself tilting. */
[data-enhanced][data-motion="full"] .stagewrap__inner {
  transform-origin: 50% 0%;
  transform:
    translate3d(0, calc((1 - var(--stage-progress, 1)) * 32px), 0)
    scale(calc(0.975 + var(--stage-progress, 1) * 0.025))
    rotateX(calc((1 - var(--stage-progress, 1)) * 3deg));
  /* Floor raised from the brief's 0.75 to 0.88 on accessibility grounds. At
     0.75 the chapter's own small text composites down to 4.44:1 against paper
     and axe fails it — and that is the state the page rests in before anyone
     scrolls, not a transient frame. 0.88 keeps the arrival clearly visible
     while holding the numbered plate at 5.4:1 at its faintest. */
  opacity: calc(0.88 + var(--stage-progress, 1) * 0.12);
  /* Left to the module, which drops the layer once the settle has finished.
     Declaring it here permanently would have made that release a no-op. */
  will-change: auto;
}

/* --- Reduced motion: the settled state, instantly ----------------------- *
   Asserted twice on purpose. The data attribute is what the modules set, and
   the media query catches the case where the stylesheet has loaded but
   enhance.mjs has not run or has failed.                                    */
[data-motion="static"] .hero--stage .stage__film,
[data-motion="static"] .hero--stage .hero__panel,
[data-motion="static"] .wing__inner,
[data-motion="static"] .wing:hover .wing__inner,
[data-motion="static"] .stagewrap__inner {
  transform: none !important;
  opacity: 1 !important;
  transition: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .hero--stage .stage__film,
  .hero--stage .hero__panel,
  .wing__inner,
  .wing:hover .wing__inner,
  .stagewrap__inner {
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
}


/* ========================================================================== *
 *  COLOUR SYSTEM — homepage approval pass
 *
 *  The problem this replaces: three generations of palette were stacked in
 *  :root (bone/bottle/copper, then smoked-ink/champagne, then dukes-navy/
 *  brand-brass), and the newest generation had taken the logo's navy and
 *  spread it across both review wings, the whole route dock, the eyebrow and
 *  the secondary button. Sampling a colour off the logo and repeating it at
 *  full size everywhere is what makes the logo stop feeling like the asset.
 *
 *  The rule here is that the logo is a signature, not a palette generator.
 *  Navy appears in the genuine mark and almost nowhere else; the interface
 *  around it is warm architectural neutral, and it is restraint that makes
 *  the mark read as valuable.
 *
 *  Primitives are declared globally because the shell (header, footer, legal
 *  strip) is shared and the logo-safe rule has to hold on every page. The
 *  page-body surface assignments are scoped to [data-page="home"], because
 *  the homepage is the approval prototype and the other pages must not move
 *  until Aarav has signed this off.
 * ========================================================================== */

:root {
  /* ---- Primitives: warm architectural neutrals ---- */
  --surface-paper: #f3eee5;
  --surface-ivory: #faf7f0;
  --surface-parchment: #e8decc;
  --surface-limestone: #d5c8b4;
  --surface-mushroom: #b9ad9d;

  --surface-charcoal: #292722;
  --surface-olive-charcoal: #1d241f;

  --text-ink: #1c211f;
  /* Darkened twice. #69665f measured 4.3:1 on parchment; #5f5c55 then cleared
     paper and parchment but only reached 4.04:1 on limestone, which is the
     darkest of the light surfaces and the one the route dock, the journey
     gateway and the comparison tables all sit on. Measured against limestone
     rather than against the lightest surface it happens to appear on. */
  --text-muted: #56534a;
  --text-on-dark-warm: #f4eee3;

  /* Two brasses, and the difference between them is load-bearing.
     --accent-brass is the decorative one: rules, arrows, hairlines, marks
     that carry no reading burden. It does not reach 4.5:1 on a light
     surface, so it is never used for small text there.
     --accent-brass-deep is the one that carries small labels on parchment
     and limestone, measured at 5:1 rather than assumed. */
  --accent-brass: #a97842;
  --accent-brass-deep: #6b4620;
  --accent-champagne: #c5a66a;
  --accent-bottle-green: #315345;

  /* The protected signature. Outside the genuine mark this appears only as
     fine detail: an active-navigation rule, a focus ring, a legal link. */
  --brand-navy: #0b223b;

  /* ---- Semantic tokens: what components are allowed to consume ---- */
  --surface-page: var(--surface-paper);
  --surface-raised: var(--surface-ivory);
  --surface-muted: var(--surface-limestone);
  --surface-dark: var(--surface-olive-charcoal);
  --surface-nav: var(--surface-parchment);

  --text-primary: var(--text-ink);
  --text-secondary: var(--text-muted);
  --text-on-dark: var(--text-on-dark-warm);
  --text-on-dark-soft: rgba(244, 238, 227, 0.78);

  --border-subtle: rgba(28, 33, 31, 0.14);
  --border-strong: rgba(28, 33, 31, 0.28);
  --border-on-dark: rgba(244, 238, 227, 0.18);
  --border-brass: rgba(169, 120, 66, 0.55);

  --action-primary-fill: var(--surface-parchment);
  --action-primary-fg: var(--text-ink);
  --action-secondary-fg: var(--text-on-dark-warm);
}

/* ================================ SHELL ================================== *
   Header, footer and legal strip are shared, so they take the new system on
   every page. The logo-safe rule is not a homepage preference.              */

/* ---- 1. Sticky header: a calm light surface, and nothing else ---- */
.site-head {
  background: var(--surface-nav);
  border-bottom: 1px solid var(--border-subtle);
}
/* The mark sits on an uninterrupted light field with real clear space, and
   carries no ring, plate, box or outline of its own. */
.brand__ring { display: none; }
/* Padding zeroed on both axes: the block padding was making the brand cell
   66px tall, which floated the whole header above its 78-84px band. */
.brand { padding: 0; background: none; border: 0; }

@media (min-width: 64em) {
  /* 78–84px, closed and open alike. The dropdown is absolutely positioned,
     so it cannot contribute to this. */
  .site-head__inner { min-height: 82px; padding-block: 10px; }
  [data-scrolled="true"] .site-head__inner { min-height: 78px; }
  [data-scrolled="true"] .brand__mark { height: 47px; }
  .brand__mark { height: 50px; }
}

/* ---- Navigation triggers: transparent, no form-control boxes ---- */
@media (min-width: 64em) {
  .nav__item { position: relative; }

  .nav__link,
  .nav__link--trigger {
    position: relative;
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--text-primary);
    padding: 0 2px;
  }
  /* Hover and open read as a brass underline drawing in, not as a filled
     pill and not as a white box. */
  .nav__link::after,
  .nav__link--trigger::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 6px;
    height: 1.5px;
    background: var(--accent-brass);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .nav__link:hover::after,
  .nav__link:focus-visible::after,
  .nav__link--trigger:hover::after,
  .nav__link--trigger:focus-visible::after,
  .nav__link--trigger[aria-expanded="true"]::after { transform: scaleX(1); }
  .nav__link--trigger[aria-expanded="true"] { color: var(--accent-brass-deep); }
  .nav__caret { border-color: var(--accent-brass-deep); }
  /* The one navy detail in the navigation: the page you are on. */
  .nav__link[aria-current="page"] { color: var(--brand-navy); }
  .nav__link[aria-current="page"]::after { background: var(--brand-navy); transform: scaleX(1); }
}

/* ---- Compact anchored dropdown ---- */
.navdrop {
  position: absolute;
  top: calc(100% + 6px);
  left: -14px;
  z-index: 60;
  min-width: 16rem;
  max-width: min(22rem, 90vw);
  /* Opaque, because it overlays a moving film. Parchment rather than navy:
     a navy panel this size competes with the mark in the same eyeline. */
  background: var(--surface-parchment);
  border: 1px solid var(--border-brass);
  border-radius: 0;
  box-shadow: 0 14px 28px -22px rgba(28, 33, 31, 0.55);
}
.navdrop[hidden] { display: none; }
.navdrop__list { list-style: none; margin: 0; padding: 6px; display: grid; }
.navdrop__link {
  display: grid;
  gap: 1px;
  min-height: 44px;
  align-content: center;
  padding: 9px 14px;
  text-decoration: none;
  color: var(--text-primary);
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.navdrop__link:hover,
.navdrop__link:focus-visible { background: rgba(169, 120, 66, 0.14); }
.navdrop__label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9375rem;
  font-weight: 600;
}
.navdrop__arrow {
  color: var(--accent-brass-deep);
  transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.navdrop__link:hover .navdrop__arrow,
.navdrop__link:focus-visible .navdrop__arrow { transform: translateX(3px); }
.navdrop__note { font-size: 0.8125rem; line-height: 1.45; color: var(--text-secondary); }

/* Opacity and a short lift. No scale, no bounce, no glow, and it is display
   toggled by [hidden] so nothing invisible is left intercepting clicks. */
.navdrop[data-open] { animation: navdrop-in 200ms cubic-bezier(0.4, 0, 0.2, 1) both; }
@keyframes navdrop-in {
  from { opacity: 0; transform: translateY(-7px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .navdrop[data-open] { animation: none; }
  .navdrop__link .navdrop__arrow { transition: none; }
  .nav__link::after,
  .nav__link--trigger::after { transition: none; }
}

/* ---- Header actions: deliberate blocks, not underlined text ---- */
@media (min-width: 64em) {
  .headact { border-radius: 0; }
  .headact--utility {
    color: var(--text-ink);
    background: transparent;
    border: 1px solid var(--border-strong);
  }
  .headact--utility:hover,
  .headact--utility:focus-visible { border-color: var(--accent-brass-deep); background: rgba(169, 120, 66, 0.1); }
  /* The primary action is the one deliberate dark block in the header. It is
     charcoal, not navy: navy here would sit 200px from the mark at a similar
     size and flatten it. */
  .headact--primary {
    color: var(--text-on-dark);
    background: var(--surface-charcoal);
    border: 1px solid var(--surface-charcoal);
  }
  .headact--primary:hover,
  .headact--primary:focus-visible { background: var(--surface-olive-charcoal); border-color: var(--accent-brass); }
}

/* ---- Mobile drawer ---- */
.menu__panel { background: var(--surface-parchment); border-top: 1px solid var(--border-brass); }
.menu__actions { display: grid; gap: var(--s3); margin-top: var(--s4); }
.menu__actions .headact {
  justify-content: center;
  border-radius: 0;
  min-height: 48px;
  padding: 0 var(--s5);
  text-decoration: none;
  font-weight: 600;
}
.menu__actions .headact--utility { color: var(--text-ink); border: 1px solid var(--border-strong); background: transparent; }
.menu__actions .headact--primary { color: var(--text-on-dark); background: var(--surface-charcoal); border: 1px solid var(--surface-charcoal); }
.mnav__item { border-bottom: 1px solid var(--border-subtle); }
.mnav__summary, .mnav__link--top { color: var(--text-primary); }
.mnav__link { color: var(--text-secondary); }
.mnav__link:hover { color: var(--accent-brass-deep); }
.mnav__caret { border-color: var(--accent-brass-deep); }
/* The open drawer holds the page still behind it. Set by nav.mjs, and only
   while it is genuinely open. */
body[data-menu-open] { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }

/* ---- 8. Main footer: the logo on an uninterrupted light surface ---- */
.site-foot {
  background: var(--surface-parchment);
  color: var(--text-primary);
  border-top: 1px solid var(--border-brass);
}
.site-foot__inner { padding-block: clamp(3rem, 5vw, 4.5rem); }
/* No plate, no card, no coloured box behind it — just clear space. */
.site-foot__brand { background: none; border: 0; padding: 0; }
.site-foot__mark {
  height: auto;
  width: clamp(150px, 14vw, 190px);
  margin-bottom: var(--s5);
  filter: none;
  opacity: 1;
  mix-blend-mode: normal;
}
.site-foot__position { color: var(--text-secondary); max-width: 34ch; }
.site-foot__heading {
  color: var(--accent-brass-deep);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.site-foot__link { color: var(--text-primary); }
.site-foot__link:hover, .site-foot__link:focus-visible { color: var(--accent-brass-deep); }
.site-foot__legal { color: var(--text-secondary); }
.site-foot__legal p { color: var(--text-secondary); }
.site-foot__caution { color: var(--text-secondary); border-left: 2px solid var(--accent-brass); padding-left: var(--s3); }
.site-foot__legal .link { color: var(--brand-navy); }
.site-foot__group + .site-foot__group { border-top: 0; }

/* ---- 9. Thin dark legal strip ---- */
.legalstrip {
  background: var(--surface-olive-charcoal);
  border-top: 1px solid var(--border-on-dark);
  padding: var(--s3) var(--inset);
}
.legalstrip__line {
  margin: 0;
  max-width: var(--max);
  margin-inline: auto;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--text-on-dark-soft);
}

/* =========================== HOMEPAGE SURFACES =========================== *
   Scoped, so the approval prototype is the only page that moves.           */

[data-page="home"] { background: var(--surface-page); }

/* ---- 2. Hero: the film is the visual, the frame is neutral ---- */
/* The wings become a warm near-black rather than two heavy blue columns.
   Olive-charcoal reads as neutral against the aerial's own greens without
   ever announcing itself as green. */
[data-page="home"] .stage { background: var(--surface-olive-charcoal); }

@media (min-width: 75em) {
  [data-page="home"] .wing {
    background: linear-gradient(180deg, #212821 0%, var(--surface-olive-charcoal) 100%);
  }
  /* One warm hairline between each wing and the film. No glow, no blur. */
  [data-page="home"] .wing--left {
    border-right: 1px solid var(--border-brass);
    box-shadow: inset -14px 0 20px -20px rgba(0, 0, 0, 0.7);
  }
  [data-page="home"] .wing--right {
    border-left: 1px solid var(--border-brass);
    box-shadow: inset 14px 0 20px -20px rgba(0, 0, 0, 0.7);
  }
}
[data-page="home"] .wing__text { border-top: 1px solid var(--border-brass); }
[data-page="home"] .wing__text p { color: var(--text-on-dark); }
[data-page="home"] .wing__name { color: var(--text-on-dark); }
/* Champagne, not brass, for the small labels: brass does not clear 4.5:1
   against this surface at this size and champagne does. */
[data-page="home"] .wing__source,
[data-page="home"] .wing__index { color: var(--accent-champagne); }
[data-page="home"] .wing__stars { color: var(--accent-champagne); }

/* The eyebrow loses its navy rectangle: champagne type between two fine
   rules, sitting on the film. */
[data-page="home"] .hero--stage .hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--accent-champagne);
  text-shadow: 0 1px 12px rgba(12, 14, 12, 0.9);
}
[data-page="home"] .hero--stage .hero__eyebrow::before,
[data-page="home"] .hero--stage .hero__eyebrow::after {
  content: "";
  display: block;
  width: clamp(1.25rem, 2.5vw, 2.25rem);
  height: 1px;
  background: var(--accent-champagne);
  opacity: 0.7;
}

/* Primary action stays parchment with ink type. */
[data-page="home"] .hero--stage .btn--gold {
  --btn-fill: var(--surface-parchment);
  --btn-fg: var(--text-ink);
  border: 1px solid var(--border-brass);
}
[data-page="home"] .hero--stage .btn--gold::after { background: var(--surface-charcoal); }
[data-page="home"] .hero--stage .btn--gold:hover,
[data-page="home"] .hero--stage .btn--gold:focus-visible { color: var(--text-on-dark); }

/* Secondary loses its navy rectangle for a quiet charcoal wash and a fine
   champagne rule. */
[data-page="home"] .hero__second {
  background: rgba(29, 36, 31, 0.42);
  border: 1px solid rgba(197, 166, 106, 0.6);
  color: var(--text-on-dark);
}
[data-page="home"] .hero__second:hover,
[data-page="home"] .hero__second:focus-visible {
  background: rgba(29, 36, 31, 0.72);
  border-color: var(--accent-champagne);
  color: var(--text-on-dark);
}

/* ---- 3. Route dock: warm limestone, the transition out of the film ---- */
[data-page="home"] .hero--stage .dock,
[data-page="home"] .hero--stage .dock__item {
  background: var(--surface-limestone);
}
[data-page="home"] .hero--stage .dock {
  border-top: 1px solid var(--accent-brass);
  box-shadow: none;
}
[data-page="home"] .hero--stage .dock::before { display: none; }
[data-page="home"] .hero--stage .dock__list {
  background: rgba(41, 38, 32, 0.18);
  gap: 1px;
  max-width: var(--max);
  margin-inline: auto;
}
/* Roughly 12% shorter, and the headings come down with it: refined spacing
   rather than oversized type. */
[data-page="home"] .hero--stage .dock__link {
  min-height: 78px;
  padding: 13px 26px;
  color: var(--text-primary);
  transition: background-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-page="home"] .hero--stage .dock__audience {
  font-size: 0.6875rem;
  letter-spacing: 0.15em;
  font-weight: 700;
  color: var(--accent-brass-deep);
}
[data-page="home"] .hero--stage .dock__action {
  font-size: clamp(1.15rem, 1.05rem + 0.25vw, 1.35rem);
  line-height: 1.15;
  color: var(--text-primary);
}
[data-page="home"] .hero--stage .dock__cue { color: var(--accent-brass-deep); transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1); }
/* A warm tonal shift, not a navy flood. */
[data-page="home"] .hero--stage .dock__link:hover,
[data-page="home"] .hero--stage .dock__link:focus-visible { background: rgba(107, 70, 32, 0.1); }
[data-page="home"] .hero--stage .dock__link:hover .dock__cue,
[data-page="home"] .hero--stage .dock__link:focus-visible .dock__cue { transform: translateX(3px); }
[data-page="home"] .hero--stage .dock__link::after { background: var(--accent-brass-deep); height: 2px; }
[data-page="home"] .hero--stage .dock__link:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: -4px; }
@media (prefers-reduced-motion: reduce) {
  [data-page="home"] .hero--stage .dock__cue { transition: none; }
}

/* ---- 4. Why Dukes: the light paper surface ---- */
[data-page="home"] .band--dossier { background: var(--surface-page); color: var(--text-primary); }

/* ---- 5. Journey gateway: a related limestone tone, no new hue ---- */
[data-page="home"] .band--journeys { background: var(--surface-muted); color: var(--text-primary); }

/* ---- 6. Reviews: paper, not another full-width dark wall ---- */
[data-page="home"] .band--reviews {
  background: var(--surface-page);
  color: var(--text-primary);
  --fg: var(--text-primary);
  --fg-soft: var(--text-secondary);
  --line: var(--border-subtle);
  --rule: var(--border-subtle);
}
[data-page="home"] .band--reviews .h-section,
[data-page="home"] .band--reviews .lede,
[data-page="home"] .band--reviews .chapter__label { color: var(--text-primary); }
[data-page="home"] .band--reviews .chapter__index { color: var(--accent-brass-deep); }
[data-page="home"] .band--reviews .chapter__rule { background: var(--border-subtle); }
/* Cards become a warm ivory variant on paper: separated by tone and a rule,
   not by being dropped onto a coloured slab. */
[data-page="home"] .band--reviews .rcard {
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  color: var(--text-primary);
  box-shadow: none;
}
[data-page="home"] .band--reviews .rcard__quote { color: var(--text-primary); }
[data-page="home"] .band--reviews .rcard__stars { color: var(--accent-brass-deep); }
[data-page="home"] .band--reviews .rcard__name { color: var(--text-primary); }
[data-page="home"] .band--reviews .rcard__src,
[data-page="home"] .band--reviews .rcard__when,
[data-page="home"] .band--reviews .rcard__host,
[data-page="home"] .band--reviews .rcard__verify { color: var(--text-secondary); }
[data-page="home"] .band--reviews .rcard__initials {
  background: var(--surface-limestone);
  color: var(--text-ink);
  border: 1px solid var(--border-subtle);
}
[data-page="home"] .band--reviews .rcard__link { color: var(--brand-navy); }
[data-page="home"] .band--reviews .rwall__eyebrow { color: var(--accent-brass-deep); }
[data-page="home"] .band--reviews .rwall__title { color: var(--text-primary); }
[data-page="home"] .band--reviews .rwall__links .link { color: var(--brand-navy); }
[data-page="home"] .band--reviews .ctrl,
[data-page="home"] .band--reviews .rwall__toggle {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
}
[data-page="home"] .band--reviews .rwall__toggle:hover,
[data-page="home"] .band--reviews .rwall__toggle:focus-visible { border-color: var(--accent-brass-deep); background: rgba(169, 120, 66, 0.1); }
/* One small dark panel is allowed, for the aggregate that has to carry
   authority. It is the only dark surface in the light run. */
[data-page="home"] .band--reviews .score {
  background: var(--surface-olive-charcoal);
  color: var(--text-on-dark);
  border: 0;
  padding: var(--s5);
}
[data-page="home"] .band--reviews .score__value { color: var(--text-on-dark); }
[data-page="home"] .band--reviews .score__stars { color: var(--accent-champagne); }
[data-page="home"] .band--reviews .score__count,
[data-page="home"] .band--reviews .score__captured { color: var(--text-on-dark-soft); }

/* ---- 7. Contact and receptionist: the single deliberate dark anchor ---- */
[data-page="home"] .band--contact,
[data-page="home"] .reception {
  background: var(--surface-olive-charcoal);
  color: var(--text-on-dark);
  --fg: var(--text-on-dark);
  --fg-soft: var(--text-on-dark-soft);
  --line: var(--border-on-dark);
  --rule: var(--border-on-dark);
  --focus-ring: var(--text-on-dark);
}
[data-page="home"] .band--contact { padding-bottom: 0; }
[data-page="home"] .reception { padding-top: clamp(2rem, 4vw, 3.5rem); }
[data-page="home"] .band--contact .h-section,
[data-page="home"] .band--contact .lede,
[data-page="home"] .band--contact .chapter__label,
[data-page="home"] .reception .h-section { color: var(--text-on-dark); }
[data-page="home"] .band--contact .chapter__index,
[data-page="home"] .reception__eyebrow { color: var(--accent-champagne); }
[data-page="home"] .band--contact .chapter__rule { background: var(--border-on-dark); }
/* The two closing choices separate by tone and rule, not by two more hues. */
[data-page="home"] .action-panel {
  background: rgba(244, 238, 227, 0.06);
  border: 1px solid var(--border-on-dark);
  color: var(--text-on-dark);
}
[data-page="home"] .action-panel--lead { background: rgba(49, 83, 69, 0.34); border-color: rgba(197, 166, 106, 0.42); }
[data-page="home"] .action-panel__title { color: var(--text-on-dark); }
[data-page="home"] .action-panel__body { color: var(--text-on-dark-soft); }
[data-page="home"] .action-panel__index { color: var(--accent-champagne); }
/* Green earns its place here as the primary action, and only here. */
[data-page="home"] .band--contact .btn--gold {
  --btn-fill: var(--accent-bottle-green);
  --btn-fg: var(--text-on-dark);
  border: 1px solid rgba(197, 166, 106, 0.55);
}
[data-page="home"] .band--contact .btn--outline {
  --btn-fill: transparent;
  --btn-fg: var(--text-on-dark);
  border: 1px solid var(--border-on-dark);
}
[data-page="home"] .reception__notice,
[data-page="home"] .reception__demo { color: var(--text-on-dark-soft); }
[data-page="home"] .reception__summary { color: var(--text-on-dark); }
[data-page="home"] .reception__index { color: var(--accent-champagne); }
[data-page="home"] .reception__route { border-color: var(--border-on-dark); }
/* Warm ivory inputs rather than stark white rectangles. */
[data-page="home"] .reception .form__control,
[data-page="home"] .band--contact .form__control {
  background: var(--surface-ivory);
  color: var(--text-ink);
  border: 1px solid var(--border-brass);
}

/* ---- Focus, on every surface ---- */
[data-page="home"] .band--contact :focus-visible,
[data-page="home"] .reception :focus-visible,
.legalstrip :focus-visible { outline: 2px solid var(--accent-champagne); outline-offset: 2px; }

/* ---- The chapter rule, brought onto the system ---- *
   This component predates the palette and was still reading the old --copper
   and --ink-soft values. Against the new paper and limestone surfaces those
   land at 3.65:1, 4.17:1 and 3.81:1 — axe caught all three. The numbered
   plate and its label are small text, so they take the deep brass and the ink
   rather than the decorative brass.                                          */
[data-page="home"] .chapter__index { color: var(--accent-brass-deep); }
[data-page="home"] .chapter__label { color: var(--text-primary); }
[data-page="home"] .chapter__rule { background: var(--border-subtle); }

/* The dark anchor keeps champagne, which clears 7:1 there. */
[data-page="home"] .band--contact .chapter__index,
[data-page="home"] .reception .chapter__index { color: var(--accent-champagne); }
[data-page="home"] .band--contact .chapter__label { color: var(--text-on-dark); }
[data-page="home"] .band--contact .chapter__rule { background: var(--border-on-dark); }

/* ========================================================================== *
 *  COLOUR SYSTEM — promoted site-wide
 *
 *  The homepage was the approval prototype and it is approved, so the system
 *  now applies to all sixteen pages.
 *
 *  This is done by redefining the three earlier generations of primitive in
 *  terms of the approved semantic tokens, rather than by restyling ~177 call
 *  sites one at a time. Every component that already reads --bone, --bottle,
 *  --copper or --sand keeps working untouched and simply renders in the new
 *  palette, which is what keeps the secondary pages consistent with the
 *  homepage instead of drifting into a second dialect of it.
 *
 *  The relative roles are preserved exactly — page surface stays lighter than
 *  raised, raised stays lighter than sunk, and the deep surface stays deeper
 *  than the mid one — so existing light/dark rhythm decisions still read the
 *  way their authors intended.
 * ========================================================================== */

:root {
  /* One new primitive: the deepest surface, for footers and the base of a
     dark chapter. Everything else is already declared above. */
  --surface-dark-deep: #141813;

  /* ---- Warm neutrals replace the bone family ---- */
  --bone: var(--surface-paper);
  --bone-raised: var(--surface-ivory);
  --bone-sunk: var(--surface-limestone);

  /* ---- Bottle green stops being the default dark ----
     Green is no longer a surface. It survives as an action colour and as a
     small landlord-side cue, which is where it means something. */
  --bottle: var(--surface-olive-charcoal);
  --bottle-deep: var(--surface-dark-deep);
  --forest-shade: var(--surface-dark-deep);

  /* ---- Ink ---- */
  --ink: var(--text-ink);
  --ink-soft: var(--text-muted);
  --on-deep: var(--text-on-dark-warm);
  --on-deep-soft: var(--text-on-dark-soft);

  /* ---- Metals ----
     --copper carried small labels all over the site, so it takes the
     text-safe deep brass rather than the decorative one. --sand sat on dark
     surfaces, where champagne clears 7:1. */
  --copper: var(--accent-brass-deep);
  --copper-deep: #573716;
  --sand: var(--accent-champagne);

  /* ---- Lines ---- */
  --rule: var(--border-subtle);
  --rule-strong: var(--border-strong);
  --rule-on-deep: var(--border-on-dark);

  /* Crest red stays exactly what it was: a micro-accent, never a surface. */
}

/* Page surface for every page, not just the approved one. */
body { background: var(--surface-page); color: var(--text-primary); }

/* ---- Actions ----
   The primary control is where bottle green earns its keep. Everything else
   that used to be a green block is now a neutral surface, so the one green
   thing on a page is the thing you are meant to press. */
.btn--primary {
  --btn-fill: var(--accent-bottle-green);
  --btn-fg: var(--text-on-dark-warm);
}
.btn--primary:hover,
.btn--primary:focus-visible { --btn-fill: #274539; }

/* Two hardcoded bottle-deep values predate the token system and would have
   stayed green on the search hero. */
.hero--search .btn--primary {
  --btn-fill: var(--accent-champagne);
  --btn-fg: var(--text-ink);
  border-color: var(--accent-champagne);
  color: var(--text-ink);
}

/* ---- Dark chapters on secondary pages ----
   Same warm near-black as the homepage's contact anchor, so a dark band on
   /landlords/ and a dark band on / are recognisably the same material. */
.band--dark { background: var(--surface-dark); color: var(--text-on-dark-warm); }
.band--dark .chapter__index { color: var(--accent-champagne); }
.band--dark .chapter__label { color: var(--text-on-dark-warm); }
.band--dark .chapter__rule { background: var(--border-on-dark); }

/* Service and search heroes take the light surface: they open a page, they do
   not need to announce themselves with a colour. */
.hero--service { background: var(--surface-page); }
.hero--search { background: var(--surface-dark); color: var(--text-on-dark-warm); }

/* Forms: warm ivory fields, never stark white rectangles. */
.form__control,
.search__control { background: var(--surface-ivory); color: var(--text-ink); border-color: var(--border-strong); }
.form__control:hover,
.form__control:focus-visible { border-color: var(--accent-brass-deep); }

/* Tables and comparison areas group with tone, not with another hue. */
.package-grid > *,
.facts__row,
.evidence__list > * { background: var(--surface-raised); border-color: var(--border-subtle); }

/* ---- Secondary-text colours that the promotion exposed ---- *
   The site-wide pass moved several surfaces darker or lighter than the colours
   sitting on them expected. These are the pairs axe found once every page was
   measured rather than just the homepage.                                    */

/* Muted ink is a light-surface colour. Anywhere it landed on a dark panel it
   was reading at 2.7:1, so those places take the on-dark tone instead. */
/* Scoped: .stage__step also appears on the valuation form, which is on a light
   surface. An unscoped on-dark colour there was light type on light paper. */
.band--dark .mount__meta,
.band--dark .mount__summary,
.band--dark .stage__step,
.hero--search .stage__step { color: var(--text-on-dark-soft); }
/* Small uppercase step counter. Deep brass rather than muted ink: it is a
   wayfinding label, and at 12px it needs the headroom. */
.stage__step { color: var(--accent-brass-deep); opacity: 1; }
.stage__title { color: var(--text-primary); }

/* The media mount plates are internal art-direction furniture, but they are
   still rendered text and still have to be legible. They were using faded
   greys on near-white. */
.mount__title { color: var(--text-primary); }
.mount__id,
.mount__meta,
.mount__summary,
.mount__replace { color: var(--text-muted); }
.mount__flag { color: var(--accent-brass-deep); }
.mount__banner { background: var(--surface-ivory); border: 1px solid var(--border-subtle); }

/* The mount's storyboard scene is a mid-grey panel; dark text on it was
   reading at 2.4:1. Light type on the scene, dark type on the plate. */
.mount__scene { background: var(--surface-mushroom); }
.mount__scene .mount__flag,
.mount__scene .mount__title,
.mount__scene .mount__id { color: var(--text-ink); }

/* The review rail's peek column is a preview of the next card, deliberately
   quiet — but quiet has a floor. */
.review__peek-quote,
.review__peek-initials { color: var(--text-muted); }

/* ---- Two permanent fades that were doing the job twice ---- */

/* The review rail's peek column already fades out under a gradient mask. The
   0.5 opacity on top of that was belt-and-braces, and it pushed the preview
   text to 2.3:1 — a resting state, not a transient one. The mask alone gives
   the same read at full contrast. */
.review__peek { opacity: 1; }

/* The valuation form dims the steps you are not on. Dimming a heading to the
   point it cannot be read is not the same as disabling a control, and these
   fieldsets are not disabled — they are the map of where the form is going. */
fieldset.stage { opacity: 1; filter: none; }

/* ---- The valuation form's fieldsets ---- *
   `.stage` is used twice in this codebase: the hero film container and each
   step of the valuation form. Two unscoped `.stage` rules written for the hero
   were painting the form's fieldsets near-black and absolutely positioning
   them, which is why a brass step label was sitting on a dark panel. The form
   takes a raised light surface, like every other form panel in the system.  */
fieldset.stage {
  position: static;
  inset: auto;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  color: var(--text-primary);
}
fieldset.stage .stage__title { color: var(--text-primary); }
fieldset.stage .stage__step { color: var(--accent-brass-deep); }

/* ---- The route dock on a phone ---- *
   Three routes in a two-column grid left a dead cell in the bottom right. The
   third route takes the full width instead: two decisions side by side, one
   beneath, and no empty box.                                                */
@media (max-width: 47.99em) {
  .hero--stage .dock__item:last-child { grid-column: 1 / -1; }
}

/* ---- The launcher wears the crown ---- */
.launcher__glyph {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
}
.launcher__crown {
  width: 100%;
  height: auto;
  /* The artwork is used as supplied: no filter, no recolour, no monochrome. */
  filter: none;
}


/* ====================== Receptionist showcase (04) ======================= *
   The assistant presented as part of the offer. Paper surface, because the
   chapter above it is paper too and there is no functional reason to change
   material — spacing and a rule do the separating.                          */
[data-page="home"] .band--showcase { background: var(--surface-page); }

.showcase { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); align-items: center; }
@media (min-width: 64em) {
  .showcase { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
}
.showcase__copy .lede { margin-top: var(--s4); max-width: 52ch; }
.showcase__points { list-style: none; margin: var(--s7) 0 0; padding: 0; display: grid; gap: 0; }
.showcase__point { padding: var(--s5) 0; border-top: 1px solid var(--border-subtle); }
.showcase__point:last-child { border-bottom: 1px solid var(--border-subtle); }
.showcase__point-title {
  margin: 0 0 6px;
  font-family: var(--font-text);
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-primary);
}
.showcase__point-body { margin: 0; font-size: 0.9375rem; line-height: 1.6; color: var(--text-secondary); max-width: 50ch; }
.showcase__actions { margin: var(--s7) 0 0; }

/* ---- The preview panel ---- */
.rprev {
  border: 1px solid var(--border-subtle);
  background: var(--surface-raised);
  box-shadow: 0 26px 50px -40px rgba(28, 33, 31, 0.55);
  overflow: hidden;
  max-width: 26rem;
  margin-inline: auto;
}
.rprev__head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  background: var(--surface-olive-charcoal);
}
.rprev__crown { width: 40px; height: auto; flex: none; }
.rprev__id { display: grid; gap: 1px; }
.rprev__name { font-family: var(--font-display); font-size: 1.0625rem; color: var(--text-on-dark); }
.rprev__role { font-size: 0.75rem; letter-spacing: 0.08em; color: var(--accent-champagne); }
.rprev__body { padding: var(--s5); display: grid; gap: var(--s4); }
.rprev__bubble {
  margin: 0;
  padding: var(--s4);
  background: var(--surface-ivory);
  border: 1px solid var(--border-subtle);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text-primary);
}
.rprev__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.rprev__chip {
  padding: 9px 14px;
  border: 1px solid var(--border-strong);
  background: var(--surface-page);
  font-size: 0.8125rem;
  color: var(--text-primary);
}
.rprev__foot {
  margin: 0;
  padding: var(--s3) var(--s5) var(--s4);
  font-size: 0.75rem;
  color: var(--text-secondary);
  border-top: 1px solid var(--border-subtle);
}

/* One composed arrival, not three competing ones: the panel settles, then the
   bubble, then the chips. Nothing loops. */
[data-enhanced][data-motion="full"] .band--showcase .rprev { opacity: 0; transform: translateY(18px); }
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev {
  opacity: 1;
  transform: none;
  transition: opacity 640ms cubic-bezier(0.4, 0, 0.2, 1), transform 640ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-enhanced][data-motion="full"] .band--showcase .rprev__bubble,
[data-enhanced][data-motion="full"] .band--showcase .rprev__chip { opacity: 0; transform: translateY(8px); }
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__bubble,
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__chip {
  opacity: 1;
  transform: none;
  transition: opacity 420ms cubic-bezier(0.4, 0, 0.2, 1), transform 420ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__bubble { transition-delay: 260ms; }
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__chip:nth-child(1) { transition-delay: 420ms; }
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__chip:nth-child(2) { transition-delay: 500ms; }
[data-enhanced][data-motion="full"] .band--showcase.is-in .rprev__chip:nth-child(3) { transition-delay: 580ms; }

[data-motion="static"] .rprev,
[data-motion="static"] .rprev__bubble,
[data-motion="static"] .rprev__chip {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

[data-page="home"] .band--creds { background: var(--surface-muted); }

/* ---- Narrow-width guards for the two new chapters ---- *
   Grid and flex children default to min-width:auto, so they refuse to shrink
   below their content and push the whole page wider than the viewport. At
   320px that was 215px of horizontal overflow.                              */
.showcase > *,
.showcase__copy,
.showcase__preview { min-width: 0; }
.rprev { max-width: min(26rem, 100%); }
.rprev__chips { min-width: 0; }
.rprev__chip { max-width: 100%; }
.creds__wordmark { overflow-wrap: anywhere; }


/* ---- The review wall must not push the page wider than the phone ---- *
   Its track is a deliberately over-wide strip of cloned cards. The window
   around it was not clipping horizontally at the narrowest widths, so a card
   sitting past the right edge dragged the document's scroll width out with it
   (215px of overflow at 320px, 164px at 375px).
   `clip`, never `hidden`: hidden would make this a scroll container and break
   the sticky header above it.                                               */
.rwall,
.rwall__window,
.rwall__wall { overflow-x: clip; }

/* The band is the boundary that matters: nothing inside the review chapter may
   extend the document. `clip` keeps it from becoming a scroll container. */
.band--reviews { overflow-x: clip; }

/* A chapter label is a short tag, not a sentence. This keeps an over-long one
   from refusing to wrap and dragging the document wider than the viewport,
   which a 53-character label did at 320px. */
.chapter__label { white-space: normal; overflow-wrap: anywhere; min-width: 0; }
.chapter { flex-wrap: wrap; }

/* The Why Dukes image is landscape now, so its frame is too. Forcing a 16:9
   architectural view into a 4:5 portrait crop would have thrown away the
   station frontage, which is the only reason to use the picture. */
.welcome__photo--wide { aspect-ratio: 16 / 9; }
@media (min-width: 64em) {
  .welcome__photo--wide { aspect-ratio: 4 / 3; }
}


/* ============================ The launcher ============================== *
   It was a near-black disc with a champagne ring and a shimmer sweep across
   it. Three problems: the crown carries navy, gold and red linework and goes
   muddy on a dark disc (the same logo-safe rule the header and footer already
   follow — the crown is part of the mark, so it is covered by it); a ring plus
   a wide dark halo reads as a glow rather than as a control; and a shimmer
   that sweeps across a brand mark is exactly the detail that makes premium
   look cheap.

   It is now the same warm parchment as the header, with one brass hairline and
   a tight contact shadow. The crown sits on light, where it was designed to.  */

.launcher {
  background: var(--surface-parchment);
  color: var(--text-ink);
  border: 1px solid var(--border-brass);
  /* A contact shadow, not a halo: short offset, tight blur, low alpha. */
  box-shadow: 0 6px 18px -8px rgba(28, 33, 31, 0.45);
  overflow: visible;
  transition:
    background-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 220ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.launcher:hover,
.launcher:focus-visible {
  background: var(--surface-ivory);
  border-color: var(--accent-brass);
  box-shadow: 0 10px 24px -10px rgba(28, 33, 31, 0.5);
}
.launcher:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 3px; }
.launcher:active { transform: translateY(1px); }

/* The shimmer goes entirely. */
.launcher__glint { display: none !important; }

.launcher__text { color: var(--text-ink); font-weight: 700; }
.launcher__sub { color: var(--text-secondary); }

/* The disc below the desktop breakpoint. */
@media (max-width: 63.99em) {
  [data-enhanced] .launcher {
    border-color: var(--border-brass);
    background: var(--surface-parchment);
  }
  [data-enhanced] .launcher .launcher__glyph { color: inherit; }
}

/* The crown is given room to breathe rather than filling the disc edge to
   edge, which is what made it read as a sticker. */
.launcher__glyph { width: 30px; height: 30px; }
.launcher__crown { width: 100%; height: auto; display: block; }

@media (prefers-reduced-motion: reduce) {
  .launcher { transition: none; }
  .launcher:active { transform: none; }
}

/* At desktop the crown sits beside the label rather than stacked above it, so
   the whole thing reads as one control instead of a small card with a mark
   dropped in the corner. */
@media (min-width: 64em) {
  [data-enhanced] .launcher {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--s3);
    padding: 14px var(--s5) 14px var(--s4);
  }
  [data-enhanced] .launcher .launcher__glyph { display: grid; width: 34px; height: 34px; }
}


/* ===================== Credentials rail, as a marquee =================== *
   Driven entirely by a CSS animation rather than a JavaScript loop, and that
   is the load-bearing decision. A rAF loop has to be told to stop when the tab
   is hidden and told to start again when the reader comes back, which is
   exactly the case that gets missed: leave the page, return, and the rail is
   dead. A CSS animation is suspended and resumed by the browser itself, so
   returning to the tab, restoring from the back-forward cache, or coming back
   from another app all continue from where it stopped, with no code.

   Pause on hover and on keyboard focus is then one declaration, and it pauses
   in place rather than snapping.                                            */

.creds { position: relative; }

.creds__viewport {
  overflow: hidden;
  /* The rail fades out at both edges instead of being guillotined by the
     section, so items enter and leave rather than appearing and vanishing. */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.creds__track {
  list-style: none;
  margin: 0;
  padding: var(--s2) 0;
  display: flex;
  width: max-content;
  gap: var(--s4);
  animation: creds-roll 56s linear infinite;
  /* Promoted once, so the loop does not repaint the whole band every frame. */
  will-change: transform;
}

@keyframes creds-roll {
  from { transform: translate3d(0, 0, 0); }
  /* Exactly half: the second copy of the list lands where the first began. */
  to { transform: translate3d(-50%, 0, 0); }
}

/* Pause in place. `:focus-within` covers the keyboard, not just the pointer. */
.creds:hover .creds__track,
.creds:focus-within .creds__track { animation-play-state: paused; }

.creds__item { flex: 0 0 auto; }

.creds__card {
  display: grid;
  gap: var(--s3);
  align-content: center;
  justify-items: center;
  width: 208px;
  min-height: 124px;
  padding: var(--s4) var(--s5);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 0;
  text-align: center;
  color: var(--text-primary);
  transition:
    border-color 260ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* The whole rail slows and the card under the pointer lifts its keyline. No
   scale, no shadow bloom: the rail is already the moving thing on screen. */
.creds__item:hover .creds__card {
  border-color: var(--accent-brass);
  box-shadow: 0 10px 24px -18px rgba(28, 33, 31, 0.5);
}

.creds__mark { display: grid; place-items: center; min-height: 44px; width: 100%; }
.creds__logo { max-width: 100%; max-height: 44px; width: auto; height: auto; }

/* Until each approved brand file arrives, a wordmark set in the site's own
   display face. Never an imitation of somebody else's mark. */
.creds__wordmark {
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--text-primary);
}

.creds__kind {
  font-size: 0.6563rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-brass-deep);
}

/* Reduced motion: the rail stops being a rail. Every item is present and
   readable in a static wrapped grid rather than being hidden off-track. */
@media (prefers-reduced-motion: reduce) {
  .creds__viewport { overflow: visible; mask-image: none; -webkit-mask-image: none; }
  .creds__track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
  }
  .creds__item[aria-hidden="true"] { display: none; }
  .creds__item:hover .creds__card { box-shadow: none; }
}
[data-motion="static"] .creds__viewport { overflow: visible; mask-image: none; -webkit-mask-image: none; }
[data-motion="static"] .creds__track { animation: none; width: auto; flex-wrap: wrap; justify-content: center; }
[data-motion="static"] .creds__item[aria-hidden="true"] { display: none; }


/* ---- Credentials rail: review fixes ---- */

/* Optical scale per record. Normalising by bounding box alone leaves a wide
   wordmark tiny beside a near-square mark. */
.creds__logo { max-height: calc(40px * var(--logo-scale, 1)); max-width: 100%; width: auto; }

/* Every plate identical regardless of whether its label wraps. One record's
   two-line label was shifting its whole content block up by 9px, which on a
   moving rail reads as a wobble. */
.creds__card { grid-template-rows: 44px auto; align-content: start; }
.creds__kind { align-self: start; }

/* The fade has to be at least a card wide or plates are guillotined rather
   than dissolving. 6% was 21px against a 208px card at 390. */
.creds__viewport {
  mask-image: linear-gradient(90deg, transparent 0, #000 200px, #000 calc(100% - 200px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 200px, #000 calc(100% - 200px), transparent 100%);
}

/* Below the tablet breakpoint the rail stops rolling and becomes the static
   wrapped grid that already exists for reduced motion. A 208px card inside a
   350px viewport can never show a whole plate, so on a phone the marquee was
   guaranteed to display two half-cut cards and nothing else. */
@media (max-width: 47.99em) {
  .creds__viewport { overflow: visible; mask-image: none; -webkit-mask-image: none; }
  .creds__track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--s3);
  }
  .creds__item[aria-hidden="true"] { display: none; }
  .creds__card { width: 100%; min-height: 108px; }
  .creds__item { flex: 1 1 150px; max-width: 220px; }
}


/* ====================== The receptionist conversation =================== *
   A transcript, not a form. Assistant on the left in ivory, the reader on the
   right in olive-charcoal, chips and a single input along the bottom.        */

.chat {
  width: min(30rem, calc(100vw - 2rem));
  max-height: min(84vh, 44rem);
  margin: auto;
  padding: 0;
  border: 1px solid var(--border-brass);
  border-radius: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  overflow: hidden;
  box-shadow: 0 30px 60px -40px rgba(20, 24, 19, 0.8);
}
.chat::backdrop { background: rgba(20, 24, 19, 0.62); }
/* Flex, not grid with positional tracks. The progress bar is conditional, so a
   fixed list of rows shifted every child up one whenever it was absent and the
   closing note landed on top of the answer buttons, swallowing their clicks. */
.chat[open] { display: flex; flex-direction: column; }
.chat > * { flex: none; }
.chat__log { flex: 1 1 auto; min-height: 0; }

/* ---- Head ---- */
.chat__head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  background: var(--surface-olive-charcoal);
}
.chat__crown { width: 38px; height: auto; flex: none; }
.chat__id { display: grid; gap: 1px; margin-right: auto; }
.chat__title { margin: 0; font-family: var(--font-display); font-size: 1.0625rem; color: var(--text-on-dark); }
.chat__role { margin: 0; font-size: 0.75rem; letter-spacing: 0.08em; color: var(--accent-champagne); }
.chat__close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  padding: 0;
  background: none;
  border: 0;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--text-on-dark);
  cursor: pointer;
}
.chat__close:hover { color: var(--accent-champagne); }
.chat__close:focus-visible { outline: 2px solid var(--accent-champagne); outline-offset: -4px; }

/* ---- Demo banner. This build collects nothing, and says so up front. ---- */
.chat__banner {
  margin: 0;
  padding: 9px var(--s5);
  background: var(--accent-brass-deep);
  color: var(--surface-ivory);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.chat__progress {
  margin: 0;
  padding: 7px var(--s5);
  background: var(--surface-parchment);
  border-bottom: 1px solid var(--border-subtle);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-brass-deep);
}

/* ---- Transcript ---- */
.chat__log {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--s5);
  display: grid;
  gap: var(--s3);
  align-content: start;
}
.chat__row { display: flex; }
.chat__row--in { justify-content: flex-start; }
.chat__row--out { justify-content: flex-end; }

.chat__bubble {
  margin: 0;
  max-width: 84%;
  padding: 11px 14px;
  background: var(--surface-ivory);
  border: 1px solid var(--border-subtle);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--text-primary);
}
.chat__bubble--me {
  background: var(--surface-olive-charcoal);
  border-color: var(--surface-olive-charcoal);
  color: var(--text-on-dark);
}
/* Safety and closing notices: brass keyline, never a red error box. */
.chat__bubble--safety {
  background: var(--surface-parchment);
  border-left: 3px solid var(--accent-brass);
}
.chat__bubble--retry { border-left: 3px solid var(--crest); }

.chat__summary {
  margin: 0;
  max-width: 84%;
  padding: var(--s4);
  background: var(--surface-ivory);
  border: 1px solid var(--border-subtle);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px var(--s3);
  font-size: 0.875rem;
}
.chat__summary-key { margin: 0; color: var(--accent-brass-deep); font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; align-self: center; }
.chat__summary-value { margin: 0; color: var(--text-primary); overflow-wrap: anywhere; }

/* ---- Answer area ---- */
.chat__foot {
  padding: var(--s4) var(--s5);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-parchment);
  display: grid;
  gap: var(--s3);
}
.chat__chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chat__chip {
  min-height: 44px;
  padding: 10px 15px;
  background: var(--surface-ivory);
  border: 1px solid var(--border-strong);
  border-radius: 0;
  font: inherit;
  font-size: 0.875rem;
  color: var(--text-primary);
  cursor: pointer;
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1), border-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.chat__chip:hover { background: var(--surface-page); border-color: var(--accent-brass-deep); }
.chat__chip:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 2px; }

.chat__form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s2); }
.chat__input {
  min-height: 48px;
  padding: 12px 14px;
  background: var(--surface-ivory);
  border: 1px solid var(--border-strong);
  border-radius: 0;
  font: inherit;
  font-size: 1rem;
  color: var(--text-primary);
  resize: vertical;
}
.chat__input:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: -1px; border-color: var(--accent-brass-deep); }
.chat__send {
  width: 48px;
  min-height: 48px;
  display: grid;
  place-items: center;
  background: var(--accent-bottle-green);
  border: 1px solid var(--accent-bottle-green);
  border-radius: 0;
  font-size: 1.15rem;
  color: var(--text-on-dark);
  cursor: pointer;
}
.chat__send:hover { background: #274539; }
.chat__send:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 2px; }

.chat__back {
  justify-self: start;
  min-height: 44px;
  padding: 0 2px;
  background: none;
  border: 0;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.chat__back:hover { color: var(--accent-brass-deep); }

.chat__actions { display: flex; flex-wrap: wrap; gap: var(--s3); }
.chat__again,
.chat__done {
  min-height: 46px;
  padding: 0 var(--s5);
  border-radius: 0;
  font: inherit;
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
}
.chat__again { background: transparent; border: 1px solid var(--border-strong); color: var(--text-primary); }
.chat__again:hover { border-color: var(--accent-brass-deep); }
.chat__done { background: var(--accent-bottle-green); border: 1px solid var(--accent-bottle-green); color: var(--text-on-dark); }
.chat__done:hover { background: #274539; }

.chat__note {
  margin: 0;
  padding: 10px var(--s5) var(--s4);
  background: var(--surface-parchment);
  font-size: 0.75rem;
  color: var(--text-secondary);
}

/* A phone gets the full height: a conversation is the task, not an overlay. */
@media (max-width: 47.99em) {
  .chat {
    width: 100vw;
    max-width: 100vw;
    max-height: 100dvh;
    height: 100dvh;
    margin: 0;
    border: 0;
  }
  .chat__bubble { max-width: 88%; }
}

@media (prefers-reduced-motion: reduce) {
  .chat__chip,
  .chat__input { transition: none; }
}


/* ---- Bigger plates: the marks were unreadable at 208px ---- *
   A 208px card with a 40px logo box left OnTheMarket about 24px tall. The
   plate now gives each mark a 200x72 field, and the mark is constrained on
   both axes so a wide wordmark and a near-square badge read at the same
   optical weight rather than the same bounding box.                        */
.creds__card { width: 300px; min-height: 150px; padding: var(--s5) var(--s5); gap: var(--s4); }
.creds__mark { min-height: 72px; }
.creds__logo {
  max-height: calc(60px * var(--logo-scale, 1));
  max-width: calc(200px * var(--logo-scale, 1));
  width: auto;
  height: auto;
}
.creds__viewport {
  mask-image: linear-gradient(90deg, transparent 0, #000 290px, #000 calc(100% - 290px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 290px, #000 calc(100% - 290px), transparent 100%);
}
@media (max-width: 47.99em) {
  .creds__card { width: 100%; min-height: 120px; padding: var(--s4); }
  .creds__item { flex: 1 1 160px; max-width: 240px; }
  .creds__mark { min-height: 56px; }
  .creds__logo { max-height: calc(46px * var(--logo-scale, 1)); max-width: calc(150px * var(--logo-scale, 1)); }
}

/* ---- Typing indicator ---- */
.chat__typing { display: inline-flex; gap: 5px; align-items: center; padding: 15px 16px; }
.chat__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-brass-deep);
  opacity: 0.35;
  animation: chat-dot 1.15s ease-in-out infinite;
}
.chat__dot:nth-child(2) { animation-delay: 0.16s; }
.chat__dot:nth-child(3) { animation-delay: 0.32s; }
@keyframes chat-dot {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .chat__dot { animation: none; opacity: 0.6; }
}

/* ---- Logos supplied on a white field ---- *
   Rightmove and OnTheMarket arrived as flattened files with a white
   background, which showed as a bright rectangle sitting inside the ivory
   plate. `multiply` drops white to transparent against the plate while leaving
   every brand colour exactly as supplied — no desaturation, no recolouring,
   which both companies' guidelines require.                                 */
.creds__logo { mix-blend-mode: multiply; }

/* ================= Credentials rail: legibility fixes ================== *
   Three faults, all visible on a phone at once.

   1. The edge fade was eating the rail. A 290px mask against a 350px mobile
      viewport meant no plate ever reached full opacity — the whole band looked
      like a failed image load. It is now a short, honest fade, and it is off
      entirely below the tablet breakpoint where there is no room for it.
   2. The mark row was 44px while the mark box was 72px, so every logo taller
      than 44px overprinted its own label. On PRS and ICO, which carry their own
      sub-wordmarks, two lines of text printed straight through each other.
   3. No hover response.                                                     */

.creds__viewport {
  mask-image: linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
}

/* The mark row matches the mark box, so nothing can print over the label. */
.creds__card { grid-template-rows: 72px auto; }

/* A small lift, on pointer and on touch. The rail is already pausing under the
   pointer, so the plate has room to answer. */
.creds__card { will-change: transform; }
.creds__item:hover .creds__card,
.creds__item:focus-within .creds__card {
  transform: translateY(-4px);
  border-color: var(--accent-brass);
  box-shadow: 0 14px 26px -20px rgba(28, 33, 31, 0.55);
}

@media (max-width: 47.99em) {
  /* No fade at all: at this width it only ever hid content. */
  .creds__viewport { mask-image: none !important; -webkit-mask-image: none !important; }
  .creds__card { grid-template-rows: 56px auto; }
  /* Two even columns rather than a flex wrap that produced ragged rows. */
  .creds__track { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
  .creds__item { flex: none; max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .creds__item:hover .creds__card,
  .creds__item:focus-within .creds__card { transform: none; }
}

/* The answer panel keeps its height while the receptionist is thinking, so the
   dialog does not deflate and re-inflate on every step. */
.chat__foot { min-height: 76px; align-content: center; }

/* ============== Credentials rail: rolling on every width =============== *
   The static mobile grid read as generic, and losing the motion lost the one
   thing that said "these are partners" rather than "here is a table". The rail
   rolls at every width now, with a short fade at each edge — enough to soften
   the entry and exit, nowhere near enough to grey out the plates.          */
@media (max-width: 47.99em) {
  .creds__viewport {
    overflow: hidden;
    mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%) !important;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%) !important;
  }
  .creds__track {
    display: flex;
    flex-wrap: nowrap;
    width: max-content;
    animation: creds-roll 46s linear infinite;
    gap: var(--s3);
    justify-content: flex-start;
  }
  .creds__item { flex: 0 0 auto; max-width: none; }
  .creds__item[aria-hidden="true"] { display: block; }
  .creds__card { width: 230px; min-height: 128px; }
}

/* Reduced motion keeps the grid, and the odd ninth plate centres on its own
   row rather than sitting alone against the left edge. */
@media (prefers-reduced-motion: reduce) {
  .creds__track { display: flex; flex-wrap: wrap; justify-content: center; width: auto; animation: none; }
  .creds__item[aria-hidden="true"] { display: none; }
}


/* ============ Credentials rail: discrete row-by-row carousel ============ *
   Everything below supersedes the marquee rules earlier in this file.

   Default state, which is also the no-JavaScript and reduced-motion state: a
   wrapped, centred list with every plate visible. The odd ninth plate centres
   on its own row rather than sitting alone against the left edge.

   `[data-creds-rolling]` is set by creds-rail.mjs once it is actually running,
   and only then does this become a single-row carousel.                     */

.creds__viewport { overflow: visible; mask-image: none; -webkit-mask-image: none; }

.creds__track {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  width: auto;
  gap: var(--s4);
  animation: none;
  list-style: none;
  margin: 0;
  padding: 0;
  transform: none;
}

.creds__item { flex: 0 0 auto; max-width: none; }

/* ---- Rolling ---- */
.creds[data-creds-rolling] .creds__viewport {
  overflow: hidden;
  /* Just enough to soften the entry and the exit. The plates stay legible all
     the way across; an earlier 290px fade greyed out most of the rail. */
  mask-image: linear-gradient(90deg, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
}
.creds[data-creds-rolling] .creds__track {
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  will-change: transform;
}

/* ---- The plate ---- */
.creds__card {
  display: grid;
  grid-template-rows: 72px auto;
  gap: var(--s3);
  align-content: center;
  justify-items: center;
  width: 264px;
  min-height: 152px;
  padding: var(--s5);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 0;
  text-align: center;
  color: var(--text-primary);
  transition:
    transform 260ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 260ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.creds__item:hover .creds__card,
.creds__item:focus-within .creds__card {
  transform: translateY(-4px);
  border-color: var(--accent-brass);
  box-shadow: 0 14px 26px -20px rgba(28, 33, 31, 0.55);
}

.creds__mark { display: grid; place-items: center; min-height: 72px; width: 100%; }
.creds__logo {
  max-height: calc(58px * var(--logo-scale, 1));
  max-width: calc(190px * var(--logo-scale, 1));
  width: auto;
  height: auto;
  mix-blend-mode: multiply;
}
.creds__wordmark {
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--text-primary);
}
.creds__kind {
  font-size: 0.6563rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-brass-deep);
  align-self: start;
}

@media (max-width: 47.99em) {
  .creds__card { width: 216px; min-height: 132px; grid-template-rows: 56px auto; padding: var(--s4); }
  .creds__mark { min-height: 56px; }
  .creds__logo { max-height: calc(46px * var(--logo-scale, 1)); max-width: calc(150px * var(--logo-scale, 1)); }
  .creds[data-creds-rolling] .creds__viewport {
    mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
  }
  .creds__track { gap: var(--s3); }
}

@media (prefers-reduced-motion: reduce) {
  .creds__item:hover .creds__card,
  .creds__item:focus-within .creds__card { transform: none; box-shadow: none; }
}

/* ---- The receptionist head: the crown goes on light ---- *
   The head was olive-charcoal with the genuine crown on it, which contradicts
   the rule this build applies everywhere else — the mark carries navy, gold and
   fine linework and turns to mud on a dark field. The launcher already states
   it: the crown sits on light, where it was designed to. The dialog now agrees,
   and the head reads as a continuation of the site header rather than a
   separate dark bar.                                                        */
.chat__head {
  background: var(--surface-parchment);
  border-bottom: 1px solid var(--border-brass);
}
.chat__title { color: var(--text-ink); }
.chat__role { color: var(--accent-brass-deep); }
.chat__close { color: var(--text-ink); }
.chat__close:hover { color: var(--accent-brass-deep); }
.chat__close:focus-visible { outline-color: var(--accent-brass-deep); }

/* ============ Journey gateway: the gallery fits its own band ============ *
   The gallery, its heading and its aside are all set to 1480px so the route
   cards read wider and more cinematic than body copy. The band around them was
   still capped at the standard 1320px content column, and `margin-inline: auto`
   on a child wider than its parent does not centre — it resolves to zero on the
   left and negative on the right. So the whole gallery hung 229px past the
   band's right edge and sat on the page surface outside it.

   Clipping it would have thrown away the intent. The band takes the wider
   measure instead, and everything inside centres honestly within it.        */
.band--journeys {
  max-width: none;
  padding-inline: var(--inset);
}
/* The numbered rule centres on the same measure as the cards it introduces. */
.band--journeys > .chapter {
  width: min(1480px, 100%);
  margin-inline: auto;
}
.band--journeys .band__head,
.band--journeys .gallery,
.band--journeys .gallery__aside,
.band--journeys .gallery__note {
  width: min(1480px, 100%);
}

/* ---- The Google Reviews lockup ---- *
   The review chapter read as typeset quotations rather than as Google reviews.
   The mark says where they came from at a glance, and it sits on the paper
   surface rather than on the dark score panel: the lockup's "Reviews" wordmark
   is mid-grey and would disappear against olive-charcoal, and Google's brand
   terms do not allow recolouring it to fix that.                            */
.rwall__source { margin: 0 0 var(--s4); }
.rwall__source-mark {
  width: clamp(132px, 12vw, 168px);
  height: auto;
  display: block;
  /* The supplied file is flattened on white; multiply drops that to the paper
     behind it without touching a single brand colour. */
  mix-blend-mode: multiply;
}

/* ---- Manual stepping ---- *
   Waiting for the right mark to come round is fine for a decorative logo wall
   and useless for somebody checking whether their deposit scheme is on it.  */
.creds { position: relative; }
.creds__nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  transform: translateY(-50%);
  background: var(--surface-parchment);
  border: 1px solid var(--border-brass);
  border-radius: 0;
  font-size: 1rem;
  color: var(--text-ink);
  cursor: pointer;
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1), border-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.creds__nav[hidden] { display: none; }
.creds__nav--prev { left: -10px; }
.creds__nav--next { right: -10px; }
.creds__nav:hover { background: var(--surface-ivory); border-color: var(--accent-brass-deep); }
.creds__nav:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 2px; }
@media (max-width: 47.99em) {
  .creds__nav--prev { left: -6px; }
  .creds__nav--next { right: -6px; }
}

/* ================= Credentials rail: the scrub control ================== *
   The arrows are gone. They only moved you one plate at a time and never said
   where you were in the set; a slider does both, drags on a phone, and takes
   arrow keys, Home and End for free.

   It is a real <input type="range">, restyled rather than replaced, so all of
   that keyboard behaviour is the browser's rather than something to reimplement
   and get subtly wrong.                                                     */

.creds__nav { display: none !important; }

.creds__scrub {
  display: flex;
  justify-content: center;
  margin-top: var(--s5);
}
.creds__scrub[hidden] { display: none; }

.creds__slider {
  -webkit-appearance: none;
  appearance: none;
  width: min(340px, 68%);
  height: 44px; /* the target, not the visible rail */
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: grab;
}
.creds__slider:active { cursor: grabbing; }

/* One hairline track, the same weight as the rules used elsewhere. */
.creds__slider::-webkit-slider-runnable-track {
  height: 2px;
  background: rgba(41, 38, 32, 0.24);
  border-radius: 0;
}
.creds__slider::-moz-range-track {
  height: 2px;
  background: rgba(41, 38, 32, 0.24);
  border-radius: 0;
}

/* A brass marker rather than a round grey knob: square geometry, like the
   rest of the system. */
.creds__slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 46px;
  height: 10px;
  margin-top: -4px;
  background: var(--accent-brass-deep);
  border: 0;
  border-radius: 0;
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.creds__slider::-moz-range-thumb {
  width: 46px;
  height: 10px;
  background: var(--accent-brass-deep);
  border: 0;
  border-radius: 0;
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.creds__slider:hover::-webkit-slider-thumb { background: var(--accent-brass); }
.creds__slider:hover::-moz-range-thumb { background: var(--accent-brass); }
.creds__slider:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 4px; }

@media (max-width: 47.99em) {
  .creds__slider { width: min(280px, 78%); }
  .creds__slider::-webkit-slider-thumb { width: 54px; }
  .creds__slider::-moz-range-thumb { width: 54px; }
}

/* The roll itself is the Web Animations API's, so the stylesheet only has to
   stop competing for the same property. */
.creds[data-creds-rolling] .creds__track { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .creds__scrub { display: none; }
}

/* The range input still carried its own border and radius under the custom
   track, which read as a rounded form control sitting in a square system. */
.creds__slider,
.creds__slider:focus {
  border: 0;
  border-radius: 0;
  outline-offset: 6px;
  background: transparent;
  box-shadow: none;
}
.creds__slider::-moz-focus-outer { border: 0; }
/* Give the rail a hairline the full width of the control so the thumb reads as
   a position along a measure rather than a lone marker. */
.creds__scrub { position: relative; }

/* ---- Notches ---- *
   One detent per credential, so the thumb reads as a position within a known
   set rather than a marker on an unmeasured line. Drawn on the wrapper rather
   than the input's track pseudo-element: the track is a 2px hairline and the
   notches need to stand proud of it, and the three browser engines disagree
   about how tall a range track is allowed to be.                            */
.creds__scrub::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(340px, 68%);
  height: 9px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(41, 38, 32, 0.3) 0 1px,
    transparent 1px calc(100% / var(--creds-count, 9))
  );
  /* The last notch would otherwise fall off the end of the repeat. */
  background-size: calc(100% - 1px) 100%;
  background-repeat: no-repeat;
}
.creds__scrub::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(340px, 68%);
  height: 1px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: rgba(41, 38, 32, 0.3);
}

/* The input sits above the drawn track, and stops drawing its own. */
.creds__slider { position: relative; z-index: 1; }
.creds__slider::-webkit-slider-runnable-track { background: transparent; }
.creds__slider::-moz-range-track { background: transparent; }

/* Grip lines on the thumb, so it reads as something to take hold of. */
.creds__slider::-webkit-slider-thumb {
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 20px,
    rgba(250, 247, 240, 0.55) 20px 21px,
    transparent 21px 24px
  );
}
.creds__slider::-moz-range-thumb {
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 20px,
    rgba(250, 247, 240, 0.55) 20px 21px,
    transparent 21px 24px
  );
}

@media (max-width: 47.99em) {
  .creds__scrub::before,
  .creds__scrub::after { width: min(280px, 78%); }
}

/* ---- Notches removed ---- *
   Nine tick marks across a hairline read as a measuring instrument, not as a
   premium control. The position is legible from the thumb's travel alone.   */
.creds__scrub::before { content: none; }

/* ---- The thumb loses its grip lines ---- *
   A light rule drawn across the middle of the marker read as a crack in it,
   not as something to take hold of. The block alone is the control.         */
.creds__slider::-webkit-slider-thumb { background-image: none; }
.creds__slider::-moz-range-thumb { background-image: none; }

/* A pinned plate says so: it holds the hover keyline rather than snapping back
   to flat the moment the pointer leaves. */
/* Only the plate you actually stopped on is marked, not the whole rail. */
.creds__item[data-pinned] .creds__card { border-color: var(--accent-brass); }
.creds { cursor: default; }
.creds[data-creds-rolling] .creds__item { cursor: pointer; }

/* ---- The track line goes too ---- *
   First the notches, now the rule they sat on. A hairline running out either
   side of the marker is measuring-instrument furniture; the marker's own
   travel across the band already says where you are. What is left is a single
   brass block that moves, which is all the control ever needed to be.       */
.creds__scrub::after { content: none; }
.creds__slider::-webkit-slider-runnable-track { background: transparent; border: 0; }
.creds__slider::-moz-range-track { background: transparent; border: 0; }

/* Slightly wider and softer now it stands alone, so it reads as a considered
   marker rather than a stray rectangle. */
.creds__slider::-webkit-slider-thumb { width: 58px; height: 8px; margin-top: -3px; }
.creds__slider::-moz-range-thumb { width: 58px; height: 8px; }

/* ---- The track line comes back ---- *
   Removing it was a step too far. The notches were the clutter; the rule was
   doing real work — it shows how far the set runs, so the marker's position
   means something instead of floating on an unmeasured field. Restored as one
   hairline, with the notches still gone.                                    */
.creds__scrub::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(340px, 68%);
  height: 1px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: rgba(41, 38, 32, 0.28);
}
@media (max-width: 47.99em) {
  .creds__scrub::after { width: min(280px, 78%); }
}

/* ---- The marker ---- *
   The native thumb is kept for dragging and for the keyboard, and made
   invisible: it can only sit on whole pixels, so at this speed it advanced in
   visible jerks. What is seen is a sibling positioned by transform, which the
   compositor moves in sub-pixels and therefore continuously.                */
.creds__slider::-webkit-slider-thumb { background: transparent; width: 58px; height: 22px; margin-top: -10px; }
.creds__slider::-moz-range-thumb { background: transparent; border: 0; width: 58px; height: 22px; }

.creds__marker {
  position: absolute;
  top: 50%;
  left: calc(50% - min(340px, 68%) / 2);
  width: 58px;
  height: 8px;
  background: var(--accent-brass-deep);
  pointer-events: none;
  transform: translate3d(0, -50%, 0);
  will-change: transform;
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.creds__slider:hover ~ .creds__marker,
.creds__slider:focus-visible ~ .creds__marker { background: var(--accent-brass); }

@media (max-width: 47.99em) {
  .creds__marker { left: calc(50% - min(280px, 78%) / 2); }
}
@media (prefers-reduced-motion: reduce) {
  .creds__marker { will-change: auto; }
}


/* The pointer-tracked tilt and sheen were removed after review. Kept here as a
   note rather than a file, because the reasons are worth not rediscovering:

   * 3deg moved the launcher's corner 1.2px. The two extremes of its travel were
     visually identical — the effect was invisible on the element it was built
     for.
   * The sheen gradient was ~316px across against a 223px launcher, so it could
     not track a pointer; it was a uniform wash. Its one visible effect was
     shifting the genuine crown's reds warm and flattening its golds, which the
     brand rules forbid outright.
   * `transition: transform 260ms` on the card silently reset transition-property
     and, at equal specificity but later in the file, killed the review card's
     -3px hover lift. That lift was the only hover feedback those cards had.
   * On a 288px card, 3deg is 5.6px at a corner and 0.04px at the centre, where
     a pointer actually rests. The only perceptible result was body copy losing
     subpixel antialiasing.

   The binding visual brief bans 3D tilts by name, twice. It was right. */


/* ============================ The footer ================================ *
   Measured against Apex's, which reads denser than ours and is worth being
   honest about why: four labelled columns, a contact block at the top, and a
   confident brand field.
   
   Their weakness is that the density is padding. Eighteen visible links resolve
   to about twelve destinations — "Book a Valuation" appears three times,
   "Commercial Property" and "Property EPC Ratings" twice each. Columns filled
   by repetition look complete and waste the reader's time.
   
   So this does not copy the grid. It fixes the two things that actually made
   ours weaker — one sparse column on a phone, and no contact block at all —
   and keeps the one thing Apex cannot claim: every destination appears exactly
   once, and the legal identity links to the public record rather than to a page
   about itself.                                                             */

/* Two columns on a phone. One column for six links was a whole screen of
   almost nothing, which is the entire reason theirs felt more substantial. */
.site-foot__nav { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6) var(--s5); }
@media (min-width: 48em) {
  .site-foot__nav { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.site-foot__list { display: grid; gap: 2px; }
.site-foot__list li { margin: 0; }
.site-foot__link {
  display: inline-block;
  padding: 7px 0;
  line-height: 1.35;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.site-foot__link:hover,
.site-foot__link:focus-visible { border-bottom-color: var(--accent-brass); }

/* ---- Contact ---- */
.site-foot__contact { margin: var(--s5) 0 0; font-style: normal; }
.site-foot__office-label {
  margin: 0 0 3px;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-brass-deep);
}
.site-foot__office { margin: 0; font-size: 0.9375rem; line-height: 1.5; color: var(--text-primary); max-width: 26ch; }

.site-foot__reach { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); margin: var(--s4) 0 0; }
.site-foot__reach-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text-primary);
  text-decoration: none;
  border-bottom: 1px solid var(--accent-brass);
}
.site-foot__reach-link span { transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1); display: inline-block; }
.site-foot__reach-link:hover span,
.site-foot__reach-link:focus-visible span { transform: translateX(3px); }

/* ---- The provenance note, moved down ---- *
   It has to stay — the film's licence is genuinely unconfirmed and the footer
   is where that is recorded. It does not have to be the loudest thing above
   the fold of the footer, which is what a bordered block in the main flow made
   it. It sits with the legal line instead, in the same quiet register.       */
.legalstrip { padding-block: var(--s4); }
.legalstrip__note {
  max-width: var(--max);
  margin: 0 auto var(--s2);
  font-size: 0.75rem;
  line-height: 1.55;
  color: rgba(244, 238, 227, 0.6);
}

/* The evidence group carries six links against the other two columns' three or
   four, so on a phone it takes the full width and lays them out two-up rather
   than running a long thin column down one side with dead space beside it. */
@media (max-width: 47.99em) {
  .site-foot__group:last-child { grid-column: 1 / -1; }
  .site-foot__group:last-child .site-foot__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px var(--s5);
  }
}

/* ====================== The compact menu, full screen =================== *
   Measured against Apex's, which is stronger and worth saying why: it commits
   to the whole screen, the rows are large enough to hit without looking, and
   the two actions sit anchored at the bottom where a thumb already is.

   Ours covered about 40% and let the page show through underneath, so it read
   as an unfinished dropdown rather than a menu. That is the fault being fixed.

   What is not copied is the burgundy field. Apex needs a saturated background
   because their mark is gold and has to survive on it; ours is parchment,
   which is the surface the genuine Dukes mark was drawn for.                */

@media (max-width: 63.99em) {
  .menu[open] .menu__panel {
    position: fixed;
    inset: var(--head-h, 61px) 0 0;
    z-index: 45;
    display: flex;
    flex-direction: column;
    padding: var(--s5) var(--inset) max(var(--s5), env(safe-area-inset-bottom));
    background: var(--surface-parchment);
    border-top: 1px solid var(--border-brass);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* Rows you can hit without aiming. */
  .menu[open] .mnav { flex: 1 1 auto; }
  .menu[open] .mnav__summary,
  .menu[open] .mnav__link--top {
    min-height: 60px;
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 400;
    letter-spacing: 0.01em;
  }
  .menu[open] .mnav__item { border-bottom: 1px solid var(--border-subtle); }
  .menu[open] .mnav__link { min-height: 48px; font-size: 1rem; }
  .menu[open] .mnav__caret { width: 9px; height: 9px; border-width: 2px; }

  /* The actions anchor to the bottom rather than trailing the list, so they
     are where a thumb rests and not wherever the links happen to end. */
  .menu[open] .menu__actions {
    margin-top: auto;
    padding-top: var(--s5);
    border-top: 1px solid var(--border-brass);
    gap: var(--s3);
  }
  .menu[open] .menu__actions .headact { min-height: 54px; font-size: 1rem; }

  /* The button says what pressing it does. A chevron that flips is a glyph
     you have to interpret. */
  .menu__label--close { display: none; }
  .menu[open] .menu__label--close { display: inline; }
  .menu[open] [data-menu-open-label] { display: none; }
}
@media (min-width: 64em) {
  .menu__label--close { display: none; }
}

/* ---- Filling the middle, and making the actions read as actions ---- */
@media (max-width: 63.99em) {
  .menu[open] .mnav { flex: 0 0 auto; }

  .menu__contact { margin-top: var(--s6); }
  .menu__contact-label {
    margin: 0 0 4px;
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-brass-deep);
  }
  .menu__contact-office { margin: 0; font-size: 0.9375rem; line-height: 1.5; color: var(--text-primary); max-width: 30ch; }
  .menu__contact-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-top: var(--s3);
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-brass);
  }

  /* Centred, like a button rather than another row in the list. */
  .menu[open] .menu__actions .headact { justify-content: center; text-align: center; }

  /* An X, not a rotated chevron. The hamburger's own bars become the cross. */
  .menu[open] .menu__glyph {
    position: relative;
    background: none;
    border: 0;
    width: 16px;
    height: 16px;
  }
  .menu[open] .menu__glyph::before,
  .menu[open] .menu__glyph::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 1.5px;
    background: var(--text-ink);
  }
  .menu[open] .menu__glyph::before { transform: rotate(45deg); }
  .menu[open] .menu__glyph::after { transform: rotate(-45deg); }
}

/* The glyph is already rotated 45deg by the open state further up, so bars at
   45/-45 landed at 90/0 and drew a plus. Zero the parent and let the bars be
   the only rotation in play. */
@media (max-width: 63.99em) {
  .menu[open] .menu__glyph { transform: none; }
}

/* ==================== The receptionist route list ======================= *
   Five rows that were entirely interactive and looked entirely like text.
   They are <summary> elements, so pressing one opens it — but nothing said so,
   and the 01-05 numbering actively worked against it: numbers read as a
   sequence to complete, when these are five alternatives and a reader picks
   one. The numbers are gone and a caret does the job they were occupying.   */

.reception__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 64px;
  padding: var(--s3) 0;
  cursor: pointer;
  list-style: none;
  transition: color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.reception__summary::-webkit-details-marker { display: none; }
.reception__label { font-size: 1.0625rem; line-height: 1.4; }

.reception__caret {
  flex: none;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--accent-champagne);
  border-bottom: 2px solid var(--accent-champagne);
  transform: rotate(45deg) translateY(-2px);
  transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.reception__disclosure[open] .reception__caret { transform: rotate(-135deg) translateY(-2px); }

/* It answers to a pointer, so it reads as something you can press. */
.reception__summary:hover { color: var(--accent-champagne); }
.reception__summary:hover .reception__caret { border-color: var(--text-on-dark); }
.reception__summary:focus-visible {
  outline: 2px solid var(--accent-champagne);
  outline-offset: 4px;
}

/* The demo notice was a dashed outline, which is the visual language of a
   validation error. It is a statement of fact, not a fault. */
.reception__demo {
  border: 0;
  border-left: 2px solid var(--accent-brass);
  padding: var(--s2) 0 var(--s2) var(--s4);
  background: none;
}

@media (prefers-reduced-motion: reduce) {
  .reception__caret { transition: none; }
}

/* ======================== The evidence rail ============================= *
   Seven records, each sized to its own text, so they staggered at seven
   different widths and the eye had nothing to follow. The category label also
   repeated on every card — "COMPANY PARTICULARS" three times, "PUBLISHED
   DOCUMENTS" three times — which is the label doing the grouping's job badly.

   A regular grid, and the label demoted to a quiet tag rather than the loudest
   line on each card. The record's own name leads, because that is the thing a
   reader is looking for.                                                    */

.rail__track {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
  width: auto;
  animation: none;
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 48em) {
  .rail__track { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 64em) {
  .rail__track { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.rail__viewport { overflow: visible; mask-image: none; -webkit-mask-image: none; }

.rail__item { min-width: 0; }
.rail__link,
.rail__card {
  display: grid;
  align-content: space-between;
  gap: var(--s3);
  min-height: 108px;
  height: 100%;
  padding: var(--s4);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 0;
  text-decoration: none;
  color: var(--text-primary);
  transition: border-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
a.rail__link:hover,
a.rail__link:focus-visible { border-color: var(--accent-brass); }

/* Name first, category second and quiet. */
.rail__org { font-size: 1rem; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; order: 1; }
.rail__category {
  order: 2;
  font-size: 0.625rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* ===================== The hero veil, derived not pasted ================ *
   It was a radial ellipse of near-black dropped over the middle of the film —
   an arbitrary shape with no relationship to the picture underneath, which is
   precisely why it read as a smudge rather than as light.

   The reference here is Apple's: the light belongs to the subject. Their type
   sits in the glow the object in frame is already casting, so nothing looks
   applied. This film has its own light — a bright dusk sky across the top and
   third, and progressively darker land below. So the protection follows that
   luminance instead of ignoring it: almost nothing over the sky, a gentle
   graded weight where the ground already is, and the copy sits in the part of
   the frame that was dark to begin with.

   Not Apex's approach, which is a flat burgundy wash across the whole aerial.
   That guarantees contrast and costs them the photography — their sky, their
   rooftops and their fields all end up one colour.

   Net effect: roughly 40% less darkening overall, and what remains is where
   the eye already expected shadow.                                          */
[data-page="home"] .stage__veil {
  background:
    /* Following the footage: sky stays open, ground carries the weight. */
    linear-gradient(
      180deg,
      rgba(14, 17, 15, 0.12) 0%,
      rgba(14, 17, 15, 0) 26%,
      rgba(14, 17, 15, 0.06) 58%,
      rgba(14, 17, 15, 0.42) 100%
    );
}

/* The eyebrow was champagne type over a moving picture with no ground of its
   own — the thing Apex's gold "REAL ESTATE" gets wrong on burgundy. A short
   rule either side and a text shadow give it an edge to sit against without
   putting it back in a box. */
[data-page="home"] .hero--stage .hero__eyebrow {
  color: #f0dcb8;
  text-shadow: 0 1px 16px rgba(10, 13, 11, 0.95), 0 0 3px rgba(10, 13, 11, 0.7);
}
[data-page="home"] .hero--stage .hero__eyebrow::before,
[data-page="home"] .hero--stage .hero__eyebrow::after { opacity: 0.85; }

/* ================= The copy carries its own light ====================== *
   The veil above no longer tries to protect the words: it only follows the
   film's own luminance. Legibility is now the copy's own job.

   This is the part of the Apple reference that actually matters. Their type is
   readable because the light in the frame belongs to the thing being lit — the
   glow is the subject's, and the words sit inside it. Nothing is laid over the
   picture. A frame-anchored scrim cannot do that anyway: the copy sits near the
   middle of a 1440 hero and near the bottom of a 390 one, so a fixed pool is
   aimed at the right place on exactly one viewport and at empty sky on the rest.

   So the pool travels with the copy. It is heavily blurred and much larger than
   the text, which is what stops it having an edge — an edge is what made the
   previous treatment read as a smudge rather than as light.                  */
[data-page="home"] .hero--stage .hero__copy { position: relative; isolation: isolate; }

[data-page="home"] .hero--stage .hero__copy::before {
  content: "";
  position: absolute;
  inset: -40% -30%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse 42% 40% at 50% 50%,
    rgba(12, 15, 13, 0.58) 0%,
    rgba(12, 15, 13, 0.38) 40%,
    rgba(12, 15, 13, 0.16) 66%,
    rgba(12, 15, 13, 0.04) 84%,
    rgba(12, 15, 13, 0) 100%
  );
}
[data-page="home"] .hero--stage .hero__copy > * { position: relative; z-index: 1; }

/* The gold that was hardest to see: the review line, which on a phone lands on
   the brightest sunlit part of the frame. Champagne rather than brass gives it
   the headroom the darker gold never had against that. */
[data-page="home"] .hero--stage .hero__score-label { color: #f2e0bf; }

/* The outlined action was a hairline over rooftops. A dark, slightly blurred
   fill gives it a surface to be an outline on, without turning it into a second
   solid button competing with the primary. */
[data-page="home"] .hero--stage .hero__second {
  background: rgba(12, 15, 13, 0.42);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border-color: rgba(242, 224, 191, 0.5);
}
[data-page="home"] .hero--stage .hero__second:hover {
  background: rgba(12, 15, 13, 0.62);
  border-color: rgba(242, 224, 191, 0.9);
}

/* ============= Hero height: the gateway has to be on screen ============= *
   The hero was tall enough that a phone showed the film and nothing else, so
   the three routes underneath — landlords, tenants, anything else — were an
   act of faith. Shortening it means the top of the gateway is visible without
   scrolling, which is what tells a visitor the site has somewhere to go.

   It got shorter for free as well: "Properties to rent" has been removed from
   the hero because it and "Find a home to rent" in the gateway were the same
   link twice, one directly above the other. Two controls doing one job is the
   thing that reads as filler. The hero keeps a single action, and the gateway
   keeps all three routes, which is the division of labour that was already
   implied by having both.                                                    */
.hero--stage { min-height: clamp(520px, calc(78svh - var(--head-h)), 720px); }
@media (max-width: 47.99em) {
  .hero--stage { min-height: clamp(500px, calc(72svh - var(--head-h)), 680px); }
}
@media (min-width: 64em) {
  .hero--stage { min-height: clamp(560px, calc(82svh - var(--head-h)), 760px); }
}

/* One action, so it should stop pretending to be one of a pair. */
[data-page="home"] .hero--stage .hero__actions { justify-content: center; }

/* ==================== The launcher arrives, and stays =================== *
   The stowing rule is gone from the script, so the old hidden state must not
   be reachable from a stale class either. Belt and braces: nothing hides this
   control now except reduced motion, which only removes the movement.        */
[data-enhanced] .launcher.is-stowed {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}

/* Rest state before the entrance. Only applied when the script is running, so
   a JavaScript failure leaves the launcher plainly visible rather than stuck
   at zero opacity waiting for a class that will never arrive. */
[data-enhanced] .launcher {
  opacity: 0;
  transform: translate3d(0, 10px, 0) scale(0.72);
  transition:
    opacity 260ms cubic-bezier(0, 0, 0.2, 1),
    /* Overshoot on the way in, so it settles rather than simply stopping.
       420ms is long enough to read as weight and short enough to stay a UI
       gesture rather than an effect. */
    transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1),
    background-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 220ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, opacity;
}
[data-enhanced] .launcher[data-launcher-in="on"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

/* Follow-through: the crown finishes after the plate it sits on, which is what
   separates one object arriving from two things moving in lockstep. A small
   counter-rotation gives it something to settle out of. */
[data-enhanced] .launcher .launcher__glyph {
  transform: scale(0.82) rotate(-7deg);
  opacity: 0;
  transition:
    transform 460ms cubic-bezier(0.34, 1.56, 0.64, 1) 110ms,
    opacity 240ms cubic-bezier(0, 0, 0.2, 1) 110ms;
}
[data-enhanced] .launcher[data-launcher-in="on"] .launcher__glyph {
  transform: scale(1) rotate(0deg);
  opacity: 1;
}

/* The label trails the crown by the same margin again.
   Transform only, deliberately: fading the label independently set its computed
   opacity below 1, and a contrast checker cannot evaluate text it cannot see
   through — it reported a serious colour-contrast failure on .launcher__text
   and .launcher__sub on every page in the site. The parent already carries the
   fade, so the stagger costs nothing by being movement alone. */
[data-enhanced] .launcher .launcher__text,
[data-enhanced] .launcher .launcher__sub {
  transform: translate3d(-4px, 0, 0);
  transition: transform 380ms cubic-bezier(0.34, 1.56, 0.64, 1) 190ms;
}
[data-enhanced] .launcher[data-launcher-in="on"] .launcher__text,
[data-enhanced] .launcher[data-launcher-in="on"] .launcher__sub {
  transform: none;
}

/* Once it has landed the hint is spent: keeping will-change on a permanently
   composited fixed element for the life of the page is the misuse the property
   is known for. */
[data-enhanced] .launcher[data-launcher-in="on"] { will-change: auto; }

/* The press has to survive the entrance transform rather than replace it. */
[data-enhanced] .launcher[data-launcher-in="on"]:active {
  transform: translate3d(0, 1px, 0) scale(0.97);
  transition: transform 110ms cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  [data-enhanced] .launcher,
  [data-enhanced] .launcher .launcher__glyph,
  [data-enhanced] .launcher .launcher__text,
  [data-enhanced] .launcher .launcher__sub {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
[data-motion="static"] [data-enhanced] .launcher,
[data-motion="static"] .launcher {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ================= The review summary, as one object =================== *
   Supersedes the earlier .score panel and the .rwall__source / .rwall__links
   stack, which together put five separate blocks between the section heading
   and the first review.                                                     */
.rwall__source, .rwall__links { display: none; }

.score {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s3);
  padding: 0;
  margin: var(--s5) 0 0;
  background: none;
  border: 0;
  color: var(--text-primary);
}

/* The number and the stars share a baseline instead of the stars sitting in a
   line of their own underneath. Stacked, they read as two unrelated facts; on
   one line they read as a rating, which is what they are. */
.score__line {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin: 0;
}
.score__value {
  font-family: var(--font-display);
  font-size: clamp(3rem, 2.4rem + 2.4vw, 4rem);
  line-height: 1;
  color: var(--text-primary);
  font-variant-numeric: lining-nums tabular-nums;
}
.score__stars {
  font-size: clamp(1.05rem, 0.9rem + 0.5vw, 1.3rem);
  letter-spacing: 0.16em;
  color: var(--accent-brass-deep);
  white-space: nowrap;
}

/* One meta line, not two. The capture date stays: it is the whole difference
   between a rating a visitor can trust and a number with no age on it. */
.score__meta {
  margin: 0;
  font-size: var(--t-small);
  color: var(--text-secondary);
  line-height: 1.5;
}
.score__meta strong { color: var(--text-primary); font-weight: 600; }
.score__sep { color: var(--border-subtle); }

/* The supplied mark, unaltered: full colour, on a light surface, never
   recoloured and never set on a dark panel where its grey "Reviews" would go.
   It is a link now rather than decoration, which is the part Apex leaves on
   the table. */
.score__brand { margin: var(--s2) 0 0; }
.score__brand a {
  display: inline-block;
  border-radius: 2px;
  transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.score__brand a:hover { opacity: 0.78; }
.score__brand a:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 4px; }
.score__brand-mark { display: block; width: auto; height: 34px; }

.score__acts { margin: var(--s3) 0 0; font-size: var(--t-small); }

@media (max-width: 47.99em) {
  .score__brand-mark { height: 28px; }
}

/* ---- The pause, docked to the wall ---- */
.rwall__wall { position: relative; }
.rwall__pause {
  position: absolute;
  top: calc(var(--s3) * -1);
  right: 0;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 36px;
  padding: 0 var(--s3);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  color: var(--text-secondary);
  cursor: pointer;
  transition:
    border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),
    color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.rwall__pause:hover { border-color: var(--accent-brass); color: var(--text-primary); }
.rwall__pause:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 2px; }
.rwall__pause-glyph {
  width: 9px;
  height: 10px;
  border-left: 3px solid currentColor;
  border-right: 3px solid currentColor;
}
/* Pressed means the wall is stopped, so the glyph becomes a play triangle. */
.rwall__pause[aria-pressed="true"] .rwall__pause-glyph {
  border: 0;
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 9px solid currentColor;
}
@media (max-width: 47.99em) {
  .rwall__pause { top: calc(var(--s2) * -1); font-size: 0.7rem; min-height: 32px; }
}

/* The anchor column is a deep panel, which the previous layout worked around by
   keeping the Google mark outside it. Rebuilding the lockup moved the mark in,
   and two things broke at once: the supplied mark ended up on a dark surface,
   which it is never allowed to be, and the count set in --text-primary went
   dark-ink-on-dark and disappeared entirely.
   Giving the lockup its own light plate fixes both at the source and is the
   better composition anyway: it is one object, so it should read as one card
   rather than as text floating on the panel behind it. */
/* The homepage score panel is a deliberate deep plate, set higher up the file
   with enough specificity to win, and it is the right call: it is the one dark
   object in a warm section and it makes the rating read as a single card.
   So the lockup keeps it, and the two things that broke when the Google mark
   moved inside are fixed properly rather than by flattening the panel.        */
.rwall__anchor .score { max-width: 30rem; }

/* On the deep plate the meta has to use the on-dark tokens. Set in
   --text-secondary it was dark ink on a dark panel: the count read as an empty
   gap and a contrast check reported it as a serious failure. */
[data-page="home"] .band--reviews .score__meta { color: var(--text-on-dark-soft); }
[data-page="home"] .band--reviews .score__meta strong { color: var(--text-on-dark); }
[data-page="home"] .band--reviews .score__sep { color: rgba(244, 238, 227, 0.4); }

/* The supplied Google mark is never allowed on a dark surface — its "Reviews"
   is set in a grey that disappears there, and recolouring it is not permitted.
   Moving it into the panel meant it needed a surface of its own, so it gets a
   light chip: the mark stays exactly as supplied, full colour on light, and the
   chip doubles as the hit area for the link through to the profile. */
[data-page="home"] .band--reviews .score__brand a {
  background: var(--surface-ivory);
  padding: var(--s3) var(--s4);
  border: 1px solid rgba(244, 238, 227, 0.16);
}
[data-page="home"] .band--reviews .score__brand a:hover {
  opacity: 1;
  border-color: var(--accent-champagne);
}

/* The pause sat over the first card because it was pulled above the wall by a
   negative offset. It gets its own room instead. */
.rwall__wall { padding-top: 52px; }
.rwall__pause { top: 4px; right: 0; }
@media (max-width: 47.99em) {
  .rwall__wall { padding-top: 46px; }
  .rwall__pause { top: 2px; }
}

/* ======================= Hero: three doors, one primary ================= *
   Apex's trio is three identical gold slabs: no hierarchy, and none of it
   related to the footage behind. Here the valuation keeps the one solid gold
   surface and the two routes flank it as quiet glass — dark enough to read on
   the film, transparent enough that the film stays the surface they sit on. */
.hero__actions--trio {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--s3);
  flex-wrap: wrap;
}
.hero__actions--trio .btn--gold { order: 0; }
.hero__side {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 var(--s5);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--warm-ivory);
  text-decoration: none;
  background: rgba(12, 15, 13, 0.42);
  border: 1px solid rgba(242, 224, 191, 0.5);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  transition:
    background-color 200ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero__side:hover,
.hero__side:focus-visible {
  background: rgba(12, 15, 13, 0.62);
  border-color: rgba(242, 224, 191, 0.9);
}
.hero__side:focus-visible { outline: 2px solid var(--accent-champagne); outline-offset: 3px; }

/* Portrait phones: the valuation leads on its own row, the two routes share
   the row beneath. In landscape and up all three sit in one row with the
   valuation centred — the Apex arrangement, with a hierarchy. */
@media (max-width: 47.99em) and (orientation: portrait) {
  .hero__actions--trio { flex-direction: column; align-items: stretch; }
  .hero__actions--trio .btn--gold { width: 100%; }
  .hero__side { flex: 1 1 0; }
  .hero__actions--trio::after { content: none; }
  .hero__sides-row { display: contents; }
}
@media (max-width: 47.99em) and (orientation: portrait) {
  .hero__actions--trio {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s3);
  }
  .hero__actions--trio .btn--gold { grid-column: 1 / -1; }
}
@media (min-width: 48em), (orientation: landscape) {
  .hero__actions--trio { flex-wrap: nowrap; }
  .hero__side { flex: 0 1 auto; }
}

/* ==================== Review wall: the verified fixes =================== */

/* Cards inherit the tallest review's height from the flex track, and a grid
   card stacked its content at the top with the slack dangling below the link —
   45% of the tallest card was void, and the verify rows sat at a different
   height on every card. As a column, the quote keeps its place and the
   permalink pins to the bottom edge of every card, which lines the verify rows
   up across the whole wall. */
.rwall__track > .rcard { display: flex; flex-direction: column; }
.rwall__track .rcard__link { margin-top: auto; }

/* The date must not orphan onto its own line: it is the fact the meta line
   exists to carry. */
.score__captured { white-space: nowrap; }
.score__meta { font-size: 0.8125rem; }

/* The Google chip hugs the mark instead of floating as a 94px sticker, and it
   carries a resting border so it reads as a control before the pointer finds
   it — invisible-until-hover was the only affordance it had. */
[data-page="home"] .band--reviews .score__brand a {
  padding: var(--s2) var(--s3);
  border: 1px solid rgba(17, 26, 22, 0.14);
}

/* ================== The dock, as a single catch-all strip =============== *
   With one route left, three empty grid columns would park the card in the
   left third. One item lays out as one full-width strip, centred, and the row
   stays shallower than the three-card band it replaces.                     */
.dock__list:has(> .dock__item:only-child) { display: block; }
.dock__list:has(> .dock__item:only-child) .dock__link {
  /* The base link is a grid, so the one-line arrangement must set display
     itself — flex-direction alone silently did nothing. */
  display: flex;
  min-height: 64px;
  flex-direction: row;
  align-items: baseline;
  justify-content: center;
  gap: var(--s4);
}
/* Engines without :has() keep the grid; the single card simply sits in the
   first column, which is inelegant but complete. */

/* ================ Wings contained in the hero's own row ================= *
   The wings ran top-to-bottom of the whole hero, but the route dock occupies
   the hero's last row, so on shorter laptop viewports the centred quotation's
   attribution — the reviewer's name and the "Google review" source line, the
   two things that make the quotation checkable — slid behind the dock band.

   The wings now stop where the dock begins. --dock-clear is measured by
   hero-wings.mjs and tracks the dock through every resize; the fallback here
   approximates one dock row plus the warm lip, so even with no JavaScript the
   attribution clears the band. No negative margins, no guessed heights.      */
@media (min-width: 75em) {
  .wing { bottom: var(--dock-clear, 132px); }
}

/* ================= Compact laptop composition =========================== *
   Not the desktop design scaled down: a different balance for the viewport it
   serves. Both dimensions gate it — a tall narrow desktop or a wide tall one
   keeps the full composition.

   The fixed margin CLAMPS a wing that is too wide and never widens one that
   is not: the first cut of this tier set a bare 236px, which at 1200-1440px
   was WIDER than the 16% it replaced and shrank the film — the exact defect
   it existed to fix. min() keeps whichever is smaller.

   The quote block hangs from the upper third rather than centring in the
   column: centred, the compact block floated in 44% void and read as a
   leftover. The outer screen edge keeps a real margin while the film-side
   edge absorbs the squeeze — the outer inset is what makes it read as a
   printed folio rather than text pushed against the bezel.                  */
@media (min-width: 75em) and (max-height: 56.25rem) {
  .stage__film { left: min(236px, 16%); right: min(236px, 16%); }
  .wing {
    width: min(236px, 16%);
    place-items: start center;
    padding-block: clamp(4rem, 12vh, 7rem) var(--s6);
  }
  .wing--left { padding-inline: clamp(1.5rem, 2.4vw, 2.25rem) clamp(1rem, 1.4vw, 1.5rem); }
  .wing--right { padding-inline: clamp(1rem, 1.4vw, 1.5rem) clamp(1.5rem, 2.4vw, 2.25rem); }
  .wing__quote { gap: var(--s2); }
  .wing__index { font-size: 0.625rem; letter-spacing: 0.15em; }
  .wing__stars { font-size: 0.75rem; letter-spacing: 0.2em; }
  .wing__text { padding-top: var(--s2); }
  /* The authored short excerpt replaces the full text; the clamp remains only
     as a guard against a future long short-form. text-wrap: pretty spends its
     effort on the last lines, which is where a 38px orphan word was landing. */
  .wing__text .wing__full { display: none; }
  .wing__text .wing__short {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 6;
    overflow: hidden;
  }
  .wing__text p {
    font-size: clamp(1.0625rem, 1rem + 0.2vw, 1.25rem);
    line-height: 1.45;
    text-wrap: pretty;
  }
}
@media (min-width: 90em) and (max-height: 56.25rem) {
  .stage__film { left: min(248px, 20%); right: min(248px, 20%); }
  .wing { width: min(248px, 20%); }
}
/* Shorter again (1280x720): tighter spacing, not smaller type — 17px is the
   floor. */
@media (min-width: 75em) and (max-height: 47.5rem) {
  .wing__text .wing__short { -webkit-line-clamp: 5; }
  .wing { padding-block: clamp(3.25rem, 10vh, 5rem) var(--s5); }
}

/* Outside the compact tier the full quotation shows and the short form does
   not exist. Unconditional, not a negated media query: `@media not (...)`
   failed silently on the current engine and both paragraphs rendered at once
   on big desktop, pushing the attribution under the dock. The compact tier
   re-shows the short form with a more specific selector, so source order no
   longer matters. */
.wing__short { display: none; }

/* The single-route dock strip lost its inset at 1280 (list at x=0). Content
   is centred so nothing touched the edge, but the one tight width should not
   be the one with no container. */
.dock__list:has(> .dock__item:only-child) { padding-inline: clamp(1.5rem, 4vw, 6rem); }

/* ================= The gateway, on a contained cream panel ============== *
   The section ran edge to edge on the page's own muted surface, so the four
   routes floated on the same plane as everything above and below them and the
   band read as a continuation rather than as a place where a decision is made.

   It becomes one restrained cream panel, inset from both edges, with the page
   white either side. The white gutters are the point: they give the panel an
   edge, and an edge is what makes it read as a considered object rather than
   as a section that happens to have a background colour.                    */
[data-page="home"] .band--journeys {
  /* White, not ivory. The first pass set the band to ivory and the panel to
     parchment, and at those two values the gutters were invisible — the panel
     had no edge, so it was not a panel. The canvas has to be the page's
     lightest surface for the cream to read as an object sitting on it. */
  background: #ffffff;
  padding-inline: clamp(1rem, 4vw, 4rem);
  /* The panel below is absolutely positioned; without this it anchors to some
     ancestor other than the band and the cream never appears where intended.
     It computed a correct inset and still rendered nothing visible. */
  position: relative;
}
[data-page="home"] .band--journeys > * {
  position: relative;
  z-index: 1;
}
[data-page="home"] .band--journeys::before {
  content: "";
  position: absolute;
  inset: clamp(1.5rem, 3vw, 3.25rem) clamp(1rem, 5vw, 5.5rem);
  z-index: 0;
  background: var(--surface-parchment);
  border: 1px solid var(--border-subtle);
  pointer-events: none;
}
/* The chapter rule runs edge to edge above the panel and belongs to the white
   canvas, so it keeps the band's own inset rather than the panel's. */
[data-page="home"] .band--journeys > .chapter { padding-top: clamp(2.5rem, 4vw, 4rem); }
/* The content sits inside the panel's inset, not the band's. */
[data-page="home"] .band--journeys > .chapter,
[data-page="home"] .band--journeys .band__head,
[data-page="home"] .band--journeys .gallery {
  width: min(1240px, 100%);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 3vw, 3.5rem);
}
[data-page="home"] .band--journeys > .chapter { padding-top: clamp(1rem, 2vw, 2rem); }
[data-page="home"] .band--journeys .gallery { padding-bottom: clamp(1.5rem, 3vw, 3rem); }

/* ---- Four equal cards ---- *
   Equal in every dimension, so the 2x2 reads as a grid rather than as four
   things that happen to be near each other. */
[data-page="home"] .band--journeys .gallery { align-items: stretch; }
[data-page="home"] .band--journeys .gcard { display: flex; }
[data-page="home"] .band--journeys .gcard__link {
  flex: 1;
  display: flex;
  align-items: flex-end;
}

/* A neutral photographic gradient, not a green wash. The scrim was tinted
   toward the brand green on every image, which flattened four different
   photographs into one colour and lost the warm interior light that made two
   of them worth using. Neutral black carries the text and leaves the
   photography its own colour. */
[data-page="home"] .band--journeys .gcard__scrim {
  background: linear-gradient(
    180deg,
    rgba(10, 12, 11, 0) 34%,
    rgba(10, 12, 11, 0.38) 58%,
    rgba(10, 12, 11, 0.74) 84%,
    rgba(10, 12, 11, 0.86) 100%
  );
}

/* Restrained interaction: the image breathes, the arrow steps, the border
   warms. Nothing glows and nothing jumps — the card is already a whole link,
   so the feedback only has to confirm that. */
[data-page="home"] .band--journeys .gcard__link {
  border: 1px solid var(--border-subtle);
  transition: border-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-page="home"] .band--journeys .gcard__link:hover,
[data-page="home"] .band--journeys .gcard__link:focus-visible {
  border-color: var(--accent-brass);
  transform: none;
}
[data-page="home"] .band--journeys .gcard__media img {
  transition: transform 420ms cubic-bezier(0.4, 0, 0.2, 1);
}
[data-page="home"] .band--journeys .gcard__link:hover .gcard__media img,
[data-page="home"] .band--journeys .gcard__link:focus-visible .gcard__media img {
  transform: scale(1.02);
}
[data-page="home"] .band--journeys .gcard__link:focus-visible {
  outline: 2px solid var(--accent-brass-deep);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  [data-page="home"] .band--journeys .gcard__media img,
  [data-page="home"] .band--journeys .gcard__arrow { transition: none; transform: none !important; }
}

/* ---- Mobile: one column, one card height ---- */
@media (max-width: 47.99em) {
  [data-page="home"] .band--journeys::before {
    inset: clamp(1rem, 3vw, 1.5rem) clamp(0.5rem, 2vw, 1rem);
  }
  [data-page="home"] .band--journeys .gallery { gap: var(--s4); }
  [data-page="home"] .band--journeys .gcard__link { height: 13.5rem; }
  /* The blurb is hidden at this width by an earlier rule, which left the CTA
     as the only thing separating one card from the next. It earns its room. */
  [data-page="home"] .band--journeys .gcard__line { display: block; }
}

/* On a phone the card is 216px and the copy block starts 17% down it, but the
   scrim stayed fully transparent until 34% — so the eyebrow and title sat on
   bare photograph, and on the two interior shots that meant cream type over a
   sunlit window. The gradient starts earlier at this size, because the text
   does. Same neutral black, same restraint, different geometry. */
@media (max-width: 47.99em) {
  [data-page="home"] .band--journeys .gcard__scrim {
    background: linear-gradient(
      180deg,
      rgba(10, 12, 11, 0.12) 0%,
      rgba(10, 12, 11, 0.52) 22%,
      rgba(10, 12, 11, 0.74) 52%,
      rgba(10, 12, 11, 0.88) 100%
    );
  }
}

/* ---- Gateway corrections from review ---- */

/* The brass eyebrow was failing AA over the two interior photographs: 49% of
   its glyph area below 4.5:1 on the tenants card at 1440, because the copy
   lands at 51% of the card where the scrim was only 0.28 alpha, over sunlit
   cream plaster. Brass is a mid-tone, so lightening the ink cannot fix it —
   cream over that wall is still 2.6:1. Only the gradient can, so the middle
   stops carry more weight. The top third is untouched, which is what keeps
   each photograph its own. */
[data-page="home"] .band--journeys .gcard__scrim {
  background: linear-gradient(
    180deg,
    rgba(10, 12, 11, 0) 28%,
    rgba(10, 12, 11, 0.7) 50%,
    rgba(10, 12, 11, 0.84) 74%,
    rgba(10, 12, 11, 0.9) 100%
  );
}
@media (max-width: 47.99em) {
  [data-page="home"] .band--journeys .gcard__scrim {
    background: linear-gradient(
      180deg,
      /* Raised again for the rebuilt copy: the buyer and management blurbs run
         a line longer, which lifts the kicker into brighter parts of both
         photographs. Measured at 4.46 and 4.39 against a 4.5 requirement. */
      rgba(10, 12, 11, 0.26) 0%,
      rgba(10, 12, 11, 0.8) 18%,
      rgba(10, 12, 11, 0.88) 52%,
      rgba(10, 12, 11, 0.93) 100%
    );
  }
}

/* The panel boundary sat exactly halfway between the page edge and the cards —
   72px gutter, 71.2px inner padding — so it read as a colour change dropped
   into the margin rather than as a frame with something inside it. The gutter
   stays; the inside grows, which is what makes it a panel. */
[data-page="home"] .band--journeys .gallery,
[data-page="home"] .band--journeys .band__head {
  padding-inline: clamp(1.25rem, 5vw, 7rem);
}
@media (max-width: 47.99em) {
  /* An 8px sliver of white reads as a misregistration, not an edge. */
  [data-page="home"] .band--journeys::before {
    inset: clamp(1rem, 3vw, 1.5rem) 20px;
  }
}

/* Card 1's blurb is one line and card 2's is two, which stepped the top row of
   copy by 27px. Reserving two lines levels the row without touching any
   wording. The CTAs were already aligned to the pixel. */
[data-page="home"] .band--journeys .gcard__line { min-height: 2lh; }

/* ============= Hero: two actions, deliberately unequal ================== *
   Supersedes the three-up trio. One solid gold surface and one quiet glass
   block, so the hierarchy is legible before a single word is read. The pair
   shares the trio's glass treatment; only the count and the balance change. */
.hero__actions--pair {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--s3);
  flex-wrap: wrap;
}
/* The primary carries more presence than the secondary at every width, rather
   than the two simply being different colours of the same size. */
.hero__actions--pair .btn--gold { padding-inline: clamp(1.75rem, 3vw, 2.75rem); }
.hero__actions--pair .hero__side { padding-inline: clamp(1.25rem, 2vw, 1.75rem); }

@media (max-width: 47.99em) and (orientation: portrait) {
  .hero__actions--pair { flex-direction: column; align-items: stretch; }
  .hero__actions--pair .btn--gold,
  .hero__actions--pair .hero__side { width: 100%; }
}
@media (min-width: 48em), (orientation: landscape) {
  .hero__actions--pair { flex-wrap: nowrap; }
}

/* The dock stays subordinate to the hero it sits under: quieter type, less
   height, no competing surface. It is a question, not a third row of buttons. */
[data-page="home"] .hero--stage .dock__action {
  font-size: clamp(1.125rem, 1rem + 0.35vw, 1.375rem);
}

/* On a portrait phone the hero and the route dock share the opening viewport,
   and "View Properties" and "Find a home to rent" are the same destination
   twice inside it — stacked, eight lines apart. The dock keeps it, because the
   dock's version names who it is for, and the hero is left with the single
   action worth leading on. Nothing is hidden that is not reachable one row
   below and again in the header. */
@media (max-width: 47.99em) and (orientation: portrait) {
  .hero__actions--pair .hero__side { display: none; }
}

/* ============ Hero actions: one accent, one genuinely quiet ============= *
   The primary was painted --surface-parchment, which computes to the exact
   background colour of the header — #e8decc, byte for byte. So the opening
   viewport carried three parchment surfaces and no accent at all, and "the
   strongest hero action" was the same neutral plate as everything else.
   --sand is already the accent in the base .btn--gold; this restores it on
   the homepage hero, where the one solid object should be the one that matters. */
[data-page="home"] .hero--stage .btn--gold {
  --btn-fill: var(--sand);
  --btn-fg: #0b231c;
  background: var(--sand);
  color: #0b231c;
  border: 1px solid var(--copper);
}
[data-page="home"] .hero--stage .btn--gold:hover,
[data-page="home"] .hero--stage .btn--gold:focus-visible {
  background: var(--accent-champagne, #f0dcb8);
  border-color: var(--accent-brass-deep);
}

/* The secondary was described as glass and was not: rgba(12,15,13,0.42) over
   blur composited to 1.78:1 against the film beside it — an opaque black plate,
   and the same rendered luminance as the header's filled primary 400px above.
   Two dark filled slabs teach the reader that dark means important, then point
   them at two different places. This one now genuinely lets the film through
   and reads as an outline, which is what a secondary is. */
[data-page="home"] .hero--stage .hero__side {
  background: rgba(12, 15, 13, 0.18);
  border: 1px solid rgba(242, 224, 191, 0.85);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}
[data-page="home"] .hero--stage .hero__side:hover,
[data-page="home"] .hero--stage .hero__side:focus-visible {
  background: rgba(12, 15, 13, 0.34);
  border-color: var(--accent-champagne, #f0dcb8);
}

/* The dock went full bleed below 1366 while every other element kept a ~58px
   inset, so at 1280 "FOR LANDLORDS" sat 31.6px outside the page margin. */
.hero--stage .dock__list {
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 3.75rem);
}

/* The authored short excerpt is budgeted for 1440. At 1366 and 1280 the column
   narrows, the same words need more lines, and a 6-line clamp cut a third of
   the text off mid-word — the exact defect the authored short form exists to
   prevent. More lines are available: the attribution has 110px of clearance
   above the dock at these widths, so this does not push it back under. */
@media (min-width: 75em) and (max-width: 87.5em) {
  .wing__text .wing__short { -webkit-line-clamp: 9; }
  /* Nine lines fit the text but left only 29px between the attribution and the
     dock, down from 110. The lines are tightened rather than the quote being
     re-clipped: the attribution keeping real clearance is the whole reason this
     work started, and it must not be paid for out of that margin. */
  .wing__text p { line-height: 1.34; }
  .wing__quote { gap: calc(var(--s2) * 0.75); }
}

/* ============ The launcher's travelling brass perimeter ================= *
   A concierge entrance, not a chatbot bubble. The problem it solves is real:
   a quiet ivory plate in the corner of a quiet ivory page is easy to miss
   entirely. The problem it must not create is the pulsing, glowing, colour-
   cycling widget every AI product ships.

   So the resting state is unchanged — one 1px neutral brass hairline — and the
   only thing that ever moves is a single narrow champagne segment travelling
   the perimeter once, occasionally. Between passes there is nothing to see.

   Built from a conic gradient masked to the border, which is the one technique
   that can light a rounded rectangle's edge without a second element tracing
   its corners. `--launcher-angle` is registered as a real <angle> so it can be
   interpolated at all; an unregistered custom property is a string and would
   jump from 0 to 360 in one frame.                                          */
@property --launcher-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

[data-enhanced] .launcher {
  /* The halo has to be allowed out of the box. The base rule clips it. */
  overflow: visible;
  isolation: isolate;
}

[data-enhanced] .launcher::before,
[data-enhanced] .launcher::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  /* A ~30deg lit segment: 8.3% of the circuit. Wider reads as a sweep, much
     narrower stops registering as light at all and starts to flicker. */
  /* Saturated brass, not champagne. The first attempt lit the segment in
     #f0dcb8 on a #e8decc plate — light on light, and it measured as visible
     while being invisible. On a cream surface an illuminated edge has to read
     as metal catching the light, which means more chroma than the hairline it
     runs along, not more lightness. Champagne survives only at the very tips,
     where it reads as the highlight rolling off. */
  background: conic-gradient(
    from var(--launcher-angle),
    transparent 0%,
    rgba(197, 166, 106, 0.35) 2.5%,
    rgba(240, 220, 184, 1) 4%,
    rgba(143, 80, 36, 1) 6%,
    rgba(169, 120, 66, 0.9) 7.5%,
    rgba(197, 166, 106, 0.3) 8.3%,
    transparent 11%
  );
  /* Masked to the border only. Without the exclude the gradient fills the
     plate and the whole launcher becomes the advertisement this must not be. */
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  padding: 2px;
  /* The crisp line must sit above its own halo. ::after paints after ::before
     by default, so the blurred copy was covering the sharp one and only the
     smudge was visible. */
  z-index: 3;
}

/* The halo is the same segment again, blurred and held well back. Separating
   it from the crisp line is what keeps it a soft light rather than a smear:
   the line stays 1px sharp, the glow sits behind it at a fifth of the alpha. */
[data-enhanced] .launcher::after {
  inset: -3px;
  padding: 4px;
  filter: blur(5px);
  opacity: 0;
  z-index: 1;
}

/* One circuit, then quiet. 14s in total, with the pass occupying the first 8s, so the
   segment travels for 8 seconds and the border is an ordinary hairline for the
   remaining 6. A CSS animation rather than a JS timer, deliberately: an
   infinite CSS animation cannot be restarted by a scroll handler, cannot stack
   on resize, and is suspended and resumed by the browser across tab switches
   and the back-forward cache with no code to get wrong. */
@keyframes launcher-travel {
  0%   { --launcher-angle: 0deg;   opacity: 0; }
  3%   { opacity: 1; }
  50%  { --launcher-angle: 360deg; opacity: 1; }
  57%  { --launcher-angle: 360deg; opacity: 0; }
  100% { --launcher-angle: 360deg; opacity: 0; }
}

[data-enhanced] .launcher[data-launcher-in="on"]::before {
  animation: launcher-travel 14s linear 1.5s infinite;
}
[data-enhanced] .launcher[data-launcher-in="on"]::after {
  animation: launcher-travel 14s linear 1.5s infinite;
  /* The halo peaks lower than the line it belongs to. */
  animation-name: launcher-travel-halo;
}
@keyframes launcher-travel-halo {
  0%   { --launcher-angle: 0deg;   opacity: 0; }
  3%   { opacity: 0.55; }
  50%  { --launcher-angle: 360deg; opacity: 0.55; }
  57%  { --launcher-angle: 360deg; opacity: 0; }
  100% { --launcher-angle: 360deg; opacity: 0; }
}

/* ---- Hover and keyboard focus ---- */
/* The segment brightens and settles rather than the plate lighting up. The
   lift is 2px and the shadow stays a contact shadow, not a halo. */
[data-enhanced] .launcher[data-launcher-in="on"]:hover,
[data-enhanced] .launcher[data-launcher-in="on"]:focus-visible {
  transform: translate3d(0, -2px, 0);
  box-shadow: 0 10px 22px -14px rgba(28, 33, 31, 0.5);
  border-color: var(--accent-brass);
}
[data-enhanced] .launcher[data-launcher-in="on"]:hover::before,
[data-enhanced] .launcher[data-launcher-in="on"]:focus-visible::before {
  animation-play-state: running;
  opacity: 1;
}
[data-enhanced] .launcher[data-launcher-in="on"]:hover::after,
[data-enhanced] .launcher[data-launcher-in="on"]:focus-visible::after { opacity: 0.7; }
/* The crown alone, and barely. Animating the text as well is what makes a
   control feel like it is inflating. */
[data-enhanced] .launcher .launcher__glyph { transform-origin: center; }
[data-enhanced] .launcher[data-launcher-in="on"]:hover .launcher__glyph,
[data-enhanced] .launcher[data-launcher-in="on"]:focus-visible .launcher__glyph {
  transform: scale(1.02);
}

/* ---- While the conversation is open ---- */
/* The launcher must not compete with the panel it opened. No JavaScript and no
   timer: :has() reads the dialog's own open state, so there is nothing to
   resume incorrectly and nothing to leak on close. */
/* Specificity has to beat the entrance rule, which sets opacity on the same
   elements — at equal weight the launcher stayed at full opacity and the ring
   kept running while the conversation was open. */
body:has(dialog[open]) [data-enhanced] .launcher::before,
body:has(dialog[open]) [data-enhanced] .launcher::after,
[data-enhanced] body:has(dialog[open]) .launcher::before,
[data-enhanced] body:has(dialog[open]) .launcher::after,
body:has(dialog[open]) .launcher[data-launcher-in="on"]::before,
body:has(dialog[open]) .launcher[data-launcher-in="on"]::after {
  animation-play-state: paused;
  opacity: 0;
}
body:has(dialog[open]) .launcher[data-launcher-in="on"],
body:has(dialog[open]) [data-enhanced] .launcher { opacity: 0.5; }

/* ---- Reduced motion: the hairline stays, the travel goes ---- */
@media (prefers-reduced-motion: reduce) {
  [data-enhanced] .launcher::before,
  [data-enhanced] .launcher::after { animation: none; opacity: 0; }
  [data-enhanced] .launcher[data-launcher-in="on"]:hover,
  [data-enhanced] .launcher[data-launcher-in="on"]:focus-visible { transform: none; }
  [data-enhanced] .launcher[data-launcher-in="on"]:hover .launcher__glyph,
  [data-enhanced] .launcher[data-launcher-in="on"]:focus-visible .launcher__glyph { transform: none; }
}
[data-motion="static"] .launcher::before,
[data-motion="static"] .launcher::after { animation: none; opacity: 0; }

/* ---- Position, safe areas and footer clearance ---- */
[data-enhanced] .launcher {
  right: max(16px, env(safe-area-inset-right));
  bottom: max(16px, calc(env(safe-area-inset-bottom) + 12px));
}
@media (max-width: 47.99em) {
  /* Compact on a phone: the crown and the name stay, the supporting line goes.
     A two-line card in the corner of a 375px screen covers more of the page
     than it earns. */
  [data-enhanced] .launcher {
    grid-template-columns: auto auto;
    align-items: center;
    gap: var(--s2);
    padding: 12px var(--s4);
    min-height: 48px;
    right: max(12px, env(safe-area-inset-right));
    bottom: max(12px, calc(env(safe-area-inset-bottom) + 10px));
    max-width: calc(100vw - 24px);
  }
  [data-enhanced] .launcher .launcher__glyph { display: grid; width: 26px; height: 26px; }
  [data-enhanced] .launcher .launcher__sub { display: none; }
}
/* So a fixed control can never sit on top of the legal line at the foot of the
   page. Clearance, not stowing — hiding it was the behaviour that made it
   unreliable in the first place. */
[data-enhanced] .site-foot { padding-bottom: clamp(5rem, 8vh, 7rem); }

/* The disc is retired below the desktop breakpoint. It hid "Speak to Dukes" in
   a visually-hidden span, so on every phone and tablet the control was a gold
   crown in a circle with no words on it — a symbol a first-time visitor has no
   reason to read as "talk to someone". The label is the discoverability.
   The compact pill keeps the crown, keeps the name, and drops only the
   supporting line, which is the one part a phone genuinely has no room for. */
@media (max-width: 63.99em) {
  [data-enhanced] .launcher {
    width: auto;
    height: auto;
    min-height: 48px;
    padding: 10px var(--s4) 10px 12px;
    border-radius: var(--radius-control);
    place-items: center;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--s3);
    max-width: calc(100vw - 24px);
  }
  [data-enhanced] .launcher .launcher__glyph {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
  }
  /* Undo the visually-hidden clip: the name is the point of the control. */
  [data-enhanced] .launcher .launcher__label {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
    white-space: nowrap;
  }
  [data-enhanced] .launcher .launcher__text { font-size: 0.875rem; }
}
/* Only the very narrowest phones lose the supporting line; a 768 tablet keeps
   it, because it has the room. */
@media (max-width: 47.99em) {
  [data-enhanced] .launcher .launcher__sub { display: none; }
}

/* ---- The buyer card's confirmation label ---- *
   Discreet, not decorative, and deliberately not styled as a badge: a badge
   reads as a feature ("New", "Popular"), and this is the opposite — a note
   that the service behind the card is not yet agreed. It sits with the
   audience kicker because that is where the card says who it is for, and the
   qualification belongs to the same breath.

   The card is otherwise identical to the other three. Equal prominence was
   asked for and is right: a visitor looking to buy should see the route, and
   the label is for the client reviewing this preview, not a reason to demote
   the card visually. */
.gcard__flag {
  display: block;
  margin-top: 4px;
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(240, 220, 184, 0.82);
  font-weight: 600;
}
.gcard__flag::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 6px;
  vertical-align: middle;
  border-radius: 50%;
  background: var(--copper, #8f5024);
  box-shadow: 0 0 0 1px rgba(240, 220, 184, 0.55);
}
/* The dashed edge already carried by .gcard--planned says the same thing
   silently; both together are enough, and neither shouts. */
@media (max-width: 47.99em) {
  .gcard__flag { font-size: 0.5rem; letter-spacing: 0.12em; }
}

/* ================== Why Dukes: the proof sequence ====================== *
   Place, then person, then action. One editorial sequence in a fixed frame,
   not a carousel: no arrows, no dots, no slide. The three principles beside it
   are the controls, so moving through the images is the same act as reading
   the claims they stand for.

   The frame size is fixed per breakpoint and the images are absolutely
   positioned inside it, so the section cannot move as the picture changes —
   the defect this composition exists to avoid.                              */
.proofseq { position: relative; width: 100%; }
.proofseq__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--surface-parchment);
}
.proofseq__shot {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 750ms cubic-bezier(0.4, 0, 0.2, 1);
}
.proofseq__shot[data-active] { opacity: 1; }
.proofseq__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* A 1.5% drift, and only on the frame being shown. Enough to keep a held still
   from looking frozen; far short of a zoom. */
@media (prefers-reduced-motion: no-preference) {
  /* Every frame drifts, not only the visible one. Running it on [data-active]
     alone meant the outgoing picture dropped its transform the instant the
     attribute was removed — 0.87% of width in a single frame, at 99.9% opacity,
     which is a visible pop in the middle of the crossfade. It also meant each
     frame only ever played the first half of a 12s alternate ramp, so the
     drift never reached the 1.5% it declares. 6s each way completes the arc
     within one hold. */
  .proofseq[data-proof-seq] .proofseq__shot img {
    animation: proof-drift 6s ease-in-out infinite alternate;
  }
  /* Must match the specificity of the rule that sets `animation`, or the
     shorthand resets play-state to running and the picture keeps creeping
     while it is supposedly held. */
  .proofseq[data-proof-seq][data-proof-paused] .proofseq__shot img,
  .proofseq[data-proof-seq][data-proof-paused] .proofseq__shot[data-active] img {
    animation-play-state: paused;
  }
}
/* A slow push, not a zoom. 3% over a 6s hold is roughly 15px of travel across
   a 510px frame — enough that the picture reads as alive rather than as a
   pasted still, and far short of anything that announces itself as an effect.
   The half-percent of vertical drift is what stops it looking like a lens
   zooming: real camera movement has a direction.

   Every frame runs this same animation in sync, which is what makes the
   handover invisible — at the moment of the crossfade the outgoing and
   incoming pictures are at an identical scale, so there is nothing to pop.
   6s per direction matches the 6s hold, so each frame gets one clean pass
   rather than reversing mid-view. */
@keyframes proof-drift {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to { transform: scale(1.03) translate3d(0, -0.5%, 0); }
}

/* ---- The counter and progress line ---- */
.proofseq__meter {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-top: var(--s3);
}
.proofseq__count {
  margin: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Was --border-subtle: 1.32:1 against the panel, which is not text, it is a
   smudge. The frame index carries nothing a non-sighted reader can act on, so
   the meter is aria-hidden in the markup and this only has to satisfy the eye —
   but it still has to be legible to the eye it is for. */
.proofseq__of { color: var(--text-secondary); opacity: 0.55; }
.proofseq__line {
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
  position: relative;
  overflow: hidden;
}
.proofseq__fill {
  position: absolute;
  inset: 0;
  background: var(--accent-brass-deep);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

/* ---- The caption ---- *
   Editorial, not a warning banner. It says what the pictures are, in the same
   register as a photo credit, because that is what it is. */
.proofseq__caption {
  margin: var(--s3) 0 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-secondary);
  font-style: italic;
  letter-spacing: 0.01em;
}

/* ---- The principles, now controls ---- */
.welcome__principles[data-proof-nav] { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
/* The list item kept its own padding and bottom border from the plain-list
   version, so each row was 87px tall around a 54px button — 38% dead click
   zone — and drew a second grey hairline under the button's own brass rule.
   The button owns the whole row now, and .principle__rule is the only rule. */
.welcome__principles[data-proof-nav] > li { padding: 0; border-bottom: 0; margin: 0; }
.principle {
  display: grid;
  gap: 6px;
  width: 100%;
  padding: var(--s3) 0;
  background: none;
  border: 0;
  text-align: left;
  font: inherit;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.principle__label { font-size: var(--t-small); }
/* A fine brass rule, not a coloured card. It is the whole indicator. */
.principle__rule {
  display: block;
  height: 1px;
  background: var(--border-subtle);
  position: relative;
  overflow: hidden;
}
.principle__rule::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-brass-deep);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
.principle[aria-pressed="true"] { color: var(--text-primary); }
.principle[aria-pressed="true"] .principle__rule::after { transform: scaleX(1); }
.principle:hover { color: var(--text-primary); }
.principle:hover .principle__rule::after { transform: scaleX(0.35); }
.principle:focus-visible {
  outline: 2px solid var(--accent-brass-deep);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  /* A progress line that can never progress is furniture with no function. */
  .proofseq__line { display: none; }
  .proofseq__shot { transition: none; }
  .proofseq__shot img { animation: none !important; }
  .principle__rule::after { transition: none; }
}
[data-motion="static"] .proofseq__shot { transition: none; }
[data-motion="static"] .proofseq__shot img { animation: none !important; }

/* ---- Mobile: image first, then copy, then the selectors ---- */
@media (max-width: 47.99em) {
  .welcome__grid { display: flex; flex-direction: column; align-items: stretch; }
  /* Explicit width, because the frame's only size is an aspect ratio: a flex
     item that shrink-to-fits around content with no intrinsic width resolves
     to zero, and the image vanished entirely on a phone. */
  .welcome__media { order: 1; width: 100%; align-self: stretch; }
  .proofseq, .proofseq__frame { width: 100%; }
  .welcome__copy { order: 2; }
  .proofseq__frame { aspect-ratio: 4 / 3; }
  .principle { padding: var(--s3) 0; min-height: 44px; }
  /* The floating launcher sits in the bottom-right corner and covered the
     right half of the progress line and the end of the caption — measured
     166x17px of overlap at 375. Real clearance, not a no-op declaration. */
  .proofseq__meter { padding-right: 188px; }
  .proofseq__caption { padding-right: 188px; }
}

/* ================= Navigation: collapse before it squeezes ============== *
   The desktop bar appeared from 1024px. With the full architecture that left
   25px between the last nav item and the actions block — measured, not
   estimated — which is a bar that fits rather than a bar that reads. Tablet
   landscape and the narrower laptops now get the accordion instead, which is
   a better control at that width anyway. 13-inch Macs report 1440 or 1512, so
   they keep the full bar.                                                   */
@media (min-width: 64em) and (max-width: 73.99em) {
  .nav--wide { display: none; }
  .menu { display: inline-flex; }
}

/* ---- The dropdown, as a warm editorial panel ---- *
   Opaque parchment, ink type, a brass hairline and a contact shadow. Not a
   white box, and nothing borrowed from Apex's red blocks. */
.navdrop {
  background: var(--surface-parchment);
  border: 1px solid var(--border-brass);
  box-shadow: 0 18px 40px -28px rgba(28, 33, 31, 0.5);
  padding: var(--s4);
  min-width: 19rem;
  border-radius: 0;
}
.navdrop__intro {
  margin: 0 0 var(--s3);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--border-subtle);
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  max-width: 34ch;
}
/* Past five links a single column becomes a scroll rather than a menu. */
/* A two-column panel needs a two-column panel's width. The base rule caps
   .navdrop at 22rem, and the wider list simply overflowed it — the second
   column's links rendered outside the parchment, on top of the hero film,
   unreadable and un-clickable-looking. The cap is raised only for panels that
   actually hold two columns, and clamped to the viewport so a trigger near
   the right edge cannot push the panel off screen. */
.navdrop:has(.navdrop__list--two) {
  /* Both bounds. Raising only the maximum let the grid compress itself back
     into the 19rem minimum and the two columns became two narrow gutters. */
  min-width: min(34rem, calc(100vw - 2rem));
  max-width: min(38rem, calc(100vw - 2rem));
}
.navdrop__list--two {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--s4);
  width: 100%;
}
/* Panels belonging to the last triggers open leftward, so they stay on screen
   at the width the two-column layout needs. */
.nav__item:nth-last-child(-n + 2) .navdrop { left: auto; right: -14px; }
.navdrop__link { min-height: 44px; display: grid; align-content: center; }
.navdrop__note { max-width: 30ch; }

/* A safe diagonal path from trigger to panel: without it the pointer crosses
   a gap and the panel closes under the cursor on its way there. */
.navdrop::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -12px;
  height: 12px;
}

@media (prefers-reduced-motion: reduce) {
  .navdrop { transition: none; }
}

/* The drawer's contact link was a 23px text target. It is a real control in a
   menu operated by thumb, so it gets a real hit area. */
.menu__contact-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ==================== The evidence library ============================= *
   Supersedes the moving trust rail. That was a marquee: cards drifted, the
   left edge clipped them mid-word, and the last row was whatever happened to
   be left over. Evidence is the one thing on this site a reader may want to
   stop and inspect, so it must not move, and it must not need a pause button
   to be readable.

   Seven records, four then three, centred as a block rather than left-packed,
   so the shorter second row sits under the middle of the first.             */
.ev {
  width: min(1240px, 100%);
  margin-inline: auto;
  padding: clamp(2rem, 4vw, 3.5rem) clamp(1.25rem, 3vw, 3rem);
  background: var(--surface-parchment);
  border: 1px solid var(--border-subtle);
}
.ev__head { max-width: 62ch; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.ev__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.5rem);
  line-height: 1.1;
  margin: 0 0 var(--s3);
  color: var(--text-primary);
}
.ev__intro { margin: 0; color: var(--text-secondary); font-size: var(--t-small); line-height: 1.6; }

/* Centred by the grid itself: `justify-content: center` on a fixed-width track
   keeps the block centred whatever the count, so a trailing row of three sits
   under the middle of four rather than against the left edge. No negative
   margins, no transforms, nothing to drift. */
/* Flex, not grid, and for one reason: a grid cannot centre an incomplete final
   row. Seven records means a row of four and a row of three, and under grid the
   three packed to the left and left a hole on the right — the unbalanced last
   row this rebuild exists to fix. Wrapping flex centres every row it produces,
   including the short one, with no placeholder cells and no offsets. */
.ev__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: var(--s4);
}
.ev__cell { flex: 0 1 15.5rem; }
/* Every card the same height, across both rows and not merely within one.
   Rows sized to content left the second row 21px shorter than the first, which
   is the sort of near-miss that reads as sloppy rather than as variation.
   Single-column mobile is excluded: matching a one-line card to the tallest in
   the set would only add dead space. */
.ev__cell { display: flex; }
.ev__cell > .ev__card { height: 100%; }

.ev__card {
  position: relative;
  display: grid;
  grid-template-rows: auto auto auto 1fr auto;
  gap: var(--s2);
  width: 100%;
  padding: var(--s5) var(--s4) var(--s4);
  background: var(--surface-ivory);
  border: 1px solid var(--border-subtle);
  text-decoration: none;
  color: var(--text-primary);
  transition:
    transform 200ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* The one piece of decoration: a fine brass rule along the top edge, which is
   what separates an evidence card from a content card without a coloured slab. */
.ev__card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: var(--accent-brass);
}
.ev__card:hover,
.ev__card:focus-visible {
  transform: translate3d(0, -3px, 0);
  border-color: var(--accent-brass);
  box-shadow: 0 12px 24px -18px rgba(28, 33, 31, 0.45);
}
.ev__card:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 3px; }

.ev__mark { display: flex; align-items: center; min-height: 34px; }
.ev__icon {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: var(--accent-brass-deep);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The supplied portal mark, used as delivered. It is flattened on white, so
   multiply drops it onto the ivory card without touching a brand colour. */
/* The portal mark was set to 22px, which put it well below the 26px line
   markers beside it — the one real logo in the set read as the smallest thing
   on the card. Matched to the marker row's optical weight instead. */
.ev__logo { height: 34px; width: auto; display: block; mix-blend-mode: multiply; }

.ev__label {
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-brass-deep);
  font-weight: 600;
}
.ev__name {
  font-family: var(--font-display);
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--text-primary);
}
.ev__blurb { font-size: 0.8125rem; line-height: 1.55; color: var(--text-secondary); }
.ev__act {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--border-subtle);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-primary);
}
.ev__arrow { color: var(--accent-brass-deep); transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1); }

/* The marker leads the movement by a fraction, so the card reads as one object
   settling rather than a box and an arrow moving independently. 40ms is below
   the threshold at which a stagger is consciously noticed and above the one at
   which it does nothing — it is felt as weight, not seen as a sequence.
   Purpose, not decoration: this card is a link to an external register, and
   the hover has to say "this opens something" more clearly than a colour
   change can on a page where everything is already warm ivory. */
.ev__mark { transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1) 40ms; }
.ev__card:hover .ev__mark,
.ev__card:focus-visible .ev__mark { transform: translate3d(0, -2px, 0); }

/* The brass rule is the card's one piece of identity, so it is what confirms
   the hover: it thickens rather than the card changing colour. */
.ev__card::before { transition: height 200ms cubic-bezier(0.4, 0, 0.2, 1); }
.ev__card:hover::before,
.ev__card:focus-visible::before { height: 3px; }
.ev__card:hover .ev__arrow,
.ev__card:focus-visible .ev__arrow { transform: translateX(4px); }

/* Tablet is two columns, and that runs to 1200 rather than 1024 — at 1024 a
   flexible basis produced three columns and left a single card alone on a
   third row, which is the unbalanced tail this rebuild is fixing. The cut
   matches the navigation's own: below 75em this is a tablet. */
@media (max-width: 74.99em) {
  .ev__cell { flex: 0 1 20rem; max-width: 20rem; }
}
@media (max-width: 47.99em) {
  .ev__grid { gap: var(--s3); }
  .ev__cell { flex: 1 1 100%; }
  .ev { padding: var(--s5) var(--s4); }
  .ev__card { padding: var(--s4); }
}
@media (prefers-reduced-motion: reduce) {
  .ev__card, .ev__arrow, .ev__mark { transition: none; }
  .ev__card:hover .ev__mark, .ev__card:focus-visible .ev__mark { transform: none; }
  .ev__card:hover, .ev__card:focus-visible { transform: none; }
  .ev__card:hover .ev__arrow, .ev__card:focus-visible .ev__arrow { transform: none; }
}


/* ---- Navigation corrections from review ---- */

/* A wrapping link left its arrow stranded: .navdrop__label was an inline-flex
   whose text wrapped internally while the arrow stayed on the flex line —
   measured 146px of gap on "Tenant fees and permitted payments" at 1440. The
   arrow belongs to the last word, so it goes back in the text flow. */
.navdrop__label { display: block; }
.navdrop__arrow { display: inline; margin-left: 8px; }
/* And the panels were sitting exactly on their 19rem floor, which is what
   forced those wraps in the first place. */
.navdrop { min-width: 21rem; }

/* "Contact" carries both .mnav__link and .mnav__link--top, and the plain-child
   rules came later at equal specificity, so the top-level item rendered
   smaller and greyer than its siblings. Scoping the child rules to the
   submenu lets the top-level styling win on its own terms. */
.menu[open] .mnav__sub .mnav__link,
.mnav__sub .mnav__link { font-size: 1rem; }
.menu[open] .mnav__link--top,
.mnav__link--top {
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--text-primary);
  min-height: 60px;
}

/* The drawer's two primary actions were pinned with margin-top:auto inside a
   scrolling column, so they sat at the bottom of the CONTENT, not the panel —
   measured off screen at 320 and 375 before any interaction, with a 169px void
   above them. Sticky keeps them on screen whatever the panel height. */
.menu[open] .menu__actions {
  margin-top: var(--s5);
  position: sticky;
  bottom: 0;
  background: var(--surface-parchment);
  padding-block: var(--s3);
  box-shadow: 0 -12px 18px -18px rgba(28, 33, 31, 0.5);
}

/* The review build packs seven groups plus two actions; at a large root font
   "Contact" overprinted the Properties button. Letting the nav shrink and the
   actions keep their intrinsic width resolves it without a new breakpoint. */
.site-head__inner { min-width: 0; }
.nav--wide { min-width: 0; }
.site-head__actions { flex: 0 0 auto; }

/* Short labels — Buy, Sell, Let — rendered 40-43px wide, under the 44px
   minimum target. Height was already right; width was not. */
.nav__link--trigger { min-width: 44px; justify-content: center; }

/* The horizontal TDS lockup, which sits with the other landscape plates
   instead of fighting them. It is a JPEG flattened on white like the rest of
   the supplied marks, so multiply drops it onto the warm surfaces without
   touching its turquoise or its navy. */
.creds__logo[src*="tds"] { max-height: 40px; max-width: 150px; object-fit: contain; }
[data-page="home"] .ev__logo[src*="tds"] {
  height: 34px;
  max-width: 130px;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/* ==========================================================================
 *  CONTACT HUB AND SEARCH HERO                        2 August 2026
 *
 *  Two components rebuilt against verified facts.
 *
 *  The contact panel used to be a definition list of five bracketed gaps —
 *  "[Business phone pending client confirmation]" and four more like it —
 *  because nothing had been confirmed. Aarav has now verified the office
 *  line, the WhatsApp number, the email address and the Instagram profile,
 *  so the panel becomes what it was always meant to be: four routes a
 *  visitor can actually use. Facebook and opening hours are still
 *  unconfirmed and are therefore absent, not greyed out and not labelled
 *  pending: a public visitor is not the audience for the build's own open
 *  questions.
 *
 *  The property hero opened on a mushroom-grey media placeholder with crop
 *  guides and a ratio badge printed on it, and put white type on that grey
 *  at a contrast nobody would have signed off. It is now a warm ivory-to-
 *  stone wash with charcoal type, and the deep-forest search module is the
 *  only saturated thing on the screen — which is the point, because it is
 *  the thing you are meant to use.
 *
 *  This block is last in the sheet on purpose. dukes.css is nine thousand
 *  lines with three generations of palette in it, and every earlier attempt
 *  to restyle either component from the middle of the file lost to a later
 *  override.
 * ========================================================================== */

:root {
  /* The brief's values, scoped to these two components rather than pushed
     into the shared palette. Repainting the site tokens would move all
     sixteen pages and invalidate every contrast pair axe has measured. */
  --contact-ivory: #f7f3ea;
  --contact-parchment: #e9dfcf;
  --contact-forest: #183a31;
  --contact-charcoal: #211f1a;
  --contact-brass: #b48745;
  /* Measured, not assumed: #b48745 is 2.9:1 on ivory, so it never carries
     text on a light surface. It is the fill, the rule and the hover edge.
     Text-weight brass is the existing deep one, 7.5:1 on ivory. */
  --contact-brass-text: var(--accent-brass-deep);
  --contact-on-forest: #f4eee3;
  --contact-on-forest-soft: rgba(244, 238, 227, 0.82);
}

/* ------------------------------ Contact hub ------------------------------ */

.contact { display: grid; gap: var(--s3); }
.contact__intro {
  margin: 0;
  font-size: var(--t-small);
  color: var(--text-secondary);
  max-width: 62ch;
}

.contact__grid {
  list-style: none;
  margin: var(--s4) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s4);
  grid-template-columns: 1fr;
}
/* Two columns from tablet up and no further. Four routes are a 2x2 at every
   size that can hold two; a third column would leave one card alone on a
   second row, which is the unbalanced tail this rebuild exists to avoid. */
@media (min-width: 40em) {
  .contact__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.contact__cell { display: flex; }

/* The card is the evidence card's material on purpose: same ivory, same
   hairline, same brass rule, same three-pixel lift. A contact route and a
   source record are both "a thing you can act on", and giving them two
   different card languages on the same page is how a site starts to look
   assembled rather than designed. */
.cmethod {
  position: relative;
  display: grid;
  grid-template-rows: auto auto auto 1fr auto;
  gap: var(--s2);
  width: 100%;
  padding: var(--s5) var(--s4) var(--s4);
  background: var(--contact-ivory);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-control);
  color: var(--contact-charcoal);
  text-decoration: none;
  transition:
    transform 200ms var(--ease-in-out),
    border-color 200ms var(--ease-in-out),
    box-shadow 200ms var(--ease-in-out);
}
.cmethod::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: var(--contact-brass);
  transition: height 200ms var(--ease-in-out);
}

.cmethod__mark {
  display: flex;
  align-items: center;
  min-height: 30px;
  transition: transform 200ms var(--ease-in-out) 40ms;
}
.cmethod__icon {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: var(--contact-charcoal);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The two platform glyphs are the official marks, drawn solid. They take the
   monochrome treatment both platforms publish rather than a brass tint,
   because recolouring somebody else's mark to match your palette is the one
   thing their guidelines actually forbid. Keeping all five marks the same
   ink also leaves brass doing one job on this page. */
.cmethod__icon--brand { fill: var(--contact-charcoal); stroke: none; }

.cmethod__label {
  font-size: var(--t-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-secondary);
}
.cmethod__value {
  font-family: var(--font-display);
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  font-weight: 600;
  line-height: 1.3;
  color: var(--contact-charcoal);
  /* "ask@dukesestate.com" is one unbreakable token in a 230px column. */
  overflow-wrap: anywhere;
}
.cmethod__blurb { font-size: var(--t-small); color: var(--text-secondary); }
.cmethod__act {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--contact-brass-text);
}
.cmethod__arrow { transition: transform 200ms var(--ease-in-out); }

/* Hover is gated so a tap on a phone does not leave a card stuck in its
   hover state. Focus gets the identical treatment plus a ring: the keyboard
   route is not the poor relation of the pointer one. */
@media (hover: hover) and (pointer: fine) {
  .cmethod:hover {
    transform: translate3d(0, -3px, 0);
    border-color: var(--contact-brass);
    box-shadow: 0 12px 24px -18px rgba(33, 31, 26, 0.45);
  }
  .cmethod:hover::before { height: 3px; }
  .cmethod:hover .cmethod__mark { transform: translate3d(0, -2px, 0); }
  .cmethod:hover .cmethod__arrow { transform: translateX(4px); }
}
.cmethod:focus-visible {
  outline: 2px solid var(--contact-brass-text);
  outline-offset: 3px;
  transform: translate3d(0, -3px, 0);
  border-color: var(--contact-brass);
  box-shadow: 0 12px 24px -18px rgba(33, 31, 26, 0.45);
}
.cmethod:focus-visible::before { height: 3px; }
.cmethod:focus-visible .cmethod__arrow { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .cmethod,
  .cmethod::before,
  .cmethod__mark,
  .cmethod__arrow { transition: none; }
  .cmethod:hover,
  .cmethod:focus-visible { transform: none; }
  .cmethod:hover .cmethod__mark,
  .cmethod:focus-visible .cmethod__mark { transform: none; }
}

/* The registered office is legal information, not a fifth way to get in
   touch, so it is a quieter row on parchment below the four cards and it
   says in its own words that nobody is sitting there waiting for you. */
.contact__legal {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s3) var(--s4);
  align-items: start;
  margin: var(--s5) 0 0;
  padding: var(--s4);
  background: var(--contact-parchment);
  border-left: 3px solid var(--contact-brass);
  /* It is a <p>, and every <p> in this sheet is capped at the reading measure.
     This one is a panel, so it takes the width of the cards above it. */
  max-width: none;
}
.contact__legal-mark { display: flex; align-items: start; }
.contact__legal-mark .cmethod__icon { width: 22px; height: 22px; stroke: var(--contact-brass-text); }
.contact__legal-body { display: grid; gap: 3px; min-width: 0; }
.contact__legal-label {
  font-size: var(--t-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--contact-brass-text);
}
.contact__legal-value { font-weight: 600; color: var(--contact-charcoal); }
.contact__legal-note { font-size: var(--t-small); color: var(--text-secondary); }

/* The closing block used to sit the contact routes in a 0.85fr column beside
   the form, which left the four cards 185px wide at 1024. The hub now spans
   the full measure and the form is centred under it. */
.closing__hub { width: 100%; }
/* The form keeps a reading measure — full-width fields at 1320px are a worse
   form — but it shares the hub's left edge rather than being centred under it,
   so the block has one alignment instead of two. */
.closing__form { width: 100%; max-width: 64rem; margin-inline: 0; }

/* --------------------------- Property search hero ------------------------- */

.hero--search {
  position: relative;
  /* Ends close to --surface-page so the hero hands over to the results band
     without a visible seam across the full width of the viewport. */
  background: linear-gradient(168deg, #fdfbf7 0%, #f6f1e6 38%, #ece2d1 78%, #f2ede3 100%);
  color: var(--contact-charcoal);
  --fg: var(--contact-charcoal);
  --fg-soft: var(--text-secondary);
  --focus-ring: var(--contact-brass-text);
  --focus-halo: rgba(180, 135, 69, 0.32);
  border-bottom: 1px solid rgba(33, 31, 26, 0.12);
}
/* Restraint over texture: two very wide, very low-opacity radials so the wash
   has a light source and a warm corner instead of reading as a flat fill. No
   image, no noise layer, nothing to download. */
.hero__wash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 78% at 86% 6%, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0) 62%),
    radial-gradient(78% 62% at 2% 100%, rgba(180, 135, 69, 0.11), rgba(180, 135, 69, 0) 70%);
}
.hero__inner--search { position: relative; padding-bottom: clamp(2.5rem, 4.5vw, 4rem); }
.hero--search .h-display,
.hero--search .h-display--sm { color: var(--contact-charcoal); }
.hero--search .hero__lede { color: var(--text-secondary); max-width: 46ch; }

/* Brass eyebrow, in the two weights the palette already distinguishes: the
   deep one carries the word at 7.5:1, the decorative one draws the rule. */
.eyebrow--rule {
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  color: var(--contact-brass-text);
}
.eyebrow--rule::after {
  content: "";
  width: clamp(2rem, 6vw, 3.5rem);
  height: 1px;
  background: var(--contact-brass);
}

/* The one saturated surface on the page. */
.hero--search .search--hero {
  margin-top: var(--s6);
  padding: clamp(1.25rem, 2.4vw, 2.25rem);
  background: var(--contact-forest);
  border-top: 3px solid var(--contact-brass);
  color: var(--contact-on-forest);
  --fg: var(--contact-on-forest);
  --fg-soft: var(--contact-on-forest-soft);
  --focus-ring: var(--contact-brass);
  --focus-halo: rgba(197, 166, 106, 0.4);
  box-shadow: 0 26px 50px -36px rgba(24, 58, 49, 0.75);
}
.hero--search .form__label,
.hero--search .search__legend { color: var(--contact-on-forest); }

/* Fields were translucent dark-on-dark. They are light warm surfaces now, so
   what you have typed is the highest-contrast thing in the module. */
.hero--search .form__control {
  min-height: 46px;
  background: var(--contact-ivory);
  border: 1px solid rgba(33, 31, 26, 0.3);
  color: var(--contact-charcoal);
}
.hero--search .form__control:hover { border-color: var(--contact-brass-text); }
.hero--search .form__control:focus-visible {
  outline: 3px solid var(--contact-brass);
  outline-offset: 2px;
  border-color: var(--contact-charcoal);
}
.hero--search .form__control option { color: var(--contact-charcoal); background: var(--contact-ivory); }

.hero--search .btn--primary {
  --btn-fill: var(--contact-brass);
  --btn-fg: var(--contact-charcoal);
  border-color: var(--contact-brass);
  color: var(--contact-charcoal);
}
.hero--search .btn--primary:hover,
.hero--search .btn--primary:focus-visible { --btn-fill: #c79a55; border-color: #c79a55; }
.hero--search .btn--quiet {
  --btn-fg: var(--contact-on-forest);
  border-color: rgba(244, 238, 227, 0.45);
  color: var(--contact-on-forest);
}
.hero--search .btn--quiet:hover,
.hero--search .btn--quiet:focus-visible { border-color: var(--accent-champagne); }
.hero--search .search__toggle { color: var(--contact-on-forest); }
.hero--search .search__note {
  margin: 0;
  max-width: 62ch;
  color: var(--contact-on-forest-soft);
  font-size: var(--t-small);
}

/* Public build: no transaction control at all, because lettings is the only
   confirmed one and a single radio is not a choice. This states the scope
   instead, and the hidden input keeps the submitted query honest. */
.search__scope {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2) var(--s3);
  margin: 0;
}
.search__scope-label {
  font-size: var(--t-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--contact-on-forest-soft);
}
.search__scope-value {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--contact-on-forest);
  border-bottom: 2px solid var(--contact-brass);
  padding-bottom: 2px;
}

/* Review build only: the sale route is visible so its shape can be judged,
   unselectable, and labelled in words rather than by colour alone. The struck
   label and the "not offered" flag both survive a greyscale screenshot; the
   dimmed control alone would not, and an unchecked disabled radio renders as a
   filled grey dot in Chromium, which reads as selected. */
.hero--search .search__radio--off { color: rgba(244, 238, 227, 0.72); }
.hero--search .search__radio--off input {
  cursor: not-allowed;
  opacity: 0.45;
}
.hero--search .search__radio--off > span:first-of-type {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
/* At 375 the two radios and the flag fought over one line and broke "For sale"
   across it. One choice per row below 30em, flag under its own control. */
@media (max-width: 30em) {
  .hero--search .search__mode { flex-direction: column; align-items: flex-start; gap: var(--s3); }
  .hero--search .search__radio { flex-wrap: wrap; }
  .hero--search .search__radio--off .search__flag { flex-basis: 100%; padding-left: 30px; }
}
.hero--search .search__flag {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent-champagne);
}

/* ---------------------- Launcher clearance, restored ---------------------- */
/* .is-stowed has existed since the launcher was built and has been inert the
   whole time. Its rule is at line ~3086; the entrance rule at ~7732 is
   [data-enhanced] .launcher[data-launcher-in="on"], which carries the same
   0-3-0 specificity and comes four thousand lines later, so it won every
   cascade and put opacity back to 1 on a control that had just asked to be
   hidden. That is why the launcher sat on top of a contact card and the
   property-type select at 320 and 375. The class does something again now.
   Stated at the end of the sheet because that is the only place in this file
   where a rule is safe. */
[data-enhanced] .launcher.is-stowed,
[data-enhanced] .launcher[data-launcher-in="on"].is-stowed {
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, 10px, 0) scale(0.96);
  pointer-events: none;
}

/* ==========================================================================
 *  REVIEWER FACES                                     2 August 2026
 *
 *  Every review card used to open with two letters in the display face. Where
 *  Aarav supplied the reviewer's own Google profile picture, the card opens
 *  with that instead. The two states are deliberately the same object — same
 *  diameter, same circle, same position — so a row containing one of each
 *  reads as one component with a photograph missing, not as two designs.
 *
 *  The photographs are the only faces on this site that are of real, named
 *  people. The two people-images on /about/ are still registered as
 *  placeholders. Keeping the reviewer portraits small and circular is what
 *  stops the page reading as though Dukes has a photographed team.
 * ========================================================================== */

.face {
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 50%;
  /* Every card that holds a face is a grid, so a face is a grid item and a grid
     item stretches to its column. The photo variants below all state an
     explicit width and height, which is what keeps them circular; the letter
     variants must not stretch either, hence justify-self.

     There was an aspect-ratio: 1 here, and it was actively harmful: display
     is blockified on a grid item, so the letter variant's width: auto became
     the full 1154px column and aspect-ratio squared it into a 1154px void.
     Sizing is stated per variant now rather than inferred. */
  justify-self: start;
}
.face__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

/* The stage card is the large, single-review presentation, so its face is the
   one that can afford to be a portrait. */
.review__initials.face {
  width: 56px;
  height: 56px;
  border: 1px solid var(--border-subtle);
  background: var(--surface-limestone);
}
.review__initials.face--letters {
  background: transparent;
  border-color: var(--border-brass);
  color: var(--accent-brass-deep);
  font-size: 1.15rem;
  letter-spacing: 0.04em;
}

/* The wall card already had a 40px circle. It keeps it; only the contents
   change. */
.rcard__initials.face { padding: 0; }
.rcard__initials.face:not(.face--letters) {
  border-color: var(--border-subtle);
  background: var(--surface-limestone);
}
[data-page="home"] .band--reviews .rcard__initials.face:not(.face--letters) {
  background: var(--surface-limestone);
  border: 1px solid var(--border-subtle);
}

/* The peek is the decorative preview of the next card. It now mirrors whatever
   that card's face is, so it needs the same circle when it holds a photograph
   and none of it when it holds letters. */
.review__peek-initials.face {
  width: 44px;
  height: 44px;
  border: 1px solid var(--border-subtle);
  background: var(--surface-limestone);
}
.review__peek-initials.face--letters {
  background: transparent;
  border-color: var(--border-brass);
  color: var(--accent-brass-deep);
  font-size: 1rem;
}

/* The /reviews/ source list. Same face component, sized for a dense list. */
.reviewlist__initials.face {
  width: 40px;
  height: 40px;
  border: 1px solid var(--border-subtle);
  background: var(--surface-limestone);
}
/* Initials keep the circle rather than collapsing to loose type. A row of
   cards where some open with a 40px disc and others with two floating letters
   is two components; this way it is one component with a photograph missing,
   and the rows stay the same height. */
.reviewlist__initials.face--letters {
  background: transparent;
  border-color: var(--border-brass);
  color: var(--accent-brass-deep);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
}

/* ==========================================================================
 *  CONTACT HUB AND SEARCH HERO — review pass                  2 August 2026
 *
 *  Changes from an independent review that measured rather than eyeballed.
 *  Each one is here rather than edited in place above, because that is the
 *  rule this sheet runs on: the last block wins.
 * ========================================================================== */

/* 1. Four across on a wide screen.
      The earlier comment justified capping at two columns because a third
      would strand one card on a second row. That is true of three columns and
      false of four. Measured at 1440 the two-column cards were 594px wide
      holding a longest text run of 277px, so half of every card was empty and
      the action hairline stretched 562px above a 77px link. Four routes in one
      row is the balanced arrangement; 2x2 stays the tablet answer. */
@media (min-width: 75em) {
  .contact__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* 2. Card padding was mobile-sized at every width. */
@media (min-width: 48em) {
  .cmethod { padding: var(--s5) var(--s5) var(--s5); }
  .contact__legal { padding: var(--s5); }
}

/* 3. The brand glyphs were optically two to three times heavier than the line
      icons. Rasterised at 104px: phone 14.8% ink in a 75px bounding box,
      envelope 19.9%, pin 17.2% — against WhatsApp 35.8% and Instagram 44.2%,
      both filling the full 103px box. Same nominal size, visibly different
      weight, alternating around a grid. Solid marks are set smaller so the
      optical sizes match; .cmethod__mark keeps its min-height so nothing
      shifts. */
.cmethod__icon--brand { width: 21px; height: 21px; }

/* 4. One measure for the whole closing block. The hub's cards and its
      parchment legal row are painted surfaces running the full width; the form
      beneath is also a painted surface, and at 1440 it stopped 181px short,
      which read as a misalignment rather than a reading measure. The form
      keeps a comfortable line length through its own two-column field grid. */
.closing__form { max-width: none; }
.closing__form .form { max-width: 64rem; }

/* 5. The initials fallback had three treatments across four blocks: brass ring
      on the stage and the source list, filled limestone disc on the wall, and
      photo faces carried a different ring colour from letter faces inside the
      same list. The whole argument for this component is that a card with a
      photograph and a card without are the same object, so they now share one
      ring and one background, and only the contents differ. */
.review__initials.face--letters,
.rcard__initials.face--letters,
.reviewlist__initials.face--letters,
.review__peek-initials.face--letters,
[data-page="home"] .band--reviews .rcard__initials.face--letters {
  background: var(--surface-limestone);
  border: 1px solid var(--border-subtle);
  color: var(--text-ink);
  font-family: var(--font-display);
  letter-spacing: 0.04em;
}
.review__initials.face--letters { font-size: 1.15rem; }
.rcard__initials.face--letters,
.reviewlist__initials.face--letters { font-size: 0.95rem; }
.review__peek-initials.face--letters { font-size: 1rem; }

/* ---------------------------- Search module ------------------------------- */

/* 6. The legend and the field labels were both 14.4px in the same colour, so
      the question outranked nothing. */
.hero--search .search__legend,
.search__scope-label {
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: none;
}

/* 7. Five fields in a two-column grid left "Sort by" alone beside a hole.
      Location spans the row, which is also the field most people use. */
@media (min-width: 48em) and (max-width: 63.99em) {
  .search--hero .search__field:first-child { grid-column: 1 / -1; }
}

/* 8. At 320 the three actions stacked as three ragged pills of 125, 133 and
      151px inside a 248px column. The primary takes the row it deserves. */
@media (max-width: 30em) {
  .search__actions { display: grid; gap: var(--s3); }
  .search__actions .btn { width: 100%; }
  .search__toggle { margin-top: var(--s2); }
}

/* The two confirmed routes now printed in the drawer and the footer. They were
   withheld until 2 August 2026 because nothing was confirmed; leaving them out
   after confirmation meant the footer implied there was no phone number while
   the contact hub printed one 900px above it. */
.menu__contact-routes,
.site-foot__routes {
  display: grid;
  gap: 2px;
  margin: 0 0 var(--s3);
  max-width: none;
}
.menu__contact-routes a,
.site-foot__routes a { justify-self: start; }

/* ==========================================================================
 *  THE CONTACT RAIL                                          2 August 2026
 *
 *  A row of four circular controls: telephone, WhatsApp, email, Instagram.
 *  Adapted from the supplied SocialTooltip React component, translated into
 *  this project's own system rather than the other way round — there is no
 *  React here, no Tailwind and no build step that would compile either.
 *
 *  Kept from the original: the circle, the fill rising from the bottom edge,
 *  the icon inverting over it, the tooltip fading up beneath, and the
 *  reduced-motion guards.
 *
 *  Changed, deliberately:
 *    * One fill colour, not four. The original painted each control in its
 *      platform's own green, pink and blue. Four saturated discs in a row is
 *      the look this palette was built to avoid, and it would put more
 *      colour in the footer than exists on the rest of the page. The fill is
 *      the site's forest; the edge is its brass.
 *    * 220ms, not 300ms, on --standard with the sheet's own easing, so the
 *      rail moves at the same speed as every other control here.
 *    * A 2px lift. The original's -translate-y-0.5 is the same idea; this
 *      states it in pixels because the rest of the sheet does.
 *    * Below the hover breakpoint the tooltip is not a tooltip. It becomes a
 *      permanent two-line caption under each control, because a label that
 *      only appears on hover is a label a touch user never reads.
 * ========================================================================== */

.crail { display: grid; gap: var(--s3); }
.crail__intro {
  margin: 0;
  font-size: var(--t-small);
  color: var(--text-secondary);
  max-width: 60ch;
}

.crail__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
}
.crail__item { position: relative; }

/* 48px: comfortably over the 44px minimum target at every width, and it stays
   48px on a phone rather than shrinking, because the phone is where these are
   most likely to be the thing somebody actually presses. */
.crail__link {
  position: relative;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--contact-ivory);
  color: var(--contact-charcoal);
  overflow: hidden;
  text-decoration: none;
  transition:
    transform var(--standard) var(--ease-in-out),
    border-color var(--standard) var(--ease-in-out),
    box-shadow var(--standard) var(--ease-in-out);
}

/* The fill rises from the bottom edge. Height rather than transform is the one
   place this sheet animates a layout property on purpose: the element is
   absolutely positioned inside an overflow-hidden circle, so it composites
   without touching the page's layout, and a scaleY would stretch the circle's
   curve into an ellipse on the way up. */
.crail__fill {
  position: absolute;
  inset: auto 0 0;
  height: 0;
  background: var(--contact-forest);
  transition: height var(--standard) var(--ease-in-out);
}

.crail__glyph { position: relative; z-index: 1; display: grid; place-items: center; }
.crail__icon {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: color var(--standard) var(--ease-in-out);
}
/* The two official marks are solid, and were measured at two to three times
   the ink of the line icons at a matched box, so they are set smaller. */
.crail__icon--brand { fill: currentColor; stroke: none; width: 18px; height: 18px; }

/* ---------------------------------- Tooltip ------------------------------- */

.crail__tip {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: 5;
  display: grid;
  gap: 1px;
  padding: var(--s2) var(--s3);
  background: var(--contact-charcoal);
  color: var(--contact-ivory);
  border-radius: var(--radius-control);
  box-shadow: 0 10px 22px -16px rgba(28, 33, 31, 0.75);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 4px);
  transition:
    opacity var(--standard) var(--ease-in-out),
    transform var(--standard) var(--ease-in-out);
}
.crail__tip-label {
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-champagne);
}
.crail__tip-value { font-size: var(--t-small); font-weight: 600; }

/* The first and last controls anchor their tooltip to their own edge instead
   of centring it, so a rail sitting hard against the page inset cannot push a
   tooltip off screen. */
.crail__item:first-child .crail__tip { left: 0; transform: translate(0, 4px); }
.crail__item:last-child .crail__tip { left: auto; right: 0; transform: translate(0, 4px); }

/* -------------------------------- States ---------------------------------- */

@media (hover: hover) and (pointer: fine) {
  .crail__link:hover {
    transform: translate3d(0, -2px, 0);
    border-color: var(--contact-brass);
    box-shadow: 0 10px 20px -14px rgba(28, 33, 31, 0.5);
  }
  .crail__link:hover .crail__fill { height: 100%; }
  .crail__link:hover { color: var(--contact-ivory); }
  .crail__item:hover .crail__tip { opacity: 1; transform: translate(-50%, 0); }
  .crail__item:first-child:hover .crail__tip,
  .crail__item:last-child:hover .crail__tip { transform: translate(0, 0); }
}

/* Focus is given the whole treatment, not a ring bolted onto a dead control. */
.crail__link:focus-visible {
  outline: 2px solid var(--accent-brass-deep);
  outline-offset: 3px;
  transform: translate3d(0, -2px, 0);
  border-color: var(--contact-brass);
  color: var(--contact-ivory);
}
.crail__link:focus-visible .crail__fill { height: 100%; }
.crail__item:focus-within .crail__tip { opacity: 1; transform: translate(-50%, 0); }
.crail__item:first-child:focus-within .crail__tip,
.crail__item:last-child:focus-within .crail__tip { transform: translate(0, 0); }

@media (prefers-reduced-motion: reduce) {
  .crail__link,
  .crail__fill,
  .crail__tip,
  .crail__icon { transition: none; }
  .crail__link:hover,
  .crail__link:focus-visible { transform: none; }
  /* The state still reads, it just arrives rather than travels. */
  .crail__item:hover .crail__tip,
  .crail__item:focus-within .crail__tip { transform: translate(-50%, 0); }
  .crail__item:first-child:hover .crail__tip,
  .crail__item:first-child:focus-within .crail__tip,
  .crail__item:last-child:hover .crail__tip,
  .crail__item:last-child:focus-within .crail__tip { transform: none; }
}

/* ------------------------------- On the dark footer ----------------------- */

.crail--dark .crail__intro { color: var(--text-on-dark-soft); }
.crail--dark .crail__link {
  background: transparent;
  border-color: var(--border-on-dark);
  color: var(--text-on-dark-warm);
}
.crail--dark .crail__fill { background: var(--accent-champagne); }
@media (hover: hover) and (pointer: fine) {
  .crail--dark .crail__link:hover {
    border-color: var(--accent-champagne);
    color: var(--contact-charcoal);
  }
}
.crail--dark .crail__link:focus-visible {
  outline-color: var(--accent-champagne);
  border-color: var(--accent-champagne);
  color: var(--contact-charcoal);
}
.crail--dark .crail__tip {
  background: var(--contact-ivory);
  color: var(--contact-charcoal);
}
.crail--dark .crail__tip-label { color: var(--accent-brass-deep); }

/* --------------------------- No hover: no tooltip ------------------------- */

/* A touch screen never fires hover, so the tooltip would be a label nobody
   reads. It stops being a tooltip and becomes the control's caption: in flow,
   permanently visible, and left-aligned under its own icon. The rail becomes a
   column so four captions cannot collide or run off the side. */
@media (hover: none), (max-width: 47.99em) {
  .crail__list { display: grid; gap: var(--s3); }
  .crail__item { display: flex; align-items: center; gap: var(--s4); min-height: 48px; }
  .crail__tip {
    position: static;
    display: grid;
    gap: 0;
    padding: 0;
    background: none;
    box-shadow: none;
    opacity: 1;
    transform: none;
    white-space: normal;
    min-width: 0;
    color: inherit;
  }
  .crail__item:first-child .crail__tip,
  .crail__item:last-child .crail__tip { left: auto; right: auto; transform: none; }
  .crail__tip-label { color: var(--text-secondary); }
  .crail__tip-value { color: var(--contact-charcoal); overflow-wrap: anywhere; }
  .crail--dark .crail__tip-label { color: var(--text-on-dark-soft); }
  .crail--dark .crail__tip-value { color: var(--text-on-dark-warm); }
}

/* Two columns of caption rows once there is room for them, before the hover
   breakpoint takes over. */
@media (hover: none) and (min-width: 34em) {
  .crail__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --------------------------- The labelled variant ------------------------- *
   The contact section shows the route and its value permanently. Same control,
   same circle, same fill and lift — the tooltip simply stops being a tooltip
   and becomes the caption beside it, which is exactly what the no-hover rules
   above already do for touch. Stated as a class so the presentation is chosen
   by where the rail is used, not only by what the device can do.            */
.crail--labelled .crail__list {
  display: grid;
  gap: var(--s4) var(--s5);
}
.crail--labelled .crail__item {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: 48px;
}
.crail--labelled .crail__tip {
  position: static;
  display: grid;
  gap: 0;
  padding: 0;
  background: none;
  box-shadow: none;
  opacity: 1;
  transform: none;
  white-space: normal;
  pointer-events: auto;
  color: inherit;
}
.crail--labelled .crail__item:first-child .crail__tip,
.crail--labelled .crail__item:last-child .crail__tip {
  left: auto;
  right: auto;
  transform: none;
}
.crail--labelled .crail__tip-label {
  color: var(--text-secondary);
  font-size: 0.6875rem;
}
.crail--labelled .crail__tip-value {
  color: var(--contact-charcoal);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  overflow-wrap: anywhere;
}
/* Two by two once there is room, four across on a wide screen: the same
   rhythm the card hub uses, so the two contact presentations on this site
   are recognisably the same family. */
@media (min-width: 40em) {
  .crail--labelled .crail__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 75em) {
  .crail--labelled .crail__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* The closing block is plain flow, so its children need their own separation:
   the rail was sitting directly on the enquiry form's top rule, and in the
   footer it was touching the "Registered office" label. */
.closing__hub { margin-bottom: var(--s7); }
.site-foot__contact .crail { margin-bottom: var(--s4); }

/* Tooltip containment.
   Centring on the control and anchoring the last one to its own right edge
   both fail the same way: the anchor is the control, and a control near the
   left of the viewport has no room to its left whatever you anchor to. At
   1024 the footer's Instagram tooltip measured -103px, i.e. a hundred pixels
   off the left of the screen. Every tooltip now opens from its control's LEFT
   edge and is capped to the viewport, so its left edge can never be further
   left than the control itself — and the control is already inside the page
   inset. Both rails on this site are left-aligned, so nothing can push the
   right edge out either. */
.crail__tip,
.crail__item:first-child .crail__tip,
.crail__item:last-child .crail__tip {
  left: 0;
  right: auto;
  transform: translate(0, 4px);
  max-width: min(18rem, calc(100vw - 2 * var(--inset)));
  white-space: normal;
}
.crail__item:hover .crail__tip,
.crail__item:focus-within .crail__tip,
.crail__item:first-child:hover .crail__tip,
.crail__item:first-child:focus-within .crail__tip,
.crail__item:last-child:hover .crail__tip,
.crail__item:last-child:focus-within .crail__tip {
  transform: translate(0, 0);
}
@media (prefers-reduced-motion: reduce) {
  .crail__item:hover .crail__tip,
  .crail__item:focus-within .crail__tip { transform: none; }
}
/* The labelled variant has no tooltip to contain — it is a caption in flow. */
.crail--labelled .crail__tip { max-width: none; }

/* ==========================================================================
 *  REAL LISTINGS: RESULT CARDS AND THE GALLERY          2 August 2026
 *
 *  Two properties with real photographs now sit at the top of the search
 *  results, above the demonstration records. The card treatment is the same
 *  card; only the media well changes, because a card that shows a photograph
 *  and a card that shows a placeholder should still be the same object.
 * ========================================================================== */

.prop__shot {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--surface-limestone);
  border-radius: var(--radius-control);
  aspect-ratio: 3 / 2;
}
.prop__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 320ms var(--ease-in-out);
}
/* The whole card is already a link through its title. The photograph lifts
   very slightly on hover so the card reads as one target, and nothing moves
   for a reader who has asked for less motion. */
@media (hover: hover) and (pointer: fine) {
  .prop:hover .prop__shot img { transform: scale(1.02); }
}
@media (prefers-reduced-motion: reduce) {
  .prop__shot img { transition: none; }
  .prop:hover .prop__shot img { transform: none; }
}

/* The photo count and the status stamp sit on the image, so both carry their
   own solid backing rather than relying on whatever the photograph happens to
   be behind them. */
.prop__count,
.prop__stamp {
  position: absolute;
  bottom: var(--s3);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 4px 8px;
  border-radius: var(--radius-control);
}
.prop__count {
  left: var(--s3);
  background: rgba(28, 33, 31, 0.82);
  color: var(--contact-ivory);
}
.prop__stamp {
  right: var(--s3);
  background: var(--contact-brass);
  color: var(--contact-charcoal);
}

.prop__status--open { color: var(--accent-brass-deep); font-weight: 700; }
.prop__status--closed { color: var(--text-secondary); font-weight: 700; }

/* A let-agreed property gets a panel where the viewing button would be, so the
   absence of that button is stated rather than merely felt. */
.listing__closed {
  margin: var(--s5) 0 0;
  padding: var(--s4) var(--s5);
  background: var(--contact-parchment);
  border-left: 3px solid var(--contact-brass);
}
.listing__closed-lead { margin: 0 0 var(--s3); font-weight: 700; color: var(--contact-charcoal); }
.listing__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4);
  margin: var(--s5) 0 0;
  max-width: none;
}
.listing__closed .listing__actions { margin-top: 0; }

/* -------------------------------- Gallery -------------------------------- */

.gal { display: grid; gap: var(--s4); }
.gal__stage {
  margin: 0;
  background: var(--surface-limestone);
  border-radius: var(--radius-control);
  overflow: hidden;
}
.gal__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.gal__caption {
  padding: var(--s3) var(--s4);
  font-size: var(--t-small);
  color: var(--text-secondary);
  background: var(--surface-ivory);
}
.gal__pos {
  margin: 0;
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-secondary);
}

/* A scrolling strip rather than a wrapping grid: seventeen thumbnails in a
   grid would be taller than the photograph they belong to. */
.gal__thumbs {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--s2);
  display: flex;
  gap: var(--s3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.gal__thumb { flex: 0 0 auto; scroll-snap-align: start; }
.gal__btn {
  display: block;
  padding: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-control);
  background: none;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
  transition: border-color var(--standard) var(--ease-in-out), transform var(--standard) var(--ease-in-out);
}
.gal__btn img { display: block; width: 120px; height: 90px; object-fit: cover; }
.gal__btn:hover { border-color: var(--contact-brass); }
.gal__btn:focus-visible { outline: 2px solid var(--accent-brass-deep); outline-offset: 2px; }
/* The chosen photograph is marked by a brass edge AND a change of opacity in
   the others, so the state does not rest on colour alone. */
.gal__btn[aria-pressed="true"] {
  border-color: var(--contact-brass);
  border-width: 2px;
  transform: translate3d(0, -2px, 0);
}
.gal__thumbs:has(.gal__btn[aria-pressed="true"]) .gal__btn[aria-pressed="false"] { opacity: 0.72; }
@media (prefers-reduced-motion: reduce) {
  .gal__btn { transition: none; }
  .gal__btn[aria-pressed="true"] { transform: none; }
}

.gal__all { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s4); }
.gal__all img { display: block; width: 100%; height: auto; border-radius: var(--radius-control); }

@media (min-width: 64em) {
  .gal { grid-template-columns: minmax(0, 1fr) 150px; grid-template-areas: "stage thumbs" "pos thumbs"; align-items: start; }
  .gal__stage { grid-area: stage; }
  .gal__pos { grid-area: pos; }
  /* Beside the photograph the strip runs vertically, which is where seventeen
     thumbnails stop being a scroll and start being a contact sheet. */
  .gal__thumbs {
    grid-area: thumbs;
    flex-direction: column;
    overflow-x: visible;
    overflow-y: auto;
    max-height: 30rem;
    padding: 2px;
  }
  .gal__btn img { width: 130px; height: 98px; }
}

/* The thumbnail column scrolls, and a hard cut through the middle of a
   photograph reads as a layout fault rather than as "there is more below".
   The same edge fade the review rail uses, for the same reason. */
@media (min-width: 64em) {
  .gal__thumbs {
    -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 2.5rem), transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 2.5rem), transparent 100%);
  }
  /* A strip short enough to fit needs no fade and should not get one. */
  .gal__thumbs:not(:hover) { scrollbar-width: thin; }
}

/* The thumbnail strip is a flex row inside a grid, and a grid item's default
   min-width is auto — so seventeen thumbnails pushed the grid column to
   2210px and took the whole page with them: 1903px of horizontal overflow at
   320. The strip has always had overflow-x:auto; it just was never allowed to
   be narrower than its contents. */
.gal { grid-template-columns: minmax(0, 1fr); }
.gal__thumbs { min-width: 0; }
@media (min-width: 64em) {
  .gal { grid-template-columns: minmax(0, 1fr) 150px; }
}

/* The thumbnail strip was scrolling internally exactly as intended — 288px
   wide over 2268px of content — and STILL adding 1903px to the document's
   scroll width, so the whole page could be dragged sideways at 320. Neither
   min-width:0, nor overflow:hidden on any ancestor, nor width caps changed it;
   the scroll container's overflow was propagating to the root scroller
   regardless. Paint containment is what actually stops it, verified by
   measurement rather than by reasoning: with it the document is back to 320
   and window.scrollX stays 0, while the strip still scrolls.

   The padding is load-bearing with it: containment clips to the padding box,
   and without room the 2px focus ring on the first and last thumbnail would be
   clipped by the very thing fixing the overflow. */
.gal__thumbs {
  contain: paint;
  padding: 4px;
}

/* Snap and the focus-ring padding fight each other: the browser rested the
   strip at scrollLeft:4 to align the first thumbnail's snap edge, which put
   that thumbnail's focus ring back under the containment clip. Snapping 90px
   thumbnails buys very little; a visible focus ring on the first one is not
   optional. */
.gal__thumbs { scroll-snap-type: none; }
.gal__thumb { scroll-snap-align: none; }

/* ==========================================================================
 *  DIRECT CONTACT                                          2 August 2026
 *
 *  The SocialTooltip interaction, adapted to the Dukes contact section rather
 *  than pasted into it. What survives from the reference: a colour surface
 *  rising from the bottom edge on hover and focus, the mark lifting slightly,
 *  and the content inverting over the fill. What changed:
 *
 *    * The fill covers the whole tile, not a 48px disc, because here the tile
 *      IS the control — the number is meant to be readable before anyone
 *      interacts, so the medallion is not doing the work on its own.
 *    * Channel colour is used at the depth this palette runs at. WhatsApp's
 *      own green and Instagram's own gradient at full saturation would put
 *      two internet-brand blocks in the middle of an ivory editorial page.
 *      Each fill is the channel's colour taken down to Dukes' register: every
 *      one of the four measures at least 6.8:1 against the ivory type that
 *      lands on it, which is what lets the text inversion be safe rather than
 *      hopeful.
 *    * No shadow, no scale, no bounce. 400ms on the reference's own easing.
 * ========================================================================== */

.dc { display: grid; gap: var(--s5); }

/* Editorial two-column: the statement on the left, the routes on the right.
   Single column until there is genuinely room for both. */
@media (min-width: 64em) {
  .dc {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    gap: clamp(2.5rem, 4vw, 4.5rem);
    align-items: start;
  }
  .dc__intro { position: sticky; top: 6.5rem; }
  .dc__grid { margin: 0; }
  .contact__legal { grid-column: 1 / -1; }
}

.dc__intro { display: grid; gap: var(--s3); }
.dc__eyebrow {
  margin: 0;
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--accent-brass-deep);
}
.dc__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--contact-charcoal);
}
.dc__copy {
  margin: 0;
  color: var(--text-secondary);
  max-width: 34ch;
}

/* ---------------------------------- Grid ---------------------------------- */

.dc__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s4);
  grid-template-columns: 1fr;
}
@media (min-width: 34em) {
  .dc__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.dc__cell { display: flex; }

/* ---------------------------------- Tile ---------------------------------- */

.dc__tile {
  --dc-fill: var(--contact-charcoal);
  --dc-on-fill: var(--contact-ivory);

  position: relative;
  isolation: isolate;
  display: block;
  width: 100%;
  min-height: 108px;
  padding: 0;
  overflow: hidden;
  text-decoration: none;
  color: var(--contact-charcoal);
  background: var(--contact-ivory);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-control);
  transition: border-color 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* The rising surface. Height rather than transform: the tile clips it, so it
   composites inside its own box, and scaleY would smear the gradient on the
   Instagram tile as it grew. */
.dc__fill {
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  height: 0;
  background: var(--dc-fill);
  transition: height 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

.dc__body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4) var(--s5) var(--s4) var(--s4);
  min-height: 108px;
}

.dc__mark {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border-brass);
  color: var(--contact-charcoal);
  transition:
    transform 400ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 400ms cubic-bezier(0.22, 1, 0.36, 1),
    color 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.dc__icon {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dc__icon--brand { fill: currentColor; stroke: none; width: 18px; height: 18px; }

.dc__lines { display: grid; gap: 3px; min-width: 0; }
.dc__label {
  font-size: var(--t-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-secondary);
  transition: color 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.dc__value {
  font-family: var(--font-display);
  font-size: clamp(1rem, 0.95rem + 0.25vw, 1.1875rem);
  font-weight: 600;
  line-height: 1.25;
  /* ask@dukesestate.com and @dukes_estate_agency are single unbreakable
     tokens; without this they push the arrow out of the tile. */
  overflow-wrap: anywhere;
  transition: color 400ms cubic-bezier(0.22, 1, 0.36, 1);
}
.dc__arrow {
  align-self: center;
  color: var(--accent-brass-deep);
  transition:
    transform 400ms cubic-bezier(0.22, 1, 0.36, 1),
    color 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ------------------------------ Channel fills ----------------------------- *
   Measured against --contact-ivory (#f7f3ea), which is what lands on them:
     phone      #211f1a  14.9:1
     whatsapp   #075e54   6.9:1   (WhatsApp's dark teal, not its bright green)
     email      #43301c  11.3:1
     instagram  #5b2545 → #8c3a28, lightest point 6.9:1                       */
.dc__tile--phone { --dc-fill: #211f1a; }
.dc__tile--whatsapp { --dc-fill: #075e54; }
.dc__tile--email { --dc-fill: #43301c; }
.dc__tile--instagram { --dc-fill: linear-gradient(135deg, #5b2545 0%, #7a2f39 55%, #8c3a28 100%); }

/* --------------------------------- States --------------------------------- */

.dc__tile:hover,
.dc__tile:focus-visible { border-color: var(--contact-brass); }
.dc__tile:hover .dc__fill,
.dc__tile:focus-visible .dc__fill { height: 100%; }

.dc__tile:hover .dc__value,
.dc__tile:focus-visible .dc__value { color: var(--dc-on-fill); }
.dc__tile:hover .dc__label,
.dc__tile:focus-visible .dc__label { color: rgba(247, 243, 234, 0.82); }
.dc__tile:hover .dc__arrow,
.dc__tile:focus-visible .dc__arrow {
  color: var(--accent-champagne);
  transform: translateX(3px);
}
.dc__tile:hover .dc__mark,
.dc__tile:focus-visible .dc__mark {
  transform: translateY(-2px);
  border-color: var(--accent-champagne);
  color: var(--dc-on-fill);
}

.dc__tile:focus-visible {
  outline: 2px solid var(--accent-brass-deep);
  outline-offset: 3px;
}

/* Touch has no hover: the fill would either never run or stick after a tap.
   The tile is fully readable at rest, so nothing is lost by leaving it there. */
@media (hover: none) {
  .dc__tile:hover .dc__fill { height: 0; }
  .dc__tile:hover .dc__value,
  .dc__tile:hover .dc__label { color: inherit; }
  .dc__tile:hover .dc__mark { transform: none; color: var(--contact-charcoal); }
  .dc__tile:hover .dc__arrow { transform: none; color: var(--accent-brass-deep); }
  .dc__tile:hover .dc__label { color: var(--text-secondary); }
}

/* Reduced motion keeps the state change and drops the travel: the surface
   arrives rather than rises, and nothing moves. */
@media (prefers-reduced-motion: reduce) {
  .dc__tile,
  .dc__fill,
  .dc__mark,
  .dc__arrow,
  .dc__label,
  .dc__value { transition-duration: 1ms; }
  .dc__tile:hover .dc__mark,
  .dc__tile:focus-visible .dc__mark { transform: none; }
  .dc__tile:hover .dc__arrow,
  .dc__tile:focus-visible .dc__arrow { transform: none; }
}

/* ---------------------- Direct contact: correction pass -------------------- *
   Three things were wrong once this was on a real page at a real width.

   1. The value column measured 125px, so ask@dukesestate.com and
      @dukes_estate_agency each broke onto two lines mid-word and left the
      tiles at two different heights. The intro column was taking too much of
      the row and the medallion and gaps took most of what was left.
   2. Four bordered boxes sat on the ivory as four objects. Hairline rules
      between cells is the treatment the rest of this page already uses, and
      it lets the fill be the only thing that ever draws a shape.
   3. At 400ms in both directions, dragging the pointer across the grid left a
      visible colour bar trailing behind on every tile just left. The rise is
      the deliberate moment; the retreat should get out of the way.           */

@media (min-width: 64em) {
  /* Was 0.82fr / 1.18fr. The routes are the working part of this section. */
  .dc { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.38fr); }
}

/* Hairlines, not boxes. One rule between the columns and one between the
   rows, drawn on the grid rather than around each cell, so no cell carries a
   border the fill then has to sit inside. */
.dc__grid { gap: 0; border-top: 1px solid var(--border-subtle); }
.dc__cell { border-bottom: 1px solid var(--border-subtle); }
@media (min-width: 34em) {
  .dc__cell:nth-child(odd) { border-right: 1px solid var(--border-subtle); }
}

.dc__tile {
  border: 0;
  border-radius: 0;
  background: transparent;
  min-height: 96px;
}
.dc__body {
  min-height: 96px;
  gap: var(--s3);
  padding: var(--s4);
}
.dc__mark { width: 40px; height: 40px; }
.dc__value {
  /* One line is the requirement; anywhere-breaking is the fallback of last
     resort, not the default. */
  font-size: clamp(0.9375rem, 0.88rem + 0.22vw, 1.0625rem);
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}
.dc__label { font-size: 0.6875rem; letter-spacing: 0.14em; }

/* The tile draws no border, so hover marks itself with the fill and the mark
   alone. */
.dc__tile:hover,
.dc__tile:focus-visible { border-color: transparent; }

/* Rise deliberately, retreat quickly. */
.dc__fill { transition-duration: 420ms; }
.dc__tile:not(:hover):not(:focus-visible) .dc__fill { transition-duration: 130ms; }
@media (prefers-reduced-motion: reduce) {
  .dc__tile:not(:hover):not(:focus-visible) .dc__fill { transition-duration: 1ms; }
}

/* The rail is the version that appears on every page, and it was filling
   forest for all four routes while the contact page's tiles filled in each
   channel's own colour. Two treatments of one component reads as two
   components. Same four colours, same measured contrast against the ivory
   that lands on them. */
.crail__link--phone { --crail-fill: #211f1a; }
.crail__link--whatsapp { --crail-fill: #075e54; }
.crail__link--email { --crail-fill: #43301c; }
.crail__link--instagram { --crail-fill: linear-gradient(135deg, #5b2545 0%, #7a2f39 55%, #8c3a28 100%); }
.crail__fill { background: var(--crail-fill, var(--contact-forest)); }
/* On the footer's parchment the champagne fill was the odd one out for the
   same reason; the channel colours replace it there too. */
.crail--dark .crail__fill { background: var(--crail-fill, var(--accent-champagne)); }

/* ------------------- Direct contact: Safari overlap + email ---------------- */

/* The intro column was position:sticky inside the grid. In WebKit it escaped
   its grid area and rode down over the Registered Office panel, printing the
   heading straight through the address. Aarav caught it in Safari. Sticky was
   a nicety on one section; a heading overlapping an address is a defect, so
   the nicety loses. */
@media (min-width: 64em) {
  .dc__intro { position: static; top: auto; }
}

/* Email was bronze, which sat too close to the telephone tile's ink and read
   as the odd one of the four. A deep petrol blue is the professional register
   this palette can carry: 10.8:1 against the ivory type that lands on it, and
   deliberately NOT --brand-navy (#0b223b), which is the logo's protected
   signature and does not get spent on a UI surface. */
.dc__tile--email { --dc-fill: #1e3a47; }
.crail__link--email { --crail-fill: #1e3a47; }
