/* studio token foundation for bosques-mirador-herradura */
/* Generated by foundry.py. SHARED across concepts: `site` embeds this WHOLE
   file (tokens :root + base layer) at the top of each vN styles.css, then
   binds its direction's density posture in one explicit line:
     :root { --section-pad: var(--section-pad-<posture>); --flow: var(--flow-<posture>); }
   Edit ramps/scales here; pick fonts + an art direction per concept. */
:root {
  /* --- brand color ramps (50 light .. 900 dark) --- */
  /* brand */
  --brand-50: #f0f1ef;
  --brand-100: #e0e3df;
  --brand-200: #c1c8bf;
  --brand-300: #9ba596;
  --brand-400: #6c7c66;
  --brand-500: #3e5236;
  --brand-600: #35472e;
  --brand-700: #2d3b27;
  --brand-800: #232e1e;
  --brand-900: #192116;
  /* accent */
  --accent-50: #f4f3ec;
  --accent-100: #eae7d9;
  --accent-200: #d4d0b3;
  --accent-300: #bab283;
  --accent-400: #9a8f49;
  --accent-500: #7a6b10;
  --accent-600: #695c0e;
  --accent-700: #584d0c;
  --accent-800: #443c09;
  --accent-900: #312b06;

  /* --- semantic roles (WCAG-AA verified by foundry.py) --- */
  --color-bg: #f4f1e8;
  --color-brand: #3e5236;
  --color-accent: #7a6b10;
  --color-ink: #232a1d; /* deep body ink (target >=7:1 on bg) */
  --color-muted: #555a4e; /* secondary text on bg (>=5:1) */
  --color-on-brand: #ffffff; /* text on a brand fill */
  --color-on-accent: #ffffff; /* text on an accent fill */

  /* --- dark-band vocabulary (proof bands, footers, closes) --- */
  --surface-dark: #232e1e;
  --on-dark: #f4f1e8; /* text on the dark band */
  --on-dark-muted: #abada1; /* secondary text on the dark band */
  --hairline: rgba(35, 42, 29, 0.22); /* rules/borders on light surfaces */
  --hairline-dark: rgba(244, 241, 232, 0.28); /* rules/borders on dark bands */

  /* --- extra color "corteza" (direction-named, contrast-checked) --- */
  --corteza: #c9b42e;
  --corteza-deep: #ad9b28;
  --on-corteza: #232a1d; /* text on a corteza fill */

  /* --- extra color "pacifico" (direction-named, contrast-checked) --- */
  --pacifico: #8fb0c4;
  --pacifico-deep: #7b97a9;
  --on-pacifico: #232a1d; /* text on a pacifico fill */

  /* --- extra color "laterita" (direction-named, contrast-checked) --- */
  --laterita: #6f5639;
  --laterita-deep: #5f4a31;
  --on-laterita: #f4f1e8; /* text on a laterita fill */

  /* --- fluid type scale (clamp: 360px .. 1240px viewport) --- */
  --step-6: clamp(2.4rem, 1.664rem + 3.27vw, 4.2rem);
  --step-5: clamp(2rem, 1.509rem + 2.18vw, 3.2rem);
  --step-4: clamp(1.7rem, 1.414rem + 1.27vw, 2.4rem);
  --step-3: clamp(1.4rem, 1.236rem + 0.73vw, 1.8rem);
  --step-2: clamp(1.2rem, 1.098rem + 0.45vw, 1.45rem);
  --step-1: clamp(1.1rem, 1.059rem + 0.18vw, 1.2rem);
  --step-0: clamp(1rem, 0.98rem + 0.09vw, 1.05rem);
  --step--1: clamp(0.875rem, 0.865rem + 0.05vw, 0.9rem);
  --step--2: clamp(0.78rem, 0.772rem + 0.04vw, 0.8rem);
  /* poster steps for the ONE oversized moment (hero word, giant footer
     wordmark) — overflow-safe with the base layer's wrap rules */
  --step-display: clamp(3rem, 1.839rem + 5.16vw, 7rem);
  --step-poster: clamp(4.2rem, 1.935rem + 10.06vw, 12rem);
  --leading-tight: 1.1;
  --leading-snug: 1.3;
  --leading-normal: 1.6;

  /* --- type craft tokens --- */
  --track-display: -0.02em; /* negative tracking for display/poster sizes */
  --track-caps: 0.08em; /* positive tracking for caps eyebrows/labels */
  --measure-body: 65ch; /* readable body line length */
  --measure-tight: 45ch; /* leads, captions, intro columns */
  --measure: var(--measure-body); /* legacy alias */

  /* --- fluid spacing scale (clamp: tighter on phones, generous on desktop) --- */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: clamp(1.25rem, 1.148rem + 0.45vw, 1.5rem);
  --space-lg: clamp(1.75rem, 1.648rem + 0.45vw, 2rem);
  --space-xl: clamp(2.5rem, 2.295rem + 0.91vw, 3rem);
  --space-2xl: clamp(3rem, 2.591rem + 1.82vw, 4rem);
  --space-3xl: clamp(4rem, 3.182rem + 3.64vw, 6rem);
  --space-4xl: clamp(6rem, 4.773rem + 5.45vw, 9rem);
  --space-5xl: clamp(8rem, 5.545rem + 10.91vw, 14rem);

  /* --- density postures (a concept binds ONE explicitly — never rely on
     the fallback silently; the design-director checks the binding) --- */
  --section-pad-airy: var(--space-5xl);
  --flow-airy: var(--space-2xl);
  --section-pad-measured: var(--space-4xl);
  --flow-measured: var(--space-xl);
  --section-pad-dense: var(--space-3xl);
  --flow-dense: var(--space-lg);
  /* resilience fallback only — the concept's own binding must override: */
  --section-pad: var(--section-pad-measured);
  --flow: var(--flow-measured);

  /* --- corner language: sharp (0px base) --- */
  --radius-0: 0;
  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 6px;

  /* --- shadow scale (keep restrained; hairlines over shadows) --- */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.16);

  /* --- motion --- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 140ms;
  --dur-base: 260ms;
  --dur-slow: 520ms;

  /* --- chrome --- */
  --anchor-offset: 5.5rem; /* anchored-section clearance under a fixed header */
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0ms;
    --dur-base: 0ms;
    --dur-slow: 0ms;
  }
}

/* =====================================================================
   Foundation base layer — stress-proof defaults shared by every concept.
   Embed together with the tokens above; everything is :where()-wrapped
   (zero specificity) so any concept rule overrides it.
   REQUIRED companion, inline in <head> BEFORE the stylesheet link:
     <script>
       document.documentElement.classList.add("js");
       if (new URLSearchParams(location.search).get("shot") === "1")
         document.documentElement.setAttribute("data-shot", "");
     </script>
     <style>img{max-width:100%;height:auto}</style>
   (JS-off pages then render complete, and reveals never flash on slow loads.)
   ===================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}
/* brand-tone ground behind opaque photos, so a slow or failed image never
   leaves a hole (transparent png/svg marks deliberately excluded) */
:where(img[src$=".jpg"], img[src$=".jpeg"], img[src$=".webp"]) {
  background-color: var(--brand-100, #e9e9e4);
}

/* a long unbreakable token (a name, a pasted URL) wraps instead of forcing
   horizontal overflow; `anywhere` on headings also lets grid/flex tracks shrink */
:where(h1, h2, h3, h4) {
  overflow-wrap: anywhere;
}
:where(p, li, dt, dd, figcaption, blockquote, cite) {
  overflow-wrap: break-word;
}

/* display type carries the craft tracking by default (override per concept) */
:where(h1, h2, h3) {
  letter-spacing: var(--track-display);
}

/* selection themed from brand — the finish detail every premium site has */
::selection {
  background: #3e5236;
  color: #ffffff;
}

/* anchored sections clear a fixed header on jump; tune --anchor-offset per concept */
:where([id]) {
  scroll-margin-top: var(--anchor-offset);
}

/* visible focus floor (restyle per concept, never remove) */
:where(:focus-visible) {
  outline: 3px solid var(--color-accent, currentColor);
  outline-offset: 3px;
}

/* Reveal contract: hidden-before-reveal ONLY once the head snippet set html.js,
   so content is complete with JS off. The concept's JS adds .is-in to show. */
html.js :where([data-reveal]) {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
}
html.js :where([data-reveal].is-in) {
  opacity: 1;
  transform: none;
}

/* Capture + accessibility freeze: everything rests at its final state */
html[data-shot] :where([data-reveal]),
html.no-motion :where([data-reveal]) {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}
html[data-shot] {
  scroll-behavior: auto !important;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto !important;
  }
  :where([data-reveal]) {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}
/* =====================================================================
   v2 · La Subida — concept layer
   (flagship run-1 RUNNER-UP, promoted from _flagship/run-1/B-1)
   Direction B (dossier/direction/directions.md). Stance: photographic
   immersion. Zodiak + Supreme, dark-leading analogous green and gold,
   full-bleed flyover fold, five named waypoint bands, paper resolve.
   ===================================================================== */

:root {
  /* density posture — DENSE, bound explicitly per the direction */
  --section-pad: var(--section-pad-dense);
  --flow: var(--flow-dense);

  --font-display:
    "Zodiak", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-text: "Supreme", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --gutter: clamp(1.1rem, 4vw, 3.25rem);
  --shell: 1240px;
  /* full-bleed bands stop at this width so a 1280px master is never
     resampled past ~1.5x. Beyond it the deep forest ground frames the
     photograph, which is the page's own composition, not a fallback */
  --bleed-max: 1920px;
  /* the one scrim tone, used by the header, the fold and every band */
  --scrim: 15 21 12;
  --straddle: var(--space-3xl);
  --head-h: 4.9rem;
  --anchor-offset: 6.5rem;
}

html {
  background: var(--surface-dark);
}

body {
  margin: 0;
  background: var(--surface-dark);
  color: var(--on-dark);
  font-family: var(--font-text);
  font-size: var(--step-0);
  line-height: var(--leading-normal);
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}
body.no-scroll {
  overflow: hidden;
}

::selection {
  background: var(--corteza);
  color: var(--color-ink);
}

:focus-visible {
  outline: 2px solid var(--corteza);
  outline-offset: 4px;
}
.g-paper :focus-visible,
.foot :focus-visible {
  outline-color: var(--color-accent);
}

.wrap {
  width: min(100% - (2 * var(--gutter)), var(--shell));
  margin-inline: auto;
}

/* hostile-content hardening: the base layer wraps prose and headings, these are
   the remaining text surfaces where an unbreakable run could widen the page */
.nav a,
.drawer a,
.field label,
.measure-table th,
.measure-table td,
button {
  overflow-wrap: anywhere;
}

.skip {
  position: fixed;
  left: var(--gutter);
  top: -6rem;
  z-index: 90;
  background: var(--corteza);
  color: var(--color-ink);
  padding: 0.55rem 0.9rem;
  font-size: var(--step--1);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  text-decoration: none;
  transition: top var(--dur-base) var(--ease-out);
}
.skip:focus {
  top: 1rem;
}

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- one photographic voice: the deepened grade ---------- */
.ph {
  filter: saturate(0.82) brightness(0.92) contrast(1.03);
  background-color: var(--brand-800);
}
.plate,
.band-fig,
.hero {
  position: relative;
}

/* =========================== header =========================== */
.head {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--gutter);
  min-height: var(--head-h);
  color: var(--on-dark);
  transition:
    background var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
  border-bottom: 1px solid transparent;
}
/* The header rides the fold's sky, which is the brightest thing on the page. The ramp is
   held near full strength all the way through the wordmark and the caps nav, and its tail
   is thrown well BELOW the header so the falloff reads as a soft cinematic top-of-frame,
   not a bar with an edge.
   RE-MEASURED for the photographic fold, and it needed strengthening: hero-bosque-bahia
   puts white cloud straight behind the wordmark, and the alphas that carried the flyover
   left `.mark-b` at 4.13:1 against #f4f1e8, under the 4.5:1 body floor. At these stops the
   worst background pixel inside each text rect gives 6.2:1 for the wordmark, 6.7:1 for its
   second line and 8.6:1 for the nav.
   TWO measurement traps, both hit in this project: sampling the brightest pixels INSIDE a
   text box returns the cream glyphs and the ink measures against itself (1.10:1 for type
   that is plainly legible), and hiding the header to expose its background with
   `visibility:hidden` hides `::before` with it, so the scrim being measured disappears.
   Set the type to `color: transparent` and sample the rect instead. */
.head::before {
  content: "";
  position: absolute;
  inset: 0 0 -5rem 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgb(var(--scrim) / 0.78) 0%,
    rgb(var(--scrim) / 0.72) 30%,
    rgb(var(--scrim) / 0.6) 52%,
    rgb(var(--scrim) / 0) 100%
  );
  transition: opacity var(--dur-base) var(--ease-out);
}
.head.is-stuck {
  background: var(--surface-dark);
  border-bottom-color: var(--hairline-dark);
}
.head.is-stuck::before {
  opacity: 0;
}
.head.on-paper {
  color: var(--color-ink);
}
.head.on-paper.is-stuck {
  background: var(--color-bg);
  border-bottom-color: var(--hairline);
}

.mark {
  display: block;
  text-decoration: none;
  color: inherit;
  margin-right: auto;
}
.mark-a {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--step-1);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  line-height: 1.05;
}
.mark-b {
  display: block;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: 0.34em;
  /* the size drop and the 0.34em tracking already carry the hierarchy under
     mark-a, so this line does not also need a dimming opacity — over the fold's
     sky that opacity was the difference between passing and failing AA */
  margin-top: 0.34em;
}

.nav ul {
  display: flex;
  gap: clamp(1rem, 2.1vw, 2.1rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav a {
  position: relative;
  display: inline-block;
  color: inherit;
  text-decoration: none;
  font-family: var(--font-display);
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  padding-block: 0.3rem;
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav a:hover::after,
.nav a:focus-visible::after {
  transform: scaleX(1);
}
.nav .nav-cta::after {
  transform: scaleX(1);
  background: var(--corteza);
}
.head.on-paper .nav .nav-cta::after {
  background: var(--color-accent);
}
.nav .nav-cta:hover::after {
  background: currentColor;
}

.tools {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}
.lang,
.burger,
.drawer-x,
.vid-ctl,
.send {
  font: inherit;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
/* The language switch is a preference, not the conversion path, so it carries
   the QUIETER of the two chrome treatments: a hairline underline, which is
   exactly what aman-desktop.png does with "English" while it reserves the
   boxed/filled control for "Reserve". The outlined box belongs to .head-cta
   below. Inverting these two was the mobile fold's one real defect — the box
   sat on [ES] while the only conversion path was 13,000px down the page. */
.lang {
  font-family: var(--font-display);
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border: 0;
  border-bottom: 1px solid currentColor;
  border-radius: 0;
  padding: 0.38rem 0.1rem 0.28rem;
  line-height: 1;
  white-space: nowrap;
  transition:
    color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}
.lang:hover {
  color: var(--corteza);
  border-bottom-color: var(--corteza);
}
.head.on-paper .lang:hover {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

/* The one outlined CTA the copy kit's Mode B fold calls for (copy.md: "wordmark
   lockup, thin nav, one outlined CTA, full-bleed motion"). It appears only
   BELOW the burger breakpoint, where .nav — and with it the nav's Enquire —
   goes display:none, so the phone fold keeps a visible conversion path instead
   of a boxed language toggle and nothing else. The Papagayo mobile anchor pins
   the same control in the same place beside its burger. */
.head-cta {
  display: none;
  font-family: var(--font-display);
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: inherit;
  text-decoration: none;
  border: 1px solid var(--corteza);
  border-radius: var(--radius-sm);
  padding: 0.42rem 0.62rem;
  line-height: 1;
  white-space: nowrap;
  transition:
    background var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}
.head-cta:hover {
  background: var(--corteza);
  border-color: var(--corteza);
  color: var(--color-ink);
}
.head.on-paper .head-cta {
  border-color: var(--color-accent);
}
.head.on-paper .head-cta:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.head-cta:active,
.lang:active,
.burger:active,
.drawer-x:active,
.send:active,
.vid-ctl:active,
.cue:active {
  transform: translateY(1px);
}
.burger {
  display: none;
  padding: 0.35rem;
}

/* =========================== drawer =========================== */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--brand-900);
  color: var(--on-dark);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-3xl) var(--gutter);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity var(--dur-base) var(--ease-out),
    visibility var(--dur-base);
}
.drawer.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.drawer-x {
  position: absolute;
  top: var(--space-md);
  right: var(--gutter);
  padding: 0.35rem;
}
.drawer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-sm);
}
.drawer a {
  color: inherit;
  text-decoration: none;
  font-family: var(--font-display);
  font-size: var(--step-3);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-bottom: 1px solid var(--hairline-dark);
  display: block;
  padding-bottom: 0.45rem;
  transition:
    color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}
.drawer a:hover {
  border-bottom-color: var(--corteza);
  color: var(--corteza);
}
.drawer-foot {
  margin: var(--space-xl) 0 0;
  font-size: var(--step--1);
  letter-spacing: 0.06em;
}
.drawer-foot a {
  color: var(--corteza);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

/* =========================== the fold =========================== */
.hero {
  height: 100svh;
  min-height: 32rem;
  overflow: hidden;
  /* the fold shares the bands' bleed cap, so the widest viewports frame the
     photograph rather than resampling it edge to edge */
  width: 100%;
  max-width: var(--bleed-max);
  margin-inline: auto;
}
/* The fold is a PHOTOGRAPH now, not a clip. The owner asked for a still here and for
   the video to move down the page, and the still fold earns its keep differently: a
   copy-free viewport was defensible while it was moving, so with the motion gone the
   fold carries the thesis instead (copy.md's Mode A headline, the one the kit authored
   for exactly this posture). The two display lines that used to say the same two
   sentences in the middle of the page are deleted with it, which is most of what made
   the scroll feel repetitive. */
.hero-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* hero-bosque-bahia is 1.78:1, so at any normal window the fold box is NARROWER than
     the source and X is the live axis: 48% holds the Herradura headland and the open
     water just left of centre, where the frame puts them. Only on a short wide window
     does height become the cropped axis, and 50% keeps the horizon mid-frame there. */
  object-position: 48% 50%;
  display: block;
  background: var(--brand-800);
}
.hero-grad {
  position: absolute;
  inset: auto 0 0 0;
  /* taller and stronger than the flyover's scrim, because the fold now carries type
     over the canopy instead of nothing at all. Measured against #f4f1e8 on the built
     page, not eyeballed. */
  height: 64%;
  background: linear-gradient(
    to top,
    rgb(var(--scrim) / 0.88),
    rgb(var(--scrim) / 0.52) 34%,
    rgb(var(--scrim) / 0)
  );
}
.hero-copy {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--space-2xl);
  z-index: 3;
}
/* the clip box: the only positioned ancestor the pause control needs, so the control
   sits in the VIDEO's bottom-right corner and never under the fixed header */
.clip {
  position: relative;
  display: block;
  overflow: hidden;
}
.clip > video.ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.vid-ctl {
  position: absolute;
  bottom: var(--space-sm);
  right: var(--space-sm);
  z-index: 4;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border: 1px solid var(--hairline-dark);
  color: var(--on-dark);
  /* 0.34 was enough over the flyover's canopy. This control now sits on breaking
     whitewater, which is the brightest surface on the page, so it carries a real scrim
     or the glyph disappears into the spray. references.md calls the explicit pause
     affordance the #1 anchor's craft tell, which means it has to be findable. */
  background: rgb(var(--scrim) / 0.62);
  transition:
    background var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}
.vid-ctl:hover {
  background: var(--corteza);
  border-color: var(--corteza);
  color: var(--color-ink);
}
.vid-ctl .i-play {
  display: none;
}
.vid-ctl.is-paused .i-play {
  display: block;
}
.vid-ctl.is-paused .i-pause {
  display: none;
}
.cue {
  position: absolute;
  right: var(--gutter);
  bottom: var(--space-lg);
  color: var(--on-dark);
  opacity: 0.8;
  transition:
    opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}
.cue:hover {
  opacity: 1;
  transform: translateY(3px);
}

/* =========================== grounds =========================== */
.g-dark {
  background: var(--surface-dark);
  color: var(--on-dark);
}
.g-canopy {
  background: var(--brand-500);
  color: var(--color-on-brand);
}
.g-paper {
  background: var(--color-bg);
  color: var(--color-ink);
}

.beat {
  padding-block: var(--section-pad);
}
.band-sec + .beat {
  padding-top: var(--space-2xl);
}
.waypoint-sec {
  padding-top: var(--section-pad);
}
.band-sec {
  padding: 0;
}
.measure-sec {
  padding-top: var(--section-pad);
  padding-bottom: 0;
}
.resolve {
  padding-block: var(--section-pad);
}

/* =========================== typography =========================== */
h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 400;
  margin: 0;
}
p {
  margin: 0;
}

.eyebrow {
  font-family: var(--font-text);
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--corteza);
  margin-bottom: var(--space-md);
}
/* SET BY THE BAND, not by taste. references.md's most important number is bimodal, not a
   range: five of the six survivors carry NO display type at the fold and the sixth
   (Discovery, the #1 anchor) sets a headline at 4.0% of viewport height. "Anything between
   reads as a hedge", and a huge headline over a scrim photo is called out there as both
   tells.md cliché #4 and measurably off-band for this niche. So the size is expressed in
   the unit the band is measured in — 4svh — with the type scale's own steps as floor and
   cap for short windows and for phones. It lands at 40px / 4.0% at 1440x1000 and 32.6px /
   3.9% at 390x844, which is the anchor's posture to within a rounding error. It was 6.7%
   first, measured, and that is exactly the hedge the band warns about. */
.lede {
  font-size: clamp(var(--step-4), 4svh, var(--step-5));
  line-height: 1.12;
  letter-spacing: var(--track-display);
  max-width: none;
}
.lede-sub {
  margin-top: var(--space-lg);
  max-width: 42ch;
  color: var(--on-dark-muted);
  font-size: var(--step-1);
  line-height: 1.5;
}
/* The waypoint rail is GONE from the fold, and the reason is a measurement. Its four
   proper nouns pushed the first viewport to 38 words against a measured band of 7 to 28,
   and of the two candidates for the cut it was the one that was charm rather than
   argument: the sub carries the 64-of-74-acres ratio, which is the sharpest fact on the
   page for the reader this is written for. Without it the fold is a photograph, a two-line
   headline, one quiet sub-line and a scroll cue, which is the #1 anchor's fold exactly.
   The walk still announces itself, in the four poster-scale waypoint names below and in
   the climb rail that draws the ascent. */
.hero-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-md) clamp(1.5rem, 4vw, 4rem);
  align-items: end;
}
.hero-grid .lede {
  grid-column: 1 / span 7;
}
.hero-grid .lede-sub {
  grid-column: 9 / span 4;
  align-self: end;
  margin-top: 0;
  padding-bottom: 0.2em;
  /* over a photograph the muted ink is not enough: measured on the built fold this
     needs the full cream to clear AA against the scrimmed canopy */
  color: rgba(244, 241, 232, 0.94);
}

.beat-copy h3,
.measure-copy h3,
.docs-copy h3,
.paths-grid h3,
.seasons-copy h3 {
  text-wrap: balance;
  font-size: var(--step-4);
  line-height: 1.12;
  letter-spacing: var(--track-display);
  margin-bottom: var(--space-md);
  max-width: 18ch;
}
.beat-copy p,
.seasons-copy p {
  color: var(--on-dark-muted);
  max-width: 46ch;
}
/* the reset zeroes every p margin, so a beat with two paragraphs ran them together as one
   block of text. The water beat is the only one that has two, and its second paragraph is
   the third-party quotation, which has to read as a separate statement */
.beat-copy p + p {
  margin-top: var(--space-sm);
}
/* .display / .display-right are gone with the two mid-page poster lines. They said
   "The road is cut." and "The view is chosen." — which is now the fold's headline, so
   in the body they were the page repeating its own opening twice. */
/* a Latin binomial italicises and does NOT translate, so it sits outside the data-es
   span rather than inside it (the language swap writes textContent and would eat markup) */
.bino {
  font-style: italic;
}
.cap-line {
  margin-top: var(--space-lg);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--on-dark-muted);
  max-width: 34ch;
}

/* =========================== waypoints (type over the image edge) === */
.waypoint {
  position: relative;
  z-index: 3;
  font-size: clamp(var(--step-5), 7.4vw, var(--step-display));
  line-height: 0.9;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--on-dark);
  margin-top: -0.56em;
}
/* the masked line contract, shared by the lede and every waypoint */
.mask span {
  display: block;
  overflow: hidden;
  padding-bottom: 0.09em;
}
.mask span > i {
  display: block;
  font-style: normal;
}
html.js .mask:not(.is-in) span > i {
  transform: translateY(112%);
}
html.js .mask span > i {
  transition: transform 820ms var(--ease-out);
}
html.js .mask.is-in span:nth-child(2) > i {
  transition-delay: 110ms;
}
html.js .mask.is-in span:nth-child(3) > i {
  transition-delay: 220ms;
}
html[data-shot] .mask span > i,
html.no-motion .mask span > i {
  transform: none !important;
  transition: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .mask span > i {
    transform: none !important;
    transition: none !important;
  }
}

/* =========================== full-bleed bands =========================== */
.band-fig {
  width: 100%;
  max-width: var(--bleed-max);
  margin-inline: auto;
  height: clamp(23rem, 92svh, 58rem);
  overflow: hidden;
}
/* .band-fig-tall is gone with El Corte's band. Four waypoints now, not five: the road
   and the pad were a second telling of El Sendero's own paragraph ("the access road is
   graded to the top, the building pad is levelled"), so the evidence photo moved into
   that beat and the duplicate band came out. valle-verde is 1.78:1 against a 1.74:1
   band and needs no height of its own. */
/* The corteza texture used to hold a waypoint slot as a 26svh letterbox. Two reasons,
   both void: the master was 960x420 (it is 2560x1638 since the re-source), and a flat
   blossom texture cannot open a waypoint the way the gate itself can. The texture is
   the seam below now, where thin is the point and where it reads as the bloom's own
   fallen ground rather than as a second gate photograph. */
/* And the seam is out too, 2026-07-29, on the owner's word: "the flower photo is too thin
   and we already use a same flower photo above." Both halves of that are right. El Portón's
   band is two thirds fallen blossom at 92svh, so a 24svh strip of the same carpet under it
   restated a photograph the page had just given a whole viewport to, and a strip that thin
   abutting a 92svh band reads as a mistake rather than as a seam. images.md does call this
   master "ideal as a full-width thin band" — but a crop plan says how a photograph CAN be
   shown, never that the page needs a third telling of one subject. */
.band-fig .ph {
  position: absolute;
  inset: -7% 0 auto 0;
  width: 100%;
  height: 114%;
  object-fit: cover;
}
html[data-shot] .band-fig .ph,
html.no-motion .band-fig .ph {
  inset: 0;
  height: 100%;
  transform: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .band-fig .ph {
    inset: 0;
    height: 100%;
    transform: none !important;
  }
}
.band-fig::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  z-index: 2;
  background: linear-gradient(
    to top,
    rgb(var(--scrim) / 0.9),
    rgb(var(--scrim) / 0)
  );
}
.band-plain {
  margin: var(--space-xl) 0 0;
  width: 100%;
  max-width: var(--bleed-max);
  margin-inline: auto;
}
/* sized for panorama-pad: at the 1920 bleed this is about 2.4:1 against a 2.52:1 master,
   so almost the whole sweep survives, which is the entire reason images.md allows this
   master only as a full-bleed band */
.band-plain > .ph {
  width: 100%;
  height: clamp(15rem, 58svh, 34rem);
  object-fit: cover;
}
.band-plain figcaption {
  margin-top: var(--space-xs);
  font-size: var(--step--2);
  letter-spacing: 0.02em;
  color: var(--color-muted);
}

/* .strip is gone: a 56svh band of closed canopy carried no information the four
   canopy photographs around it did not already carry, and it was half a viewport. */

/* =========================== plates =========================== */
.plate {
  margin: 0;
  display: block;
}
.plate .ph {
  width: 100%;
  height: auto;
  object-fit: cover;
  display: block;
}
.plate > .ph {
  aspect-ratio: 3 / 2;
}
.plate-tall > .ph {
  aspect-ratio: 4 / 5;
}
.plate-port > .ph {
  aspect-ratio: 3 / 4;
}
.plate-wide > .ph {
  aspect-ratio: 16 / 9;
}
/* the trail marker and the road now sit in ONE row, so they must not be the same box:
   the marker is square, the road is portrait and staggered down (see .sendero-grid).
   .plate-cut keeps its name because the road IS the cut, but the photograph in it changed
   on 2026-07-29: camino-bosque (the road climbing under canopy) for camino-corte (the pad
   from above, which sillas-mirador and panorama-pad already tell later). The new master is
   exactly 3/4, so this box crops nothing at any width, which is the whole reason the plate
   did not have to be re-shaped around it. */
.plate-sq > .ph {
  aspect-ratio: 1 / 1;
}
.plate-cut > .ph {
  aspect-ratio: 3 / 4;
}
/* porton-umbral is out: it was the gate from further down the track, directly under a
   full-bleed band of the same gate. Same subject twice in one waypoint. */
/* corteza-floracion is out with the seam. It was the page's weakest photograph and the
   crop plan is the reason it could not be rescued: images.md rules PORTRAIT OUT and SQUARE
   only maybe (W ✓ L ✓ S ~ P ✗) because the yellow crown is about a tenth of the frame wide
   and mid-frame, so the only crop allowed was the widest one, a 2.9:1 letterbox across the
   whole shell — itself thin, mostly green canopy, with dry scrub hills behind it working
   against the sentence it sat under. A caption had to tell the reader what the subject was.
   Nothing about a master that can only be shown one way, and does not read that way, is
   worth a row.
   dosel-cielo replaces it and inverts every one of those constraints: images.md marks it
   P ✓ S ✓ (W ✗), the sky gap is upper-centre at `55% 45%`, and it is the one frame in the
   set taken from UNDER the canopy looking up, where every other photograph is eye-level or
   from a drone. It illustrates the half of the paragraph that had no picture. */
.plate-dosel > .ph {
  aspect-ratio: 3 / 4;
}
/* The fall is shown tall: images.md warns a wide band "now cuts the drop", and that is
   even truer of the clip, which is a 720x1280 portrait. quebrada is shown a touch squarer
   so the pair never reads as two copies of one shape. */
.plate-fall > .clip {
  aspect-ratio: 3 / 4;
}
.plate-stream > .ph {
  aspect-ratio: 4 / 5;
}
.plate figcaption {
  margin-top: var(--space-xs);
  font-size: var(--step--2);
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: var(--on-dark-muted);
  max-width: 40ch;
}

/* =========================== beat grids =========================== */
.beat-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  align-items: center;
}
.beat-right {
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
}
.beat-right .beat-copy {
  grid-column: 1;
}
.beat-right .plate {
  grid-column: 2;
}

.porton-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
}
/* Two rows became one. With the wide bloom letterbox gone the beat is a text column against
   a tall photograph, and the two text blocks are CENTRED as a pair against it rather than
   pinned to the column's top and foot. That was the first build and the render killed it:
   a 4-line paragraph at the top and a citation at the bottom of a 645px column left 400px
   of void between them, which reads as a hole, not as air. The plate spans both rows, so
   grid hands each row half the leftover height; `end` on the paragraph and `start` on the
   citation then pull both toward the seam between the rows, and they meet in the middle one
   flow-gap apart. It is also shorter than the stack it replaces, which is the direction the
   owner asked the whole page to move in. */
.porton-grid .porton-copy {
  grid-column: 1 / span 6;
  grid-row: 1;
  align-self: end;
}
.porton-grid .porton-cap {
  grid-column: 1 / span 5;
  grid-row: 2;
  align-self: start;
  margin-top: 0;
}
.porton-grid .plate-dosel {
  grid-column: 8 / span 5;
  grid-row: 1 / span 2;
}

/* El Sendero absorbed El Corte. The groundwork paragraph already names the road and the
   pad, so its evidence photograph belongs beside the trail marker rather than under a
   waypoint band of its own. The two are kept UNLIKE on purpose — square against
   portrait, and the taller one dropped down the row — because two portraits at one size
   is the uniform tell. */
.sendero-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
}
.sendero-grid .sendero-copy {
  grid-column: 1 / span 4;
  align-self: center;
}
.sendero-grid .plate-sq {
  grid-column: 5 / span 4;
}
.sendero-grid .plate-cut {
  grid-column: 9 / -1;
  margin-top: var(--space-2xl);
}

/* This is the beat that MOVES. The owner asked for the video to leave the fold and named
   the falls as a candidate, and the falls are the right slot: running water is the one
   subject on this page a photograph cannot carry, and "the water starts on the property"
   is the claim it evidences. The clip replaces the catarata STILL in the same box, so
   the section costs no extra length. The stream stays a photograph beside it, and the
   two verticals stay deliberately UNEQUAL — the fall spans both rows at five columns,
   the stream takes four under the copy. Two portraits at one size is the uniform tell. */
.quebrada-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
}
.quebrada-grid .plate-fall {
  grid-column: 1 / span 5;
  grid-row: 1 / span 2;
  align-self: stretch;
  display: flex;
  flex-direction: column;
}
.quebrada-grid .plate-fall > .clip {
  flex: 1 1 auto;
  min-height: 0;
  aspect-ratio: auto;
}
.quebrada-grid .beat-copy {
  grid-column: 7 / -1;
  grid-row: 1;
}
.quebrada-grid .plate-stream {
  grid-column: 7 / span 4;
  grid-row: 2;
}

.seasons-copy {
  margin-top: var(--space-2xl);
  margin-bottom: var(--space-xl);
}
.seasons-copy h3,
.seasons-copy p {
  max-width: 46ch;
}
.diptych {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--hairline-dark);
  width: 100%;
  max-width: var(--bleed-max);
  margin-inline: auto;
  margin-top: var(--space-xl);
}
.diptych .plate > .ph {
  aspect-ratio: 5 / 4;
}
/* The registration pair. images.md: these two object-position values are COUPLED and
   must be re-verified against a render, never against the table, because they exist to put
   the Herradura headland on the same pixel in both frames.
   MEASURED in THIS box (a 5:4 half of the 1920 bleed, 712x570 at desktop) with a 5%
   percentage grid laid over both halves: the headland summit sits at x 28% / y 21% in the
   green frame and x 27% / y 21.5% in the dry one. So the pair registers to within about 1%
   of the plate width and half a percent of its height, roughly seven pixels, and the
   canonical values need no adjustment here. That is what the copy three lines above the
   diptych asks the reader to check, so it has to keep measuring true.
   Why the canonical values survive here and did NOT in v1: both masters are 4:3 and this
   box is 5:4, which crops only about 6% of the width, where v1's much taller box cropped
   far harder and needed the dry frame pulled a long way right. Note also that only ONE
   axis is adjustable in any box — the source fills the height here, so the Y half of
   object-position is inert and the vertical agreement above is the masters', not a tuning
   result. */
.diptych .plate-season-a > .ph {
  object-position: 46% 42%;
}
.diptych .plate-season-b > .ph {
  object-position: 34% 34%;
}
.diptych figcaption {
  margin-top: 0;
  padding: var(--space-xs) var(--space-md);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  background: var(--surface-dark);
  /* the caption bar spans its own frame — never the 40ch plate measure, which
     leaves the container hairline showing as a grey rectangle beside it */
  max-width: none;
}

/* =========================== the measure (canopy ground) ============ */
.measure-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
}
.measure-copy {
  grid-column: 1 / span 6;
}
.measure-table {
  grid-column: 8 / span 5;
}
.measure-copy h3 {
  color: var(--color-on-brand);
}
.measure-copy p {
  color: rgba(244, 241, 232, 0.9);
  font-size: var(--step-1);
  line-height: 1.55;
  max-width: 44ch;
}
.measure-table table {
  width: 100%;
  border-collapse: collapse;
}
.measure-table th,
.measure-table td {
  border-top: 1px solid var(--hairline-dark);
  padding-block: var(--space-sm);
  text-align: left;
  vertical-align: baseline;
}
.measure-table tr:last-child th,
.measure-table tr:last-child td {
  border-bottom: 1px solid var(--hairline-dark);
}
.measure-table th {
  font-family: var(--font-text);
  font-weight: 400;
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: rgba(244, 241, 232, 0.86);
  width: 52%;
}
/* Explicit widths on both numeric columns, because without them the two right-aligned
   cells collide: "8" at the right edge of the middle column read as one number with the
   cell beside it. Every FINAL value now lands on the same right edge (74 acres, 64 acres,
   233, 70, 8, 2, none) and the middle column carries only the hectare half of the two
   area rows. */
.measure-table td.num {
  width: 24%;
}
.measure-table td.num {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  text-align: right;
  white-space: nowrap;
  color: var(--color-on-brand);
}
/* the areas are the owner's figures and the counts below them are third-party, so the
   table says where one ends and the other begins with weight, not with a second table */
.measure-table tr.rule-above th,
.measure-table tr.rule-above td {
  border-top-width: 2px;
  border-top-color: var(--hairline-dark);
  padding-top: var(--space-md);
}
/* the veda line is the one a developer's counsel asks about first, so it is the row
   that carries the accent rather than the row with the largest number */
.measure-table tr.is-key td.num {
  color: var(--corteza);
}
.table-note {
  margin-top: var(--space-lg);
  font-size: var(--step--1);
  line-height: 1.5;
  color: rgba(244, 241, 232, 0.86);
  max-width: 46ch;
}

/* boundary-crossing plate: dark into paper */
.straddle {
  display: flex;
  flex-direction: column-reverse;
  margin-top: var(--space-3xl);
  margin-bottom: calc(-1 * var(--straddle));
  margin-left: auto;
  width: min(100%, 56rem);
  position: relative;
  z-index: 3;
}
.straddle > .ph {
  aspect-ratio: 4 / 3;
}
.straddle figcaption {
  color: rgba(244, 241, 232, 0.9);
  margin-top: 0;
  margin-bottom: var(--space-xs);
  max-width: none;
}

/* =========================== the paper resolve =========================== */
#development {
  padding-top: calc(var(--section-pad) + var(--straddle));
}
.g-paper h3 {
  color: var(--color-brand);
}
.g-paper p,
.g-paper li {
  color: var(--color-ink);
}
.g-paper .plate figcaption {
  color: var(--color-muted);
}

.paths-grid {
  display: grid;
  gap: var(--flow) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
/* the place beat used to be its own section under this one, on this same 4-then-7 split
   and repeating its section padding for forty words. It is row two here instead. */
.paths-grid > h3 {
  grid-column: 1 / span 4;
  grid-row: 1;
}
.paths {
  grid-column: 6 / span 7;
  grid-row: 1;
}
.place-copy {
  grid-column: 1 / -1;
  grid-row: 2;
  display: grid;
  grid-template-columns: subgrid;
  align-items: start;
  margin-top: var(--space-xl);
}
.place-copy h3 {
  grid-column: 1 / span 4;
}
.place-copy p {
  grid-column: 6 / span 7;
}
.paths-lead {
  font-size: var(--step-1);
}
.paths-list {
  list-style: none;
  margin: var(--space-lg) 0;
  padding: 0;
}
.paths-list li {
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-sm);
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.3;
}
.paths-list li:last-child {
  border-bottom: 1px solid var(--hairline);
}
.paths-note {
  color: var(--color-muted);
  max-width: 46ch;
}

/* the panorama band closes the development section now, so that section keeps its own
   air below it rather than butting the caption against the documents beat */
#development {
  padding-bottom: var(--space-2xl);
}

.docs-sec {
  padding-top: 0;
  padding-bottom: var(--space-2xl);
}
.docs-grid {
  display: grid;
  gap: var(--space-2xl) clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
}
.docs-copy {
  grid-column: 1 / span 6;
}
.docs-copy p {
  max-width: 46ch;
}
.form {
  grid-column: 8 / span 5;
  border-top: 2px solid var(--color-brand);
  padding-top: var(--space-lg);
}

.reach {
  margin: var(--space-xl) 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 var(--space-md);
  max-width: 30rem;
}
.reach dt {
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--color-muted);
  padding-block: var(--space-2xs);
  border-top: 1px solid var(--hairline);
}
.reach dd {
  margin: 0;
  padding-block: var(--space-2xs);
  border-top: 1px solid var(--hairline);
  font-variant-numeric: tabular-nums;
}
.reach a {
  color: var(--color-brand);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline);
  transition:
    border-color var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}
.reach a:hover {
  color: var(--color-accent);
  border-bottom-color: currentColor;
}
.todo {
  color: var(--color-accent);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
}

.form-title {
  font-family: var(--font-display);
  font-size: var(--step-3);
  letter-spacing: var(--track-display);
  margin-bottom: var(--space-md);
  color: var(--color-brand);
}
.field {
  display: grid;
  gap: 0.3rem;
  margin-bottom: var(--space-md);
}
.field label {
  font-size: var(--step--2);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--color-muted);
}
.field input,
.field select,
.field textarea {
  font: inherit;
  font-size: 1rem;
  color: var(--color-ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  border-radius: 0;
  padding: 0.5rem 0;
  width: 100%;
  transition: border-color var(--dur-base) var(--ease-out);
}
.field textarea {
  resize: vertical;
}
.field input:hover,
.field select:hover,
.field textarea:hover {
  border-bottom-color: var(--color-brand);
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  border-bottom-color: var(--color-accent);
}
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}
.field ::placeholder {
  /* --color-muted alone clears AA on paper; the opacity knocked it under */
  color: var(--color-muted);
  opacity: 1;
}
.send {
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-family: var(--font-display);
  font-size: var(--step--1);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  padding: 0.85rem 1.9rem;
  margin-top: var(--space-2xs);
  transition: background var(--dur-base) var(--ease-out);
}
.send:hover {
  background: var(--accent-700);
}
.form-note {
  margin-top: var(--space-sm);
  font-size: var(--step--2);
  color: var(--color-muted);
}

/* =========================== footer =========================== */
.foot {
  padding-block: var(--space-2xl) var(--space-lg);
  border-top: 1px solid var(--hairline);
}
.foot-mark {
  font-family: var(--font-display);
  color: var(--color-brand);
  font-size: min(var(--step-poster), 11.6vw);
  line-height: 0.84;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  margin-bottom: var(--space-2xl);
}
.foot-mark span {
  display: block;
}
.foot-mark-b {
  font-family: var(--font-text);
  font-size: 0.28em;
  letter-spacing: 0.32em;
  padding-top: 0.6em;
  color: var(--color-muted);
}
.foot-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-xl);
  justify-content: space-between;
  align-items: baseline;
  border-top: 1px solid var(--hairline);
  padding-top: var(--space-md);
}
.foot-where,
.foot-links {
  font-size: var(--step--1);
  color: var(--color-muted);
}
.foot-links {
  display: flex;
  gap: var(--space-lg);
  flex-wrap: wrap;
}
.foot-links a {
  color: var(--color-brand);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition:
    color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}
.foot-links a:hover {
  border-bottom-color: currentColor;
  color: var(--color-accent);
}
.foot-sign {
  margin-top: var(--space-lg);
  font-family: var(--font-display);
  font-size: var(--step-2);
  color: var(--color-ink);
  max-width: 30ch;
}

/* =========================== the climb rule (motion signature) ====== */
.climb {
  position: fixed;
  left: clamp(0.55rem, 1.5vw, 1.6rem);
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--hairline-dark);
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.climb.is-live {
  opacity: 1;
}
.climb i {
  position: absolute;
  inset: 0;
  background: var(--corteza);
  transform: scaleY(var(--p, 0));
  transform-origin: 50% 100%;
}
html[data-shot] .climb,
html.no-motion .climb {
  opacity: 1;
}
html[data-shot] .climb i,
html.no-motion .climb i {
  transform: scaleY(0);
}

/* =========================== responsive =========================== */
@media (min-width: 1700px) {
  :root {
    --shell: 1560px;
  }
}

@media (max-width: 1100px) {
  /* the burger swap is aligned with this compact breakpoint: below it the flex
     row is cramped enough that the nav labels break mid-word. The climb rail
     and the JS `wide` query (min-width: 1101px) share the same threshold so
     the signature is desktop-only in one place, not two. */
  .nav {
    display: none;
  }
  .burger {
    display: inline-flex;
  }
  /* the nav's Enquire disappears with the nav — the outlined header CTA takes
     over here so the fold never loses its conversion path */
  .head-cta {
    display: inline-block;
  }
  .climb {
    display: none;
  }

  .sendero-grid .sendero-copy {
    grid-column: 1 / -1;
    grid-row: 1;
  }
  /* at tablet the groundwork paragraph takes the full row and the two evidence plates
     share the one below it, still unlike each other */
  .sendero-grid .plate-sq {
    grid-column: 1 / span 6;
    grid-row: 2;
  }
  .sendero-grid .plate-cut {
    grid-column: 8 / -1;
    grid-row: 2;
    margin-top: 0;
  }
  /* At tablet the water beat gives the fall a column back and drops the stream under
     the copy at full width, so neither vertical is squeezed below a readable size. */
  .quebrada-grid .plate-fall {
    grid-column: 1 / span 6;
  }
  .quebrada-grid .beat-copy {
    grid-column: 8 / -1;
  }
  .quebrada-grid .plate-stream {
    grid-column: 8 / -1;
  }
  /* the gate beat keeps its two-block column against the vertical, and the vertical takes
     the column back that the narrower shell costs it */
  .porton-grid .porton-copy,
  .porton-grid .porton-cap {
    grid-column: 1 / span 6;
  }
  .porton-grid .plate-dosel {
    grid-column: 7 / -1;
  }
  .measure-copy {
    grid-column: 1 / span 7;
  }
  .measure-table {
    grid-column: 8 / span 5;
  }
  .place-copy h3 {
    grid-column: 1 / span 5;
  }
  .place-copy p {
    grid-column: 6 / -1;
  }
}

@media (max-width: 860px) {
  :root {
    --straddle: var(--space-lg);
    --head-h: 4.2rem;
    --anchor-offset: 5rem;
  }

  .beat-right,
  .porton-grid,
  .sendero-grid,
  .quebrada-grid,
  .measure-grid,
  .paths-grid,
  .docs-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .beat-right .beat-copy,
  .beat-right .plate,
  .hero-grid .lede,
  .hero-grid .lede-sub,
  .porton-grid .plate-dosel,
  .porton-grid .porton-copy,
  .porton-grid .porton-cap,
  .sendero-grid .plate-sq,
  .sendero-grid .plate-cut,
  .sendero-grid .sendero-copy,
  .quebrada-grid .plate-fall,
  .quebrada-grid .plate-stream,
  .quebrada-grid .beat-copy,
  .measure-copy,
  .measure-table,
  .paths-grid > h3,
  .paths,
  .place-copy,
  .place-copy h3,
  .place-copy p,
  .docs-copy,
  .form {
    grid-column: 1 / -1;
    /* one column means one item per row: the desktop explicit rows must be
       released here too, or the spans stack on top of each other */
    grid-row: auto;
  }
  .quebrada-grid .plate-fall,
  .quebrada-grid .plate-stream,
  .quebrada-grid .beat-copy,
  .sendero-grid .plate-cut {
    margin-top: 0;
  }
  .quebrada-grid {
    align-items: stretch;
  }
  /* the paper split collapses to plain flow on one column */
  .place-copy {
    display: block;
  }

  /* The fold's crop is horizontal at EVERY viewport (a 1.78:1 photograph is wider than
     any box shorter than a cinema screen), so X is the only live axis and the question is
     only how much of the width survives: about 90% at 1440, half at 860, a third at 390.
     This one value carries every narrow width down to 280 rather than snapping again at
     560. CHOSEN ON RENDERS: 45% is where the Herradura headland and the open water both
     stay inside the third of the frame a phone keeps, with enough canopy left of them to
     read as foreground. Further right and the bay goes behind the ridge, further left and
     the foreground goes. */
  .hero-img {
    object-position: 45% 50%;
  }

  .plate-tall > .ph,
  .plate-port > .ph {
    aspect-ratio: 4 / 5;
  }
  /* sendero-marcado and camino-corte are portrait masters (images.md marks both P) —
     a phone shows them portrait. Stacked in one column they still must not be the same
     box, so the marker keeps the shallower 4:5. The two water verticals already are
     portrait and stay unequal on one column too, so they are not swept in here. */
  .plate-sq > .ph {
    aspect-ratio: 4 / 5;
  }
  .plate-cut > .ph {
    aspect-ratio: 3 / 4;
  }
  /* One column is nearly the full width, so a 3:4 vertical here would run to about 480px
     on a 390 phone and make this beat TALLER than the two-row stack it replaced, which
     would undo the point of the change. images.md marks the master S ✓, so the phone gets
     the square: `cover` keeps the middle 75% of the frame's height and the sky gap sits at
     18% to 68%, so the whole gap survives the crop. */
  .plate-dosel > .ph {
    aspect-ratio: 1 / 1;
  }
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-grid .lede-sub {
    margin-top: var(--space-md);
    padding-bottom: 0;
  }
  .porton-grid .porton-copy {
    margin-top: 0;
  }
  .band-fig {
    height: clamp(18rem, 72svh, 40rem);
  }
  .waypoint {
    margin-top: -0.44em;
  }
  .band-mirador .ph {
    object-position: 50% 58% !important;
  }
  .diptych {
    grid-template-columns: 1fr;
    gap: var(--space-md);
    background: none;
  }
  /* both season frames survive a square crop (images.md), and stacked on a
     phone the square reads as one instrument rather than two thin strips */
  .diptych .plate > .ph {
    aspect-ratio: 1 / 1;
  }
  /* A square box crops the 4:3 pair harder than the desktop 5:4 box, so the coupled
     values are re-verified here on their own render. The headland must still land on the
     same spot in both, which is the claim the copy makes three lines above. */
  .diptych .plate-season-a > .ph {
    object-position: 46% 42% !important;
  }
  .diptych .plate-season-b > .ph {
    object-position: 34% 34% !important;
  }
  .band-plain > .ph {
    height: clamp(13rem, 42svh, 26rem);
  }
  /* .band-plain's caption already carries .wrap — a second inset double-insets
     it. The diptych captions are full-bleed and need the gutter instead. */
  .diptych figcaption {
    padding-inline: var(--gutter);
  }
  .form {
    margin-top: var(--space-lg);
  }
  .foot-mark {
    font-size: min(var(--step-display), 15vw);
  }
  .measure-sec .straddle {
    margin-top: var(--space-2xl);
  }
}

@media (max-width: 560px) {
  /* The crop is set once at 860 and carries down from there, so only the fold HEIGHT is
     decided here: 92svh rather than the desktop 100svh, so a phone's first viewport ends
     a little short and reads as a photograph the page continues under rather than as a
     slide. The headline and its sub sit inside that 92svh now, which is the change the
     still fold made necessary — a copy-free viewport was only defensible while it moved. */
  .hero {
    height: 92svh;
  }
  /* A phone header now carries four things (wordmark, ES, the outlined Enquire,
     the burger), so the lockup is compacted rather than left to wrap: both gaps
     tighten and the wordmark goes fluid with tighter tracking. Measured to hold
     one line at 360px in both languages, the narrowest width the conventions
     name, with the burger inside the gutter down to 280px. */
  .head {
    gap: var(--space-xs);
  }
  .tools {
    gap: 0.4rem;
  }
  /* the wordmark tracks the viewport so the lockup holds its two lines down to
     ~330px in BOTH languages (Spanish "Consultar" is two glyphs longer than
     "Enquire") and only wraps below that, where it wrapped before this CTA
     existed. Discovery and Papagayo both set very small phone wordmarks — the
     lockup, not its size, is what carries the mark here. */
  .mark-a {
    font-size: clamp(0.68rem, 3.1vw, 1.02rem);
    letter-spacing: 0.06em;
  }
  /* the second line scales WITH the first — a fixed --step--2 here would end up
     larger than the compacted mark-a and invert the lockup's hierarchy */
  .mark-b {
    font-size: clamp(0.6rem, 2.6vw, 0.85rem);
    letter-spacing: 0.16em;
  }
  .lang {
    letter-spacing: 0.1em;
  }
  .head-cta {
    padding: 0.42rem 0.4rem;
    letter-spacing: 0.06em;
  }
  .burger {
    padding: 0.28rem;
  }
  .burger svg {
    width: 20px;
    height: 20px;
  }
  .measure-table td.num {
    font-size: var(--step-1);
  }
  .measure-table th {
    width: 42%;
  }
  .reach {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .reach dd {
    border-top: 0;
    padding-top: 0;
    padding-bottom: var(--space-2xs);
  }
}

/* Below any real phone (the stress harness goes to 280) the four header
   controls stop fitting, and Spanish "Consultar" is the case that breaks
   first — left alone it pushes the burger off the right edge. Rather than
   drop the conversion path at the narrowest widths, the lockup's second line
   and the CTA both step down so all four stay reachable. */
@media (max-width: 340px) {
  .mark-b {
    letter-spacing: 0.1em;
  }
  .lang {
    letter-spacing: 0.06em;
  }
  .head-cta {
    font-size: 0.66rem;
    padding: 0.36rem 0.3rem;
    letter-spacing: 0.04em;
  }
}
