/* SAKVIRE — one-pager v3 · rotating hero + standard sections */

@font-face {
  font-family: "Mersad";
  src: url("fonts/mersad-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Mersad";
  src: url("fonts/mersad-700.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Mersad";
  src: url("fonts/mersad-900.woff2") format("woff2");
  font-weight: 900;
  font-display: swap;
}
@font-face {
  font-family: "FiraGO";
  src: url("fonts/firago-latin-400-normal.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "FiraGO";
  src: url("fonts/firago-latin-500-normal.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Plex Mono";
  src: url("fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --cream: #f3ece0;
  --ink: #241f1b;
  --night: #0c0b09;
  --pine: #2b4436;
  --terracotta: #c8563c;
  /* audit Medium 1: terracotta-on-cream was 3.686:1, short of AA's 4.5:1 for
     normal text. terracotta-text (4.68:1 on cream) covers small/normal text;
     terracotta-deep (4.54:1 under cream text) covers cream-on-fill buttons.
     Large display text (>=24px) and purely decorative fills/borders stay on
     the brand --terracotta itself - see usage sites for the reasoning. */
  --terracotta-text: #af4931;
  --terracotta-deep: #b34a32;
  --gold: #c8a96e;
  color-scheme: dark;

  /* layout grid: one column + a 5-step spacing rhythm (art-director pass) */
  --col: min(72rem, 92vw);
  --sp-1: 0.6rem;
  --sp-2: 1.2rem;
  --sp-3: 2rem;
  --sp-4: 3.2rem;
  --sp-5: clamp(4.5rem, 12svh, 9rem);
}

* {
  box-sizing: border-box;
  margin: 0;
}

html {
  scroll-behavior: smooth;
  overflow-x: clip;
  scroll-padding-top: 5rem;
}

body {
  /* Every section owns its surface; cream is the fail-safe for any interstitial
     pixel so scroll position can never expose a stale scene colour. */
  background: var(--cream);
  transition: none;
  color: var(--cream);
  font-family: "FiraGO", system-ui, sans-serif;
  overflow-x: hidden;
}

.skip-link {
  position: fixed;
  z-index: 100;
  top: 0.75rem;
  left: 0.75rem;
  transform: translateY(-180%);
  padding: 0.75rem 1rem;
  border-radius: 999px;
  color: var(--cream);
  background: var(--ink);
  text-decoration: none;
  transition: transform 0.2s ease;
}
.skip-link:focus {
  transform: translateY(0);
}

:where(a, button, input, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

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

.site-head {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem clamp(1.2rem, 4vw, 3rem);
  transition:
    background 0.5s ease,
    backdrop-filter 0.5s ease;
}
.site-head.scrolled {
  background: rgba(12, 11, 9, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.brand {
  display: flex;
  align-items: center;
  text-decoration: none;
}
.brand-word {
  width: clamp(140px, 12vw, 180px);
  height: auto;
  display: block;
  /* terracotta wordmark lifted to cream for dark scenes */
  filter: brightness(0) saturate(100%) invert(94%) sepia(9%) saturate(430%)
    hue-rotate(357deg) brightness(103%);
}
.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2.4vw, 2rem);
}
.site-nav a {
  font-weight: 500;
  font-family: "FiraGO", sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(243, 236, 224, 0.78);
  text-decoration: none;
  transition: color 0.25s;
}
.site-nav a.current:not(.cta) {
  color: var(--cream);
}
.site-nav a.cta {
  color: var(--cream);
  /* audit Medium 1: cream text on fill needs 4.5:1 */
  background: var(--terracotta-deep);
  padding: 0.55em 1.1em;
  border-radius: 999px;
}
/* language switcher: Georgian label on the EN page (and vice versa) - never
   uppercase it, Mkhedruli has no case and the transform would fall back to
   system-font Mtavruli */
.site-nav a.lang-switch {
  padding-left: clamp(0.9rem, 2.4vw, 2rem);
  border-left: 1px solid rgba(243, 236, 224, 0.28);
  text-transform: none;
  letter-spacing: 0.08em;
}
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  background: none;
  border: 0;
  padding: 0.55rem;
  cursor: pointer;
}
.nav-toggle span {
  width: 22px;
  height: 2px;
  background: var(--cream);
  transition:
    transform 0.25s ease,
    opacity 0.25s ease;
}
.site-head.nav-open .nav-toggle span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.site-head.nav-open .nav-toggle span:nth-child(2) {
  opacity: 0;
}
.site-head.nav-open .nav-toggle span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

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

.hero {
  position: relative;
  height: 100svh;
  isolation: isolate;
  overflow: hidden;
}
.hero-films video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
  opacity: 0;
  transition: opacity 1s ease;
  background: #000;
}
.hero-films video.active {
  opacity: 1;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    to top,
    rgba(8, 7, 5, 0.82) 0%,
    rgba(8, 7, 5, 0.28) 38%,
    rgba(8, 7, 5, 0.12) 70%,
    rgba(8, 7, 5, 0.35) 100%
  );
  pointer-events: none;
}
.hero-copy {
  position: absolute;
  z-index: 1;
  left: 50%;
  transform: translateX(-50%);
  width: var(--col);
  bottom: clamp(6rem, 16svh, 10rem);
}
.hero-copy h1 {
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: clamp(2.4rem, 6vw, 5.4rem);
  line-height: 1.03;
  color: var(--cream);
  text-wrap: balance;
}
.hero-sub {
  margin-top: 1.2rem;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  color: rgba(243, 236, 224, 0.82);
  max-width: 36rem;
}
.hero-cta {
  display: inline-block;
  margin-top: 1.8rem;
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cream);
  /* audit Medium 1: cream text on fill needs 4.5:1 */
  background: var(--terracotta-deep);
  padding: 0.9em 1.7em;
  border-radius: 999px;
  transition: background 0.25s;
}
.hero-cta:hover {
  background: var(--cream);
  color: var(--night);
}
.hero-tabs {
  position: absolute;
  z-index: 1;
  left: 50%;
  transform: translateX(-50%);
  width: var(--col);
  bottom: clamp(1.6rem, 5svh, 3rem);
  display: flex;
  flex-wrap: wrap; /* audit High 1: nowrap pushed the last tab off-screen at 200% text */
  gap: 1.6rem;
}
.hero-tabs button {
  appearance: none;
  background: none;
  border: none;
  padding: 0.4em 0;
  font-weight: 500;
  font-family: "FiraGO", sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(243, 236, 224, 0.55);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition:
    color 0.3s,
    border-color 0.3s;
}
.hero-tabs button:hover {
  color: var(--cream);
}
.hero-tabs button.active {
  color: var(--cream);
  border-bottom-color: var(--terracotta);
}

/* ---------- generic scene / reveal ---------- */

.scene {
  position: relative;
}
.cap,
.page-inner {
  opacity: 1;
  transform: none;
  transition: none;
}
.scene.inview .cap,
.scene.inview .page-inner {
  opacity: 1;
  transform: none;
}

.eyebrow {
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: clamp(0.68rem, 1.1vw, 0.82rem);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--terracotta-text);
  margin-bottom: var(--sp-2);
}

/* two-tone headline accents (deck-style mixed lines) */
.page-title em,
.statement em,
.row-text h3 em {
  font-style: normal;
  color: var(--terracotta-text);
}
.scene.page.dark .page-title em,
.scene.page.dark .row-text h3 em {
  color: #d98b6f;
}

/* ---------- functional pages ---------- */

.scene.page {
  color: var(--ink);
  background: var(--cream);
  display: grid;
  place-items: center;
  padding: var(--sp-5) 0;
}
.scene.page.dark {
  color: var(--cream);
  background: var(--pine);
}
/* the day theater drives its own sky inline */
.day-theater-section {
  background: transparent;
}
.scene.page.dark .eyebrow {
  color: var(--gold);
}
.page .eyebrow::after {
  content: "";
  display: block;
  width: 2.6rem;
  height: 2px;
  background: var(--terracotta);
  margin-top: 0.65rem;
}
.scene.page.dark .page .eyebrow::after,
.scene.page.dark .eyebrow::after {
  background: var(--terracotta);
}
.page-inner {
  width: var(--col);
}
.page-title {
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: clamp(2rem, 4.6vw, 3.8rem);
  line-height: 1.05;
  margin-bottom: var(--sp-2);
  text-wrap: balance;
  color: var(--ink);
  /* audit High 1: at 200% text, text-wrap:balance stopped soft-wrapping the
     nested <em> on the KA page (Chromium quirk, confirmed on the live page -
     the em's own word-space break opportunity was ignored); break-word is the
     forcing fallback so the emphasised phrase wraps instead of running off. */
  overflow-wrap: break-word;
}
.page-lead {
  max-width: 42rem;
  font-size: clamp(1rem, 1.5vw, 1.2rem);
  line-height: 1.6;
  color: rgba(36, 31, 27, 0.78);
}
.scene.page.dark .page-lead {
  color: rgba(243, 236, 224, 0.78);
}
.page-lead.centered {
  margin-inline: auto;
}

.scene.page.thesis {
  background: var(--cream);
  padding: clamp(4.5rem, 10svh, 7rem) 0;
}
.thesis .page-inner {
  display: block;
  min-height: 0;
}
.thesis .statement {
  max-width: 60rem;
  font-size: clamp(2.3rem, 4.8vw, 4.5rem);
}
.thesis .page-inner,
.thesis .statement,
.thesis .page-lead {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  animation: none !important;
}
/* restored pre-band palette: quiet cream field, ink lead, terracotta thesis */
.scene.page.thesis .statement em {
  color: var(--terracotta-text);
}

.thesis .page-lead {
  max-width: 52rem;
  color: rgba(36, 31, 27, 0.78);
  opacity: 1;
  transform: none;
  transition: none;
}
.thesis-image {
  width: 100%;
  margin: clamp(2rem, 5svh, 3.5rem) 0 0;
}
.thesis-image img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  border-radius: 12px;
  box-shadow: 0 30px 80px -30px rgba(36, 31, 27, 0.4);
}
.thesis.inview .page-lead {
  opacity: 1;
  transform: none;
}
.statement {
  font-family: "Mersad", sans-serif;
  font-weight: 900;
  font-size: clamp(2.2rem, 6vw, 5rem);
  line-height: 1.05;
  color: var(--cream);
  margin-bottom: 1.4rem;
  text-wrap: balance;
  overflow-wrap: break-word; /* audit High 1 - see .page-title */
}
.statement.dark {
  color: var(--ink);
}

/* ---------- surveyor's seam (thesis -> land chapter break) ---------- */

.survey-seam {
  width: min(72rem, 92vw);
  margin-inline: auto;
  margin-block: 0;
  padding-block: clamp(1rem, 4svh, 2.5rem);
  background: var(--cream);
  box-shadow: 0 0 0 100vmax var(--cream);
  clip-path: inset(0 -100vmax);
  display: flex;
  align-items: center;
  gap: 1rem;
}
.seam-line {
  flex: 1;
  height: 1px;
}
.seam-line--l {
  background: linear-gradient(90deg, transparent, rgba(200, 86, 60, 0.5));
}
.seam-line--r {
  background: linear-gradient(90deg, rgba(200, 86, 60, 0.5), transparent);
}
.seam-mark {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--terracotta);
  opacity: 0.85;
}

/* numbered chapter sections sit between seams, so they carry less of their
   own top/bottom padding - the seams supply the breathing room */
.scene.page.chapter {
  padding-top: clamp(1.5rem, 4svh, 3rem);
  padding-bottom: clamp(1.5rem, 4svh, 3rem);
}

/* chapter index on The Land eyebrow */
.eyebrow .ch-index {
  font-family: "Plex Mono", monospace;
  margin-left: 0.7rem;
  color: var(--terracotta-text);
  letter-spacing: 0.15em;
}
.eyebrow .ch-index::before {
  content: "·";
  margin-right: 0.7rem;
  color: rgba(36, 31, 27, 0.3);
}
.scene.page.dark .eyebrow .ch-index {
  color: var(--gold);
}
.scene.page.dark .eyebrow .ch-index::before {
  color: var(--gold);
}

/* ---------- land ---------- */

#land .facts {
  margin: 0 0 var(--sp-4);
}

.survey-figure {
  /* breakout: the plate leaves the text column and spans the viewport */
  margin: 2.6rem 0 0 calc(50% - 50vw);
  width: 100vw;
}

/* live plate: animated video + registered SVG survey on top */
.survey-live {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #1c2416;
  /* pinch/zoom is handled in JS; keep vertical page scroll alive at 1x */
  touch-action: pan-y;
}
.survey-zoom {
  position: absolute;
  inset: 0;
  will-change: transform;
  transform-origin: center;
}
.survey-live video,
.survey-live img.survey-plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* legend card: overlaid bottom-left of the plate, opposite the "hover a
   plot" hint (bottom-right) - a compact, readable card over the imagery */
.survey-legend-card {
  position: absolute;
  z-index: 2;
  left: clamp(1rem, 3vw, 2.4rem);
  bottom: clamp(1rem, 3vw, 2.4rem);
  max-width: min(19rem, 58vw);
  padding: 0.85em 1.05em;
  background: rgba(243, 236, 224, 0.9);
  border: 1px solid rgba(36, 31, 27, 0.16);
  border-radius: 10px;
  box-shadow: 0 8px 30px -8px rgba(8, 7, 5, 0.6);
}
.survey-overlay-host,
.survey-overlay-host svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* Let the aerial remain visible through roads on every browser/GPU.
   The ink geometry supplies the perimeter; the former sand layer is removed.
   The access road keeps a translucent inner deck over its dark casing. */
.survey-overlay .roads-ink {
  fill: rgba(243, 236, 224, 0.18);
  stroke: transparent;
}
.survey-overlay .roads-sand {
  fill: transparent;
  stroke: transparent;
}
.survey-overlay .road-body > rect[mask="url(#roadSurf)"] {
  display: none;
}
.survey-overlay .conn-road {
  stroke: transparent;
}
.survey-overlay .conn-road.sand {
  stroke: rgba(243, 236, 224, 0.18);
  stroke-linecap: butt;
}
.survey-overlay .roads-sketch .sketch-road {
  stroke: transparent;
}
.survey-breath {
  animation: none;
}

/* surveyor's annotations (inside the injected SVG): the plot number is
   silent at rest and lights up white on its own plot's hover.
   Sized 12px, not 10px (6 Aug): at 10 the 1 and the 7 read as the same
   glyph over the plate texture, and a misread number is a misdirected
   sales call. The label dropped from "604 m²" to "47" the same day, so
   the extra size costs no room. */
.survey-overlay .plot-num {
  font-family: "Plex Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-anchor: middle;
  fill: #fff;
  stroke: none;
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}
.survey-overlay .plot-g:hover .plot-num,
.survey-overlay .plot-g:focus-within .plot-num {
  opacity: 1;
}
/* sold: hatched + darkened and excluded from the immersion dive */
.survey-overlay .plot.sold {
  cursor: default;
}
.survey-overlay .plot.sold:hover {
  fill: inherit;
  filter: none;
}
/* living houses on sold plots — canvas stamps over the survey */
.sold-homes {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  opacity: 1;
  transition: none;
}
.sold-homes.show {
  opacity: 1;
}
/* the ink-draw entrance */
.survey-overlay.will-draw .plot,
.survey-overlay.will-draw .plot-echo,
.survey-overlay.will-draw .plot-tex,
.survey-overlay.will-draw .sold-mark {
  opacity: 0;
}
.survey-overlay.drawn .sold-mark {
  opacity: 1;
  transition: opacity 1.2s ease 2.8s;
}
.survey-overlay.drawn .plot-tex {
  opacity: 1;
  transition: opacity 1.6s ease 1.6s;
}
.survey-overlay.drawn .plot-echo {
  opacity: 0.32;
  transition: opacity 1.2s ease 2.8s;
}
@keyframes surveyBreath {
  0%,
  100% {
    opacity: 0.76;
  }
  50% {
    opacity: 0.84;
  }
}
.plot {
  cursor: pointer;
  transition:
    fill 0.35s ease,
    stroke 0.35s ease,
    filter 0.35s ease;
}
.plot:hover {
  fill: #c8563c;
  filter: drop-shadow(0 0 6px rgba(200, 86, 60, 0.9))
    drop-shadow(0 0 16px rgba(200, 86, 60, 0.5));
}
.survey-figure figcaption {
  margin: 0.5rem 0 0;
  font-size: 0.7rem;
  line-height: 1.4;
  color: rgba(36, 31, 27, 0.68);
}
/* ---------- map legend: map-exact swatches, sampled from make-survey-svg.cjs ----------
   CREAM #f4eddf (L79) · SAND #d8cbb0 (L80) · INK #241f1b (L81)
   available plot fill = hslRgb(36,30,79) = #dacdb9 (PLOT_BASE default/hslRgb/PLOT_FILL, L162–175)
   sold hatch = rgba(12,11,9,.34) base + rgba(36,31,27,.6) lines (#soldHatch pattern, L434–436)
   road = SAND fill + INK casing (L445–446); no drawn bridge deck — the road over the
   river reads as the bridge (L248), so the bridge swatch reuses the same SAND/INK pair
   styled as a short double-stroke rather than inventing a colour. */
.map-legend {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  margin: 0;
  padding: 0;
  font-family: "FiraGO", sans-serif;
  font-size: 0.85rem;
  color: rgba(36, 31, 27, 0.8);
}
.map-legend li {
  display: flex;
  align-items: center;
  gap: 0.45em;
}
.map-legend i {
  display: inline-block;
  width: 1.1em;
  height: 0.75em;
  border-radius: 2px;
  flex: none;
}
/* available/sold read as filled parcels (full-height block); road/bridge read
   as linear features (thin strip) — the sampled sand/plot tones are close
   enough (#dacdb9 vs #d8cbb0) that shape, not colour, keeps them legible */
/* The legend must show what the plate shows. Under option B (7 Aug) parcels are
   translucent white with a hairline, sold is solid terracotta with the hatch
   dropped, and roads are one dark translucent surface. A legend swatch that
   still shows the old hatch teaches the map wrong. */
.lg-available {
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(36, 31, 27, 0.55);
}
.lg-sold {
  background: var(--terracotta);
  border: 1px solid rgba(36, 31, 27, 0.55);
}
.lg-road {
  height: 0.4em;
  align-self: center;
  background: rgba(46, 38, 30, 0.42);
  border: 0;
}
.lg-bridge {
  height: 0.4em;
  align-self: center;
  background: transparent;
  border-top: 2px solid #241f1b;
  border-bottom: 2px solid #241f1b;
}

/* ---------- wind: fully static background - element kept in the DOM
   (a test asserts it), motion disabled so nothing animates over the plate ---------- */
.survey-wind {
  display: none;
}

.facts {
  list-style: none;
  padding: 0;
  margin: clamp(3.8rem, 7vw, 5.5rem) 0 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.4rem;
  border-top: 2px solid var(--terracotta);
  padding-top: 1.35rem;
}
.facts li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 0.7rem;
  row-gap: 0.45rem;
  min-width: 0;
  padding-top: 0;
}
.scene.page.dark .facts li {
  border-top-color: #d98b6f;
}
.scene.page.dark .facts svg {
  color: #d98b6f;
}
.facts svg {
  display: block;
  flex: none;
  grid-column: 1;
  grid-row: 1;
  width: clamp(1.6rem, 3vw, 2.6rem);
  height: clamp(1.6rem, 3vw, 2.6rem);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--terracotta);
}
.facts strong {
  display: inline;
  grid-column: 2;
  grid-row: 1;
  font-family: "Mersad", sans-serif;
  font-weight: 900;
  font-size: clamp(1.6rem, 3vw, 2.6rem);
  line-height: 1;
  margin: 0;
  color: var(--terracotta-text);
  white-space: nowrap;
}
.facts span {
  grid-column: 2;
  grid-row: 2;
  font-size: 0.9rem;
  color: rgba(36, 31, 27, 0.65);
  white-space: nowrap;
}
.scene.page.dark .facts span {
  color: rgba(243, 236, 224, 0.65);
}
.scene.page.dark .facts strong {
  color: var(--cream);
}

/* ---------- life rows ---------- */
#life .page-inner {
  counter-reset: liferow;
}
#life .row {
  counter-increment: liferow;
}
#life .row-text .eyebrow::before {
  content: "0" counter(liferow) " · ";
  color: var(--terracotta-text);
}

.row,
.row-media,
.row-text,
.wayfinder-figure {
  min-width: 0;
}

.row {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: center;
  margin-top: var(--sp-4);
}
.row.flip {
  grid-template-columns: 1fr 1.15fr;
}
.row.flip .row-media {
  order: 2;
}
.pillar-static {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 14px;
  box-shadow: 0 30px 80px -30px rgba(36, 31, 27, 0.45);
}
/* pillar 04: two full-width subsections stacked - info first, map second */
.row.location {
  grid-template-columns: 1fr;
  gap: clamp(1.2rem, 2.5vw, 1.8rem);
}
.row.location .row-text {
  order: 2;
}
.row.location .row-media {
  order: 1;
}
/* legend: four icon-led categories across the width */
.row.location .wayfinder-legend {
  grid-template-columns: repeat(4, 1fr);
  margin-top: 1.1rem;
}
.row.location .wayfinder-legend li {
  border-top-color: rgba(36, 31, 27, 0.18);
}
.wf-legend-icon {
  display: block;
  width: 22px;
  height: 22px;
  margin-bottom: 0.55rem;
}
.row-media {
  position: relative;
}
.replay-btn {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 1.5px solid rgba(243, 236, 224, 0.75);
  background: rgba(12, 11, 9, 0.28);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.4s ease,
    background 0.25s ease;
  display: grid;
  place-items: center;
}
.replay-btn::after {
  content: "";
  width: 0;
  height: 0;
  border-left: 14px solid rgba(243, 236, 224, 0.9);
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  margin-left: 3px;
}
.replay-btn.show {
  opacity: 1;
  pointer-events: auto;
}
.replay-btn:hover {
  background: rgba(200, 86, 60, 0.55);
}
.row-media video {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  border-radius: 14px;
  box-shadow: 0 30px 80px -30px rgba(36, 31, 27, 0.45);
  background: #000;
}

/* amenity slider: auto-advancing image carousel with a bottom control (pillars 01 & 03) */
.amenity-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  background: #e8dcc7;
  overflow: hidden;
  box-shadow: 0 30px 80px -30px rgba(36, 31, 27, 0.45);
}
.amenity-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.amenity-pending {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: "Plex Mono", monospace;
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(36, 31, 27, 0.4);
}
.amenity-stage:has(.amenity-img) .amenity-pending {
  display: none;
}
.amenity-control {
  position: absolute;
  left: 50%;
  bottom: clamp(0.7rem, 2vw, 1.1rem);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.28rem 0.4rem;
  border-radius: 999px;
  /* audit Medium 1: amenity-current's cream text sits on this fill - needs 4.5:1 */
  background: var(--terracotta-deep);
  box-shadow: 0 8px 24px -8px rgba(12, 11, 9, 0.45);
}
.amenity-current {
  font-family: "Plex Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--cream);
  width: 7.5rem;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.amenity-arrow {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.2s;
}
.amenity-arrow:hover {
  background: rgba(243, 236, 224, 0.18);
}
.amenity-arrow::before {
  content: "";
  width: 8px;
  height: 8px;
  border-left: 2px solid var(--cream);
  border-bottom: 2px solid var(--cream);
}
.amenity-prev::before {
  transform: rotate(45deg) translate(1px, -1px);
}
.amenity-next::before {
  transform: rotate(-135deg) translate(1px, -1px);
}
.row-text h3 {
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: clamp(1.5rem, 2.6vw, 2.2rem);
  line-height: 1.1;
  margin-bottom: 0.9rem;
  text-wrap: balance;
  color: var(--ink);
  overflow-wrap: break-word; /* audit High 1 - see .page-title */
}
.row-text p:not(.eyebrow) {
  font-size: clamp(0.95rem, 1.4vw, 1.1rem);
  line-height: 1.65;
  color: rgba(36, 31, 27, 0.75);
  max-width: 30rem;
}
.scene.page.dark .row-text p:not(.eyebrow) {
  color: rgba(243, 236, 224, 0.75);
}
.scene.page.dark .row-media {
  position: relative;
}
.replay-btn {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 1.5px solid rgba(243, 236, 224, 0.75);
  background: rgba(12, 11, 9, 0.28);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.4s ease,
    background 0.25s ease;
  display: grid;
  place-items: center;
}
.replay-btn::after {
  content: "";
  width: 0;
  height: 0;
  border-left: 14px solid rgba(243, 236, 224, 0.9);
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  margin-left: 3px;
}
.replay-btn.show {
  opacity: 1;
  pointer-events: auto;
}
.replay-btn:hover {
  background: rgba(200, 86, 60, 0.55);
}
.row-media video {
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.85);
}
.row-text .eyebrow {
  margin-bottom: 0.7rem;
}

/* pillar amenity chips — small Plex Mono pills with a terracotta rule */
.pillar-chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.7rem;
  padding: 0;
  margin: 1.5rem 0 0;
}
.pillar-chips li {
  font-family: "Plex Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 0.45em 0.95em;
  border: 1px solid rgba(200, 86, 60, 0.4);
  border-radius: 999px;
}
.scene.page.dark .pillar-chips li {
  color: var(--cream);
  border-color: rgba(217, 139, 111, 0.45);
}

/* pillar support stills — one or two photos under the chips */
.pillar-stills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.8rem;
  margin-top: 1.4rem;
}
.pillar-stills img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  border-radius: 10px;
  box-shadow: 0 16px 40px -18px rgba(36, 31, 27, 0.4);
}

/* ---------- strategic location: schematic wayfinder ----------
   Honest wayfinding art, not a geographic claim — ink lines on cream,
   Plex Mono labels, terracotta dots. Compass placements are deliberately
   coarse; the "Schematic" caption is the honesty device, not a disclaimer
   to hide. Every landmark opens its own Google Maps name-search. */
.wayfinder-figure {
  margin: 0;
}
.wayfinder {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1000 / 480;
  border-radius: 14px;
  background: var(--cream);
  border: 1px solid rgba(36, 31, 27, 0.14);
  box-shadow: 0 30px 80px -30px rgba(36, 31, 27, 0.45);
}
.wf-topo path {
  fill: none;
  stroke: rgba(36, 31, 27, 0.09);
  stroke-width: 1;
}
.wf-dir {
  font-family: "Plex Mono", monospace;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.12em;
  fill: var(--ink);
  opacity: 0.72;
}
.wf-ray {
  stroke: var(--ink);
  stroke-width: 1.1;
  stroke-dasharray: 2 5;
  opacity: 0.3;
  transition: opacity 0.2s ease;
}
.wf-hit {
  fill: transparent;
  pointer-events: all;
}
.wf-lm-label {
  font-family: "Plex Mono", monospace;
  font-size: 17px;
  fill: var(--ink);
}
.wf-lm {
  cursor: pointer;
}
.wf-lm:hover .wf-lm-label,
.wf-lm:focus-visible .wf-lm-label {
  text-decoration: underline;
}
.wf-lm:hover .wf-ray,
.wf-lm:focus-visible .wf-ray {
  opacity: 0.42;
}
.wf-lm:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 2px;
}
.wf-home-ring {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.5;
}
.wf-home-dot {
  fill: var(--terracotta);
}
.wf-home-label {
  font-family: "Plex Mono", monospace;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.1em;
  fill: var(--ink);
}
.wayfinder-legend {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.2rem 1.8rem;
  padding: 0;
  margin: 1.6rem 0 0;
}
.wayfinder-legend li {
  border-top: 2px solid var(--terracotta);
  padding-top: 0.6rem;
}
.wf-cat {
  display: block;
  font-family: "Plex Mono", monospace;
  font-size: 0.85rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--terracotta-text);
  margin-bottom: 0.3rem;
}
.wf-items {
  display: block;
  font-size: 0.92rem;
  line-height: 1.55;
  color: rgba(36, 31, 27, 0.7);
}
.wayfinder-figure figcaption {
  width: 100%;
  margin: 0.55rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: rgba(36, 31, 27, 0.55);
}
@media (max-width: 640px) {
  .row.location .wayfinder-legend {
    grid-template-columns: 1fr;
  }
}

/* ---------- landmark card: tap a wayfinder point, read here first ----------
   8 Aug: replaces the straight-to-Google tap. Content and figure art are
   ported from docs/feedback/6-aug-2026/sakvire-landmarks-concept.html, but
   the chrome is this page's own cream/ink/terracotta - the concept's dark
   theme was a moodboard, not a rule to carry over. Zero resting SVG filters
   (3 Aug doctrine, see .pm-context .subject-halo above): the scene's glow
   is concentric circles, not feGaussianBlur. */
.wfc-modal {
  position: fixed;
  inset: 0;
  z-index: 65;
  display: grid;
  place-items: center;
  padding: clamp(0.8rem, 4vw, 2.6rem);
  background: rgba(12, 11, 9, 0.62);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.35s ease,
    visibility 0.35s ease;
}
.wfc-modal[hidden] {
  display: none;
}
.wfc-modal.on {
  opacity: 1;
  visibility: visible;
}
.wfc-card {
  position: relative;
  width: min(640px, 100%);
  max-height: min(88svh, 780px);
  overflow-y: auto;
  background: var(--cream);
  color: var(--ink);
  border-radius: 16px;
  box-shadow: 0 40px 100px -24px rgba(8, 7, 5, 0.55);
  transform: translateY(18px) scale(0.98);
  transition: transform 0.4s ease;
}
.wfc-modal.on .wfc-card {
  transform: none;
}
.wfc-fig {
  position: relative;
  aspect-ratio: 20 / 9;
  overflow: hidden;
  background: var(--night);
  border-radius: 16px 16px 0 0;
}
.wfc-fig svg {
  width: 100%;
  height: 100%;
  display: block;
}
.wfc-chip {
  position: absolute;
  left: 1.2rem;
  bottom: 1.1rem;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4em 0.85em;
  border-radius: 999px;
  background: rgba(12, 11, 9, 0.55);
  font-family: "Plex Mono", monospace;
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream);
}
.wfc-chip i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}
.wfc-close {
  position: absolute;
  top: clamp(0.8rem, 3vh, 1.4rem);
  right: clamp(0.8rem, 3vw, 1.4rem);
  z-index: 2;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(243, 236, 224, 0.5);
  border-radius: 50%;
  background: rgba(12, 11, 9, 0.4);
  color: var(--cream);
  cursor: pointer;
  transition:
    background 0.25s,
    border-color 0.25s;
}
.wfc-close:hover {
  background: rgba(200, 86, 60, 0.75);
  border-color: transparent;
}
.wfc-body {
  padding: clamp(1.4rem, 3.4vw, 2.2rem);
}
.wfc-name {
  margin: 0 0 0.8rem;
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: clamp(1.4rem, 3vw, 1.9rem);
  line-height: 1.1;
}
.wfc-txt {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: rgba(36, 31, 27, 0.8);
}
.wfc-facts {
  list-style: none;
  margin: 1.2rem 0 0;
  padding: 0;
  border-top: 1px solid rgba(36, 31, 27, 0.18);
}
.wfc-facts li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0.05rem;
  border-bottom: 1px solid rgba(36, 31, 27, 0.12);
  font-family: "Plex Mono", monospace;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
}
.wfc-facts li span:first-child {
  color: rgba(36, 31, 27, 0.55);
}
.wfc-facts li span:last-child {
  color: var(--ink);
  text-align: right;
}
.wfc-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem;
  margin-top: 1.4rem;
}
.wfc-map {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.8em 1.4em;
  border-radius: 999px;
  /* audit Medium 1: cream text on fill needs 4.5:1 */
  background: var(--terracotta-deep);
  color: var(--cream);
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 0.25s;
}
.wfc-map:hover {
  background: var(--ink);
}
.wfc-share {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75em 1.1em;
  border-radius: 999px;
  border: 1px solid rgba(36, 31, 27, 0.3);
  background: none;
  color: var(--ink);
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    border-color 0.25s,
    background 0.25s;
}
.wfc-share:hover {
  border-color: var(--terracotta);
  background: rgba(200, 86, 60, 0.08);
}
.wfc-step {
  display: flex;
  gap: 0.3rem;
  margin-left: auto;
}
.wfc-step button {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(36, 31, 27, 0.22);
  background: none;
  color: var(--ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition:
    border-color 0.25s,
    background 0.25s;
}
.wfc-step button:hover {
  border-color: var(--terracotta);
  background: rgba(200, 86, 60, 0.08);
}
body.wfc-open {
  overflow: hidden;
}
@media (max-width: 640px) {
  .wfc-modal {
    padding: 0;
    align-items: flex-end;
  }
  .wfc-card {
    width: 100%;
    max-height: 92svh;
    border-radius: 16px 16px 0 0;
  }
  .wfc-actions {
    flex-direction: column;
    align-items: stretch;
  }
  .wfc-map {
    justify-content: center;
  }
  .wfc-share {
    justify-content: center;
  }
  .wfc-step {
    margin-left: 0;
    justify-content: center;
  }
}
@media (prefers-reduced-motion: reduce) {
  .wfc-modal,
  .wfc-card {
    transition: none;
  }
}

/* ---------- one-day theater ---------- */

.day-theater-section {
  transition: background 1.4s ease;
}
.day-theater {
  width: 100%;
  margin-top: 2rem;
}
/* the sky float: a height-capped 16:9 frame centered in the phase-sky,
   every pixel of the films visible, the changing sky visible around them */
.day-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  height: min(78svh, 56.25vw);
  margin-inline: auto;
  overflow: hidden;
  border-radius: 12px;
  background: #000;
  box-shadow: 0 34px 90px -32px rgba(0, 0, 0, 0.55);
}
.day-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.9s ease;
}
.day-frame video.active {
  opacity: 1;
}

/* the day-timeline: one line from first light to last star */
.day-timeline {
  position: relative;
  height: 4.6rem;
  margin: 1.6rem auto 0;
  width: min(76rem, 92vw);
}
.tl-track {
  position: absolute;
  left: 0;
  right: 0;
  top: 0.55rem;
  height: 2px;
  background: rgba(36, 31, 27, 0.22);
  border-radius: 2px;
  transition: background 1.4s ease;
}
.scene.page.dark .tl-track {
  background: rgba(243, 236, 224, 0.22);
}
.tl-dot {
  position: absolute;
  top: 0.55rem;
  left: 5.4%;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--gold);
  transform: translate(-50%, -50%);
  box-shadow: 0 0 14px rgba(200, 169, 110, 0.9);
  z-index: 2;
  pointer-events: none;
}
/* past dusk the sun becomes a moon */
.tl-dot.night {
  background: var(--cream);
  box-shadow: 0 0 12px rgba(243, 236, 224, 0.7);
}
.tl-dot.night::after {
  content: "";
  position: absolute;
  right: -2px;
  top: -1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--night);
  opacity: 0.85;
}
.tl-stop {
  position: absolute;
  left: var(--pos);
  top: 0;
  transform: translateX(-50%);
  appearance: none;
  background: none;
  border: none;
  padding: 1.1rem 0.4rem 0.2rem;
  text-align: center;
  cursor: pointer;
}
.tl-stop:first-of-type {
  transform: translateX(-14%);
  text-align: left;
}
.tl-stop:last-of-type {
  transform: translateX(-86%);
  text-align: right;
}
.tl-stop::before {
  content: "";
  position: absolute;
  top: 0.55rem;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(36, 31, 27, 0.35);
  transition: background 0.4s;
}
.tl-stop:first-of-type::before {
  left: 14%;
}
.tl-stop:last-of-type::before {
  left: 86%;
}
.scene.page.dark .tl-stop::before {
  background: rgba(243, 236, 224, 0.35);
}
.tl-stop strong {
  display: block;
  font-family: "Plex Mono", monospace;
  font-weight: 400;
  font-size: clamp(0.78rem, 1.3vw, 0.95rem);
  letter-spacing: 0.12em;
  color: rgba(36, 31, 27, 0.55);
  transition: color 0.4s;
}
.scene.page.dark .tl-stop strong {
  color: rgba(243, 236, 224, 0.55);
}
.tl-stop span {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.76rem;
  color: rgba(36, 31, 27, 0.45);
  transition: color 0.4s;
}
.scene.page.dark .tl-stop span {
  color: rgba(243, 236, 224, 0.42);
}
.tl-stop:hover strong {
  color: var(--ink);
}
.scene.page.dark .tl-stop:hover strong {
  color: var(--cream);
}
.tl-stop.active strong {
  /* Ink, not terracotta: this label sits on six JS-cycled scene tints and
     --terracotta-text clears AA only on the noon cream (4.68:1), falling to
     3.6-4.2:1 on three lighter tints (8 Aug audit residual). Ink clears all
     six - and matches the de-red the client chose for the facts strip
     (13 Jul). Dark scenes keep gold below. */
  color: var(--ink);
}
.scene.page.dark .tl-stop.active strong {
  color: var(--gold);
}
.tl-stop.active span {
  color: rgba(36, 31, 27, 0.65);
}
.scene.page.dark .tl-stop.active span {
  color: rgba(243, 236, 224, 0.65);
}
/* narrow screens: six labels can't share one line — dots stay at their
   true hours, only the active stop speaks */
@media (max-width: 640px) {
  .day-timeline {
    height: 3.8rem;
  }
  .tl-stop {
    min-width: 2.4rem;
    min-height: 2.6rem;
  }
  .tl-stop:not(.active) strong,
  .tl-stop:not(.active) span {
    display: none;
  }
  .tl-stop strong {
    font-size: 0.72rem;
  }
  .tl-stop span {
    font-size: 0.66rem;
    white-space: nowrap;
  }
}

/* ---------- roadmap: three phases, phased progress bar ---------- */

/* roadmap — blueprint project timeline (Gantt) */
.rm-gantt {
  display: grid;
  grid-template-columns: minmax(6rem, 8rem) repeat(9, 1fr);
  align-items: center;
  gap: 0.6rem 0;
  margin: clamp(5rem, 10vw, 8rem) 0 var(--sp-4);
  /* audit High 1: a year/quarter Gantt is inherently two-dimensional (WCAG 1.4.10
     exempts it from reflow) - at 200% text the nine quarter columns can't shrink
     further, so the grid scrolls within its own box instead of pushing the page
     wide. */
  overflow-x: auto;
}
.rm-grid {
  align-self: stretch;
  pointer-events: none;
  background: repeating-linear-gradient(
    90deg,
    transparent 0,
    transparent calc(100% / 9 - 1px),
    rgba(36, 31, 27, 0.07) calc(100% / 9 - 1px),
    rgba(36, 31, 27, 0.07) calc(100% / 9)
  );
}
.rm-year {
  grid-row: 1;
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--ink);
  padding-left: 0.55rem;
  border-left: 1px solid rgba(36, 31, 27, 0.28);
}
.rm-q {
  grid-row: 2;
  font-family: "Plex Mono", monospace;
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  color: rgba(36, 31, 27, 0.68);
  text-align: center;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid rgba(36, 31, 27, 0.22);
}
.rm-glabel {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: "Plex Mono", monospace;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--ink);
}
.rm-glabel svg {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--terracotta);
}
.rm-gbar {
  position: relative;
  overflow: hidden;
  height: 30px;
  border-radius: 6px;
  background: rgba(36, 31, 27, 0.18);
  display: flex;
  align-items: center;
  padding: 0 0.6rem;
  min-width: 10px;
}
/* phase I: "we are there already" - terracotta fills left -> right on entry */
.rm-gbar.current::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--terracotta);
  transform: scaleX(0);
  transform-origin: left;
}
#roadmap.inview .rm-gbar.current::before {
  animation: rm-fill 1.4s cubic-bezier(0.5, 0, 0.3, 1) 0.4s forwards;
}
.rm-gbar.current::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    transparent 25%,
    rgba(243, 236, 224, 0.3) 50%,
    transparent 75%
  );
  transform: translateX(-100%);
}
#roadmap.inview .rm-gbar.current::after {
  animation: rm-hint 5s ease-in-out 1.9s infinite;
}
@keyframes rm-fill {
  to {
    transform: scaleX(1);
  }
}
/* phases II/III: a slow gray shimmer hints "future" without competing */
.rm-gbar.future {
  background: rgba(36, 31, 27, 0.14);
}
.rm-gbar.future::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    transparent 25%,
    rgba(36, 31, 27, 0.12) 50%,
    transparent 75%
  );
  transform: translateX(-100%);
}
#roadmap.inview .rm-gbar.future::after {
  animation: rm-hint 5s ease-in-out 1.9s infinite;
}
@keyframes rm-hint {
  0% {
    transform: translateX(-100%);
  }
  60%,
  100% {
    transform: translateX(100%);
  }
}
.rm-gtag {
  position: relative; /* keeps "Now" above the fill layer */
  z-index: 1;
  font-family: "Plex Mono", monospace;
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream);
  white-space: nowrap;
}

.rm-details {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.6rem, 4vw, 3rem);
  margin-top: var(--sp-4);
}
.rm-phase {
  display: flex;
  flex-direction: column;
  margin: 0;
  border-top: 2px solid rgba(200, 86, 60, 0.3);
  padding-top: 1.1rem;
}
.rm-num {
  font-family: "Mersad", sans-serif;
  font-weight: 900;
  font-size: 2.1rem;
  line-height: 1;
  color: var(--terracotta-text);
  margin-bottom: 0.4rem;
}
.rm-phase h3 {
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: 1.15rem;
  line-height: 1.25;
  margin-bottom: 0.55rem;
}
.rm-when {
  font-family: "Plex Mono", monospace;
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--terracotta-text);
  margin-bottom: 0.9rem;
}
.rm-phase p:not(.rm-when):not(.rm-num) {
  font-size: 0.92rem;
  line-height: 1.6;
  color: rgba(36, 31, 27, 0.75);
  margin-bottom: 0.9rem;
}
.rm-phase ul {
  margin: 0 0 0.9rem;
  padding-left: 1.1rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: rgba(36, 31, 27, 0.75);
}
.rm-phase li {
  margin-bottom: 0.35rem;
}

@media (max-width: 800px) {
  .rm-gantt {
    grid-template-columns: 4.5rem repeat(9, 1fr);
  }
  .rm-glabel {
    font-size: 0.68rem;
    gap: 0.3rem;
  }
  .rm-glabel svg {
    width: 16px;
    height: 16px;
  }
  .rm-details {
    grid-template-columns: 1fr;
    gap: 2.4rem;
  }
}

/* copy placeholders — visibly unfinished, never mistaken for final copy */
.tbd {
  opacity: 0.78;
  font-family: "Plex Mono", monospace;
  font-size: 0.85em;
  letter-spacing: 0.02em;
}
.partners-placeholder {
  margin-top: 1.6rem;
}

/* one full-bleed slider - "same drill as the activities" (13-jul) */
.gallery-slider {
  margin-top: var(--sp-4);
  width: 100vw;
  margin-left: calc(50% - 50vw);
  padding-inline: max(calc((100vw - var(--col)) / 2 - 2rem), 0.8rem);
}
.gs-stage {
  position: relative;
}
.gs-frame {
  aspect-ratio: 16 / 7;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.gs-frame.tbd {
  border: 1px dashed rgba(36, 31, 27, 0.3);
  background: rgba(36, 31, 27, 0.03);
}
.gs-frame > span {
  font-family: "Plex Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(36, 31, 27, 0.4);
}
.gs-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gs-arrow {
  position: absolute;
  top: calc(50% - 1.2rem);
  width: 56px;
  height: 56px;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.2s;
}
.gs-arrow:hover {
  background: transparent;
}
.gs-arrow::before {
  content: "";
  width: 20px;
  height: 20px;
  border-left: 4px solid var(--cream);
  border-bottom: 4px solid var(--cream);
  filter: drop-shadow(0 2px 5px rgba(12, 11, 9, 0.55));
}
.gs-prev {
  left: 1.2rem;
}
.gs-next {
  right: 1.2rem;
}
.gs-prev::before {
  transform: rotate(45deg) translate(1px, -1px);
}
.gs-next::before {
  transform: rotate(225deg) translate(1px, -1px);
}
.gs-control {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: var(--sp-1);
}
.gs-caption {
  font-family: "Plex Mono", monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  color: rgba(36, 31, 27, 0.72);
  text-align: center;
}
@media (max-width: 640px) {
  .gs-frame {
    aspect-ratio: 4 / 3;
  }
  .gs-arrow {
    width: 48px;
    height: 48px;
  }
  .gs-prev {
    left: 0.7rem;
  }
  .gs-next {
    right: 0.7rem;
  }
}

.scene.page.dark {
  overflow: hidden;
}

/* ---------- closer / visit ---------- */

/* ---------- contact closer: plain pine, two-column ---------- */
.scene.closer {
  position: relative;
  min-height: 100svh;
  background: #2b4436;
  color: var(--cream);
  display: grid;
  place-items: center;
  padding: clamp(3rem, 9svh, 6.5rem) 0 clamp(2rem, 5svh, 3.5rem);
}
.closer-inner {
  width: var(--col);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(22rem, 0.9fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.closer-invite {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: clamp(2.4rem, 5.5vh, 4rem);
}
.brandmark {
  width: clamp(230px, 25vw, 340px);
  height: auto;
  display: block;
}
.closer-mark {
  order: 1;
  width: clamp(190px, 20vw, 280px);
  filter: brightness(0) saturate(100%) invert(94%) sepia(9%) saturate(430%)
    hue-rotate(357deg) brightness(103%)
    drop-shadow(0 10px 40px rgba(8, 7, 5, 0.4));
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.closer-tagline {
  margin-top: 0;
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: clamp(1.65rem, 2.7vw, 2.35rem);
  line-height: 1.08;
  color: var(--cream);
  text-wrap: balance;
}
.closer-message {
  order: 2;
}
.closer-contact {
  order: 3;
}
.pillars {
  margin-top: 1.1rem;
  font-weight: 500;
  font-family: "FiraGO", sans-serif;
  font-size: clamp(0.7rem, 1.2vw, 0.82rem);
  letter-spacing: 0.42em;
  color: var(--gold);
}
.closer-channels {
  margin-top: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 1.4rem;
  font-family: "Plex Mono", monospace;
  font-size: 0.95rem;
}
.closer-channels a {
  color: var(--cream);
  text-decoration: none;
  width: fit-content;
  border-bottom: 1px solid rgba(200, 169, 110, 0.4);
  padding-bottom: 1px;
  transition: color 0.25s;
}
.closer-channels a:hover {
  color: var(--gold);
}
.closer-form {
  width: 80%;
  justify-self: center;
  background: rgba(243, 236, 224, 0.05);
  border: 1px solid rgba(243, 236, 224, 0.14);
  border-radius: 14px;
  padding: clamp(1.6rem, 3vw, 2.4rem);
}
.closer-form-title {
  font-family: "Plex Mono", monospace;
  font-size: 0.7rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--cream);
  margin-bottom: 1.3rem;
}
.lead-form {
  display: grid;
  /* audit High 1: an implicit auto column keeps the same min-width:auto blowout
     as .closer-inner - the consent row's text pushed every field to ~350px at
     200% text even though the form itself was only ~180px wide. */
  grid-template-columns: minmax(0, 1fr);
  gap: 0.75rem;
  text-align: left;
}
.lead-form label {
  display: block;
  font-family: "Plex Mono", monospace;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(243, 236, 224, 0.78);
}
.lead-form input,
.lead-form textarea {
  display: block;
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.55em 0.75em;
  font-family: "FiraGO", sans-serif;
  font-size: 0.85rem;
  color: var(--cream);
  background: transparent;
  border: 1px solid rgba(243, 236, 224, 0.35);
  border-radius: 4px;
  transition: border-color 0.25s;
}
.lead-form textarea {
  resize: vertical;
}
.lead-form input:focus,
.lead-form textarea:focus {
  border-color: var(--terracotta);
}
.hp {
  position: absolute;
  left: -9999px;
}
.lead-form label.lead-consent {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-family: "FiraGO", sans-serif;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 0.8rem;
  color: rgba(243, 236, 224, 0.78);
}
.lead-consent input {
  width: auto;
  margin-top: 0.2rem;
  accent-color: var(--terracotta);
}
.lead-consent span {
  /* audit High 1: flex items default to min-width:auto, which held the consent
     sentence at its full one-line width instead of letting it shrink and wrap
     at 200% text. break-word (inherited into the nested link) covers the KA
     copy, where the final phrase didn't take its own space-break at 200%. */
  min-width: 0;
  overflow-wrap: break-word;
}
.lead-consent a {
  color: var(--cream);
  text-underline-offset: 0.2em;
}
.contact-hint {
  margin: -0.15rem 0 0.15rem;
  font-size: 0.78rem;
  color: rgba(243, 236, 224, 0.72);
}
.btn.lead-submit {
  display: inline-block;
  justify-self: start;
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cream);
  /* audit Medium 1: was reusing the text token for a fill - cream text on
     terracotta-text (4.68:1 on cream, not the fill's own AA target) needs
     terracotta-deep (4.54:1 under cream text) instead. */
  background: var(--terracotta-deep);
  border: none;
  cursor: pointer;
  padding: 0.9em 1.7em;
  border-radius: 999px;
  transition: background 0.25s;
}
.btn.lead-submit:hover {
  background: var(--cream);
  color: var(--night);
}
.lead-status {
  min-height: 1.2em;
  font-family: "FiraGO", sans-serif;
  font-size: 0.82rem;
  color: var(--gold);
}
.lead-fallback {
  margin-top: 2rem;
  font-family: "FiraGO", sans-serif;
  font-size: 0.85rem;
  color: rgba(243, 236, 224, 0.78);
}
.social-row {
  list-style: none;
  display: flex;
  flex-wrap: wrap; /* audit High 1: nowrap pushed the second icon off-screen at 200% text */
  gap: 1.4rem;
  padding: 0;
  margin: 1.6rem 0 0;
}
.social-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  color: var(--cream);
  text-decoration: none;
  opacity: 0.82;
  transition: opacity 0.2s ease;
}
.social-indicator:hover,
.social-indicator:focus-visible {
  opacity: 1;
}
.social-row svg {
  width: 36px;
  height: 36px;
  padding: 7px;
  color: var(--cream);
  background: var(--terracotta);
  border-radius: 50%;
  stroke-width: 1.8;
}
.social-row li:first-child svg {
  transform: translate(-0.5px, -0.5px);
}
.social-row span {
  font-family: "Plex Mono", monospace;
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.contact {
  margin-top: 2rem;
  font-weight: 500;
  font-family: "FiraGO", sans-serif;
  font-size: clamp(0.78rem, 1.4vw, 0.95rem);
  letter-spacing: 0.1em;
}
.contact a {
  color: var(--cream);
  text-decoration: none;
  border-bottom: 1px solid rgba(200, 169, 110, 0.5);
  transition: color 0.25s;
}
.contact a:hover {
  color: var(--gold);
}
.fine {
  margin-top: 4rem;
  font-weight: 500;
  font-family: "FiraGO", sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  color: rgba(243, 236, 224, 0.7);
}
.footer-brand {
  color: inherit;
}

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .nav-toggle {
    display: flex;
  }
  .site-nav {
    position: fixed;
    inset: 3.4rem 0 auto 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 0.6rem 1.4rem 1.2rem;
    background: rgba(12, 11, 9, 0.94);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    display: none;
  }
  .site-head.nav-open .site-nav {
    display: flex;
  }
  .site-nav a {
    padding: 0.7em 0;
  }
  .site-nav a.cta {
    margin-top: 0.6rem;
  }
  .site-nav a.lang-switch {
    padding-left: 0;
    border-left: 0;
  }
  .row,
  .row.flip {
    grid-template-columns: 1fr;
  }
  .row.flip .row-media {
    order: 0;
  }
  .facts {
    grid-template-columns: 1fr 1fr;
  }
  .hero-tabs {
    gap: 1rem;
  }
  .thesis-image img {
    aspect-ratio: 16 / 9;
  }
  .thesis-image {
    width: 100%;
  }
  .closer-inner {
    /* audit High 1: a bare 1fr track keeps an implicit auto min-width, so any
       unshrinkable descendant (social row, form fields) blew the whole grid past
       the viewport at 200% text; minmax(0, 1fr) lets the track - and everything
       stacked in it - actually shrink to fit. */
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 640px) {
  .facts {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .cap,
  .page-inner,
  .thesis .page-lead {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .hero-films video,
  .day-frame video {
    transition: none;
  }
  .survey-breath {
    animation: none;
  }
  .rm-gbar.current::before {
    animation: none !important;
    transform: scaleX(1);
  }
  .rm-gbar.current::after {
    animation: none !important;
  }
  .rm-gbar.future::after {
    animation: none !important;
  }
}

/* ============ plot immersion — click a free plot, stand on it ============ */
.plot-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--cream);
  display: grid;
  place-items: center;
}
.plot-modal[hidden] {
  display: none;
}
.pm-dossier {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  background: var(--cream);
  color: var(--ink);
  overflow: hidden;
}
.pm-survey {
  position: relative;
  background: var(--pine);
  overflow: hidden;
  border-right: 1px solid rgba(36, 31, 27, 0.12);
}
.pm-survey svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.pm-plot-svg path {
  fill: rgba(200, 86, 60, 0.22);
  stroke: var(--terracotta);
  stroke-width: 3px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* The dive's destination: the selected plot inside its actual neighbourhood.
   A clone of the survey overlay, reframed - so the neighbours, the roads and
   the numbering are the real ones. Decorative: the map behind stays the thing
   you interact with. */
.pm-context {
  pointer-events: none;
}
.pm-context .plot {
  fill: rgba(243, 236, 224, 0.06);
  stroke: rgba(243, 236, 224, 0.3);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
}
.pm-context .plot-g.is-subject .plot {
  fill: rgba(200, 86, 60, 0.28);
  stroke: var(--terracotta);
  stroke-width: 3px;
  vector-effect: non-scaling-stroke;
}
/* Numerals are drawn in user units, so a tighter viewBox inflates them —
   app.js sets --pm-num from the frame width to hold their apparent size. */
.pm-context .plot-num {
  /* The plate's own numeral face — without this the clone falls back to the
     body font and the numbers stop matching the map they came from. */
  font-family: "Plex Mono", monospace;
  font-size: var(--pm-num, 12px);
  letter-spacing: 0.04em;
  /* Full white at zoom (Saba, 8 Aug): the numeral is the phone-call handle
     ("plot 47") — at dossier scale it must read instantly, not at 62%. The
     dossier's background is the clean aerial, so an ink casing (drawn under
     the fill via paint-order) keeps white legible over bright meadow. */
  fill: #fff;
  paint-order: stroke;
  stroke: rgba(20, 17, 14, 0.6);
  stroke-width: calc(var(--pm-num, 12px) * 0.14);
  stroke-linejoin: round;
  opacity: 1;
}
.pm-context .plot-g.is-subject .plot-num {
  fill: #fff;
}
.pm-detail {
  padding: clamp(1.5rem, 4vh, 3rem) clamp(1.6rem, 5vw, 5rem);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  width: 100%;
  max-width: 42rem;
  margin-inline: auto;
}
.pm-status {
  margin: 0 0 0.3rem;
  font-family: "Plex Mono", monospace;
  font-size: 0.66rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--terracotta-text); /* audit Medium 1: small text needs 4.5:1 */
}
.pm-title {
  margin: 0 0 1rem;
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: 1.45rem;
  line-height: 1.15;
}
.pm-facts {
  list-style: none;
  margin: 0 0 1.3rem;
  padding: 0;
  border-top: 1px solid rgba(36, 31, 27, 0.18);
}
.pm-facts li {
  padding: 0.5rem 0.1rem;
  border-bottom: 1px solid rgba(36, 31, 27, 0.12);
  font-family: "Plex Mono", monospace;
  font-size: 0.74rem;
  letter-spacing: 0.03em;
  display: flex;
  justify-content: space-between;
  gap: 1.2rem;
}
.pm-facts li span:last-child {
  color: rgba(36, 31, 27, 0.62);
  text-align: right;
}
.pm-price {
  margin: 0 0 1.1rem;
}
/* The monthly figure is the headline (room decision, 6 Aug): it is the number a
   buyer weighs. Total and per-m² stay legible but drop to a second tone. This is
   the existing accent slot doing new work - no layout change. */
.pm-price-value {
  display: block;
  font-family: "Mersad", sans-serif;
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.1;
}
.pm-price-value small {
  font-size: 0.5em;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: rgba(36, 31, 27, 0.62);
}
.pm-price-rate {
  display: block;
  margin-top: 0.3rem;
  font-family: "Plex Mono", monospace;
  font-size: 0.8em;
  letter-spacing: 0.02em;
  color: rgba(36, 31, 27, 0.78);
}
.pm-price-note {
  display: block;
  margin-top: 0.25rem;
  font-family: "Plex Mono", monospace;
  font-size: 0.75em;
  letter-spacing: 0.02em;
  color: rgba(36, 31, 27, 0.62);
}
.pm-cta {
  display: inline-block;
  align-self: flex-start;
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cream);
  /* audit Medium 1: cream text on fill needs 4.5:1 */
  background: var(--terracotta-deep);
  padding: 0.9em 1.7em;
  border-radius: 999px;
  transition: background 0.25s;
}
.pm-cta:hover {
  background: var(--cream);
  color: var(--night);
}
.pm-close {
  position: absolute;
  top: clamp(1rem, 3.5vh, 2.2rem);
  right: clamp(1rem, 3.5vw, 2.4rem);
  width: 46px;
  height: 46px;
  border: 1px solid rgba(244, 237, 223, 0.5);
  border-radius: 50%;
  background: rgba(12, 11, 9, 0.35);
  cursor: pointer;
  transition:
    background 0.25s,
    border-color 0.25s;
}
.pm-close::before,
.pm-close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 1.5px;
  background: var(--cream);
}
.pm-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}
.pm-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.pm-close:hover {
  background: rgba(200, 86, 60, 0.75);
  border-color: transparent;
}
body.pm-open {
  overflow: hidden;
}
@media (max-width: 720px) {
  .pm-dossier {
    grid-template-columns: 1fr;
    grid-template-rows: 34vh 1fr;
    width: 100%;
    height: 100%;
  }
  .pm-survey {
    border-right: none;
    border-bottom: 1px solid rgba(36, 31, 27, 0.12);
  }
  .pm-detail {
    padding: 1.4rem 1.3rem;
    justify-content: flex-start;
    max-width: none;
  }
}
/* ---------- sticky CTA: appears once the hero has scrolled by, rests
   while the contact closer is on stage or the plot immersion is open ---- */
.sticky-cta {
  position: fixed;
  right: clamp(1.2rem, 4vw, 2.4rem);
  bottom: max(1.2rem, env(safe-area-inset-bottom));
  z-index: 40; /* above the header (20), below the plot modal (60) */
  display: inline-block;
  font-family: "FiraGO", sans-serif;
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cream);
  /* audit Medium 1: cream text on fill needs 4.5:1 */
  background: var(--terracotta-deep);
  text-decoration: none;
  padding: 0.9em 1.7em;
  border-radius: 999px;
  box-shadow: 0 14px 34px -10px rgba(12, 11, 9, 0.55);
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
  transition:
    opacity 0.35s ease,
    transform 0.35s ease,
    background 0.25s ease,
    box-shadow 0.25s ease,
    visibility 0s 0s;
}
.sticky-cta:hover {
  background: var(--cream);
  color: var(--night);
}
/* the browser's own [hidden] rule is display:none, which can't transition —
   override it so the pill fades/settles instead of popping in and out.
   visibility is flipped only after the fade finishes, so the pill leaves
   the tab order / AT tree instead of sitting invisible-but-focusable. */
.sticky-cta[hidden] {
  display: inline-block;
  opacity: 0;
  transform: translateY(14px);
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 0.35s ease,
    transform 0.35s ease,
    background 0.25s ease,
    box-shadow 0.25s ease,
    visibility 0s 0.35s;
}
/* the mobile nav panel lives in the .site-head stacking context, but the
   sticky CTA (and the Messenger button stacked above it) is bottom-anchored
   inside <main> — on short/landscape phones the open panel and the corner
   pair can overlap, so hide both while the panel is open */
.site-head.nav-open ~ main .sticky-cta,
.site-head.nav-open ~ main .sticky-msgr {
  display: none;
}
@media (max-width: 640px) {
  .sticky-cta {
    right: 1rem;
    font-size: 0.82rem;
    padding: 0.7em 1.3em;
  }
}
/* stacks above the CTA pill; stays put when the CTA rests on #contact */
.sticky-msgr {
  position: fixed;
  right: clamp(1.2rem, 4vw, 2.4rem);
  bottom: calc(max(1.2rem, env(safe-area-inset-bottom)) + 3.6rem);
  z-index: 40;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  color: var(--cream);
  background: var(--pine);
  box-shadow: 0 14px 34px -10px rgba(12, 11, 9, 0.55);
  transition: background 0.25s ease;
}
.sticky-msgr:hover {
  background: var(--terracotta);
}
.sticky-msgr svg {
  width: 24px;
  height: 24px;
}
.sticky-msgr[hidden] {
  display: none;
}
body.pm-open .sticky-msgr {
  display: none;
}
@media (max-width: 640px) {
  .sticky-msgr {
    right: 1rem;
    bottom: calc(max(1.2rem, env(safe-area-inset-bottom)) + 3.3rem);
  }
}

@media (max-width: 640px) {
  /* At phone width the map is ~220px tall and the legend card was covering
     two-fifths of it (8 Aug, 390px check). The caption goes; the four keys
     read as one slim strip. */
  .survey-legend-card {
    max-width: none;
    padding: 0.45em 0.7em;
  }
  .survey-legend-card figcaption {
    display: none;
  }
  .map-legend {
    font-size: 0.62rem;
    gap: 0.3rem 0.6rem;
    /* audit High 1: forcing one line reads as a slim strip at normal size, but
       left the card's own max-width:none free to grow past the viewport once
       200% text couldn't fit on that line - wrap (the base rule's default)
       still renders as one line whenever it fits. */
    flex-wrap: wrap;
  }
  .survey-figure figcaption {
    font-size: 0.6rem;
  }
}

/* ═══ real orthophoto plate ══════════════════════════════════════════════
   Roads must read the same everywhere. A translucent fill cannot do that on
   a real photograph - it takes the colour of whatever is beneath, so the same
   road is pale over meadow and dark over canopy. On the deployed AI plate it
   only looked uniform because that background was uniform.

   So the surface is opaque, set to the tone the deployed roads actually read
   as (#a29c90, sampled from the live map), with an ink casing for definition.
   Roads are drawn two ways in the overlay - internal as a filled shape, the
   access road and bridge as a stroked path - and both are matched here.
   ══════════════════════════════════════════════════════════════════════ */
.survey-overlay .roads-ink {
  fill: #a29c90;
  stroke: #a29c90;
  stroke-width: 0.6;
}
.survey-overlay .conn-road {
  stroke: #a29c90;
  stroke-width: 21.4;
}
.survey-overlay .conn-road.sand {
  stroke: #a29c90;
  stroke-width: 20.8;
}

/* The overlay paints a near-black road surface as a full-canvas rect masked to
   the road network. The existing rule targeted `.road-body > rect`, but the
   rect actually sits inside `.roads-sand` - so it never matched, and the dark
   layer showed through on the access road and bridge. Match it where it is. */
.survey-overlay rect[mask="url(#roadSurf)"] {
  display: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   SURVEY OPTION B — WIREFRAME.  Approved 6 Aug, shipped 7 Aug, replacing
   option A (cream filled parcels).  The land reads THROUGH the drawing: the
   survey is a drawing on the photograph, not a plan laid over it.

   Applied to both surfaces deliberately — the land plate (.survey-overlay)
   and the dossier's contextual zoom (.pm-context), which is a clone of the
   plate and must not read as a different map.

   Road rules look odd for three reasons, every one of them learned the hard
   way.  Read SURVEY-OVERLAY.md before touching them:
     1. No stroke on .roads-ink — the shape is a two-pass union with internal
        seams, so a stroke draws a line down the middle of the carriageway.
     2. No casing on .conn-road — it left a white stub above the estate.
     3. rect[mask="url(#roadSurf)"] must be hidden; it lives in .roads-sand,
        not .road-body, so the obvious rule never matched it.
   ───────────────────────────────────────────────────────────────────────── */
.survey-overlay .plot-tex,
.survey-overlay .plots,
.pm-context .plot-tex,
.pm-context .plots {
  fill: transparent;
}
.survey-overlay .plot,
.pm-context .plot {
  fill: rgba(255, 255, 255, 0.2);
  stroke: rgba(255, 255, 255, 0.92);
  stroke-width: 1.15;
}
/* Sold plots are the brand terracotta at full opacity - the exact --terracotta
   token, the same colour as the CTA button, verified against it rather than
   matched by eye (7 Aug). It reads hotter here than on cream because terracotta
   is near-opposite green: simultaneous contrast, not a wrong colour. Deliberately
   NOT a map-specific variant - one terracotta in the system, and a palette change
   flows through. */
.survey-overlay .plot.sold {
  fill: var(--terracotta);
  stroke: rgba(255, 255, 255, 0.92);
}
/* Inside the dossier the terracotta comes OFF (7 Aug call): accent belongs to
   the selected plot alone, so a sold neighbour reads like any other neighbour.
   Status lives on the main map; the zoom is about one plot's ground. */
.pm-context .plot.sold {
  fill: rgba(255, 255, 255, 0.2);
  stroke: rgba(255, 255, 255, 0.92);
}
.survey-overlay .plot:hover {
  fill: rgba(200, 86, 60, 0.75);
}
/* Keyboard focus (roving tabindex, app.js initPlotAccessibility): the mint
   ring already used for dossier selection below, reused here so keyboard
   and mouse land on the same "this one" language. Stroke only, no filter -
   the zero-resting-filter doctrine in this file (search "GPU") is a survey-
   wide rule, not a dossier-only one. The global [tabindex]:focus-visible
   outline near the top of this file is overridden here on purpose: a
   rectangular outline over an irregular parcel boundary reads as a wrong
   shape, not a selection. */
.survey-overlay .plot:focus-visible {
  outline: none;
  stroke: #7ee8a8;
  stroke-width: 3;
}
/* Sold plots came out as solid rust under option B, outweighing the available
   ones — backwards for a sales map (open question in survey-variants/README).
   Colour now carries the meaning on its own, so the hatch comes off. */
.survey-overlay .sold-mark,
.pm-context .sold-mark {
  display: none;
}
.survey-overlay .roads-ink,
.pm-context .roads-ink {
  fill: rgba(46, 38, 30, 0.42);
  stroke: none;
}
.survey-overlay .conn-road,
.pm-context .conn-road {
  stroke: transparent;
}
.survey-overlay .conn-road.sand,
.pm-context .conn-road.sand {
  stroke: rgba(46, 38, 30, 0.42);
  stroke-width: 20.8;
}
.survey-overlay .roads-sketch .sketch-road,
.pm-context .roads-sketch .sketch-road {
  stroke: transparent;
}
.survey-overlay rect[mask="url(#roadSurf)"],
.pm-context rect[mask="url(#roadSurf)"] {
  display: none;
}
/* The subject plot.  NOT terracotta - that is what "sold" means on this map, and
   using it for selection made the two indistinguishable (7 Aug).  Colour carries
   STATUS here; selection is focus, carried by the lit boundary ALONE: the room's
   verdict (7 Aug call) is that any fill - solid or tint - hides where the forest
   actually reaches into the plot, and the ground is the one thing the buyer came
   to see.  Steady glow, no pulse ("განათება საკმარისია, ციმციმი აღარ დასჭირდება"). */
.pm-context .plot-g.is-subject .plot {
  fill: transparent;
  stroke: #7ee8a8;
  stroke-width: 3.5;
  /* NO filter here, ever: a resting drop-shadow on this ring misrendered on a
     real GPU as displaced ghost copies (8 Aug) - the glow lives in the
     .subject-halo geometry app.js inserts under this ring. */
}
/* The bloom, baked as geometry: the same clean cadastral ring drawn twice more
   underneath - wide and faint, then mid - so the boundary reads lit, steadily.
   Non-scaling strokes hold the glow's apparent width at any dossier zoom. */
.pm-context .subject-halo {
  fill: none;
  stroke: #7ee8a8;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  stroke-linecap: round;
}
/* The pulse the room liked (Saba, 8 Aug) - the halos breathe; the crisp ring
   stays steady so the boundary itself never blurs. Same 1.7s beat as the
   original. Animating stroke width/opacity on geometry is safe - it was the
   FILTER that ghosted, not the motion. */
.pm-context .subject-halo-wide {
  stroke-width: 14;
  stroke-opacity: 0.14;
  animation: haloPulseWide 1.7s ease-in-out infinite;
}
.pm-context .subject-halo-mid {
  stroke-width: 7;
  stroke-opacity: 0.3;
  animation: haloPulseMid 1.7s ease-in-out infinite;
}
@keyframes haloPulseWide {
  0%,
  100% {
    stroke-opacity: 0.14;
    stroke-width: 14;
  }
  50% {
    stroke-opacity: 0.4;
    stroke-width: 30;
  }
}
@keyframes haloPulseMid {
  0%,
  100% {
    stroke-opacity: 0.3;
    stroke-width: 7;
  }
  50% {
    stroke-opacity: 0.6;
    stroke-width: 14;
  }
}
/* Anyone asking for less motion keeps the lit boundary, still glowing, still. */
@media (prefers-reduced-motion: reduce) {
  .pm-context .subject-halo {
    animation: none;
  }
}
