/* ============================================================
   MAIN STYLESHEET
   Depends on tokens.css. Avoid hard-coded colours in here —
   add a token instead so rebranding stays a one-file change.
   ============================================================ */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--space-4));
  /* `clip` contains overflow WITHOUT making this a scroll container.
     `overflow-x: hidden` here (or on body) would break position:sticky
     and hijack the document scroller. */
  overflow-x: clip;
}

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

body {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--text-body);
  background: var(--bg-page);

  /* ---- Text rendering -------------------------------------
     Scope note, because these are widely misunderstood:
     · -webkit-font-smoothing   macOS WebKit/Blink ONLY. It switches
       macOS off subpixel (RGB) AA onto grayscale, which makes text a
       little lighter. It is a NO-OP on Windows and Android, where the
       OS rasteriser (DirectWrite / Skia) decides.
     · -moz-osx-font-smoothing  macOS Firefox only.
     So this pair evens out the macOS-vs-everything-else weight
     difference. It cannot fix rendering on Windows — nothing in CSS can.

     Deliberately NOT set: `text-rendering: optimizeLegibility`. It is
     commonly cargo-culted here, but it only toggles ligatures/kerning,
     carries a real layout cost on long pages, and has a history of
     dropping glyphs. Fraunces and Inter already ship proper kerning. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* We load real 500/600/700 cuts of both families, so the browser must
     never synthesise a faux bold — smeared synthetic weights are a far
     more common cause of "blurry headings" than antialiasing is. */
  font-synthesis: none;
}

img, picture, video, canvas, svg { display: block; max-width: 100%; }
/* Must come after the display rule above, or [hidden] svgs stay visible */
[hidden] { display: none !important; }
input, button, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

/* ---------- Typography ---------- */

/* Marcellus is a static font with no variable axes, so the optical-size
   pinning that Fraunces needed here is gone. Nothing replaces it: setting
   font-variation-settings on a static face is at best ignored and at worst
   disables the kerning that comes with it. */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--text-strong);
  line-height: var(--lh-tight);
  font-weight: 600;
  letter-spacing: -0.015em;
}
h1 { font-size: var(--fs-4xl); }
h2 { font-size: var(--fs-3xl); }
h3 { font-size: var(--fs-xl); line-height: var(--lh-snug); }
h4 { font-size: var(--fs-lg); line-height: var(--lh-snug); }

/* A quieter second line inside a heading. `display: block` gives it its own
   line without a <br>, so the break is styling rather than content and a
   screen reader still reads one heading. Sized in `em` so it tracks the
   heading it sits in at every breakpoint rather than needing its own clamp. */
.h-sub {
  display: block;
  margin-top: var(--space-2);
  font-size: 0.6em;
  letter-spacing: -0.005em;
  color: var(--text-body);
}
.section--inverse .h-sub { color: var(--text-on-dark-muted); }

/* Balanced wrapping on short headings — progressive, UA-controlled */
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}
.eyebrow--light { color: var(--text-on-dark-muted); }

.lede {
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  color: var(--text-body);
  max-width: var(--container-text);
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent-hover); }

/* ---------- Focus (never remove, only restyle) ---------- */
:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  z-index: var(--z-toast);
  background: var(--c-navy);
  color: var(--text-on-dark);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--r-md);
  text-decoration: none;
  font-weight: 600;
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus { top: var(--space-4); color: var(--text-on-dark); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  /* clip-path is the modern property; `clip` is deprecated but is still the
     only one the oldest browsers honour, so both ship. Dropping either one
     shows screen-reader-only text to somebody. */
  /* stylelint-disable-next-line property-no-deprecated */
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* ---------- Layout ---------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-5);
}
@media (min-width: 768px)  { .container { padding-inline: var(--space-6); } }
@media (min-width: 1280px) { .container { padding-inline: var(--space-7); } }

.section { padding-block: var(--space-8); }
@media (min-width: 768px) { .section { padding-block: var(--space-9); } }

.section--sunk    { background: var(--bg-sunk); }
.section--inverse { background: var(--bg-inverse); color: var(--text-on-dark); }

/* ============================================================
   DECORATION
   Everything here is drawn from the brand — the swells and palms
   in the logo, and the sea-glass colours of the Oceano mosaic.
   All of it is CSS + masked SVG: no image requests, no weight,
   and it re-colours automatically if the palette changes.

   All decoration is aria-hidden / pointer-events:none and sits
   behind content, so it never affects contrast or interaction.
   ============================================================ */

/* A second .section rule on purpose: this one belongs to the decoration
   system described above, not to the layout block that sets section padding.
   They set disjoint properties and nothing between them touches .section. */
/* stylelint-disable-next-line no-duplicate-selectors */
.section { position: relative; }
.section > .container { position: relative; z-index: var(--z-raised); }

/* ---- Wave divider ----------------------------------------
   The swells from the mark, used to break a hard section edge.
   Set --wave-from to the colour of the section above.          */
.section--wave-top::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: clamp(22px, 3.2vw, 44px);
  background-color: var(--wave-from, var(--bg-page));
  pointer-events: none;
  -webkit-mask: var(--wave-shape) top center / 1200px 100% repeat-x;
          mask: var(--wave-shape) top center / 1200px 100% repeat-x;
}
:root {
  --wave-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 44' preserveAspectRatio='none'%3E%3Cpath d='M0 0h1200v18c-92 20-184 4-276-6s-184-14-276 4-184 26-276 12S72 6 0 16Z'/%3E%3C/svg%3E");
}

/* ---- Soft washes -----------------------------------------
   Light through shallow water. Very low alpha, so text
   contrast is untouched.                                      */
.section--wash {
  background-image:
    radial-gradient(60ch 40ch at 88% -10%, rgba(30, 155, 174, 0.10), transparent 70%),
    radial-gradient(50ch 34ch at 2% 108%, rgba(63, 122, 78, 0.08), transparent 70%);
}
.section--inverse.section--wash {
  background-image:
    radial-gradient(70ch 46ch at 92% 0%, rgba(127, 203, 214, 0.16), transparent 70%),
    radial-gradient(56ch 40ch at 0% 100%, rgba(30, 155, 174, 0.14), transparent 70%);
}

/* ---- Frond watermark -------------------------------------
   A single large frond ghosted into otherwise empty space.
   Hidden on small screens, where there is no dead space.      */
/* `clip` rather than `hidden`: it contains the frond without creating a
   scroll container, so position:sticky inside the section still works. */
.deco-frond { overflow: clip; }
.deco-frond::after {
  content: "";
  position: absolute;
  z-index: var(--z-base);
  width: clamp(240px, 34vw, 520px);
  aspect-ratio: 1;
  background-color: currentColor;
  opacity: 0.07;
  pointer-events: none;
  -webkit-mask: url("../img/brand/frond.svg") center / contain no-repeat;
          mask: url("../img/brand/frond.svg") center / contain no-repeat;
}
.deco-frond--tr::after { top: -4%;    right: -6%;  transform: scaleX(-1); }
.deco-frond--br::after { bottom: -8%; right: -5%; }
.deco-frond--bl::after { bottom: -8%; left: -7%;  transform: scaleX(-1); }
.section--inverse.deco-frond::after { opacity: 0.09; }

@media (max-width: 899px) {
  .deco-frond::after { display: none; }
}

/* ---- Full-bleed photo band -------------------------------
   The strongest antidote to flat sections: the photography
   itself, at full width, with a measured scrim so the text on
   top still clears WCAG AA.                                   */
.photo-band {
  position: relative;
  isolation: isolate;
  overflow: clip;
  min-height: clamp(240px, 34vw, 440px);
  display: grid;
  place-items: center;
  color: var(--c-white);
}
/* Short interstitial: a breather between content blocks rather than a
   full statement piece. */
.photo-band--short { min-height: clamp(180px, 22vw, 300px); }
.photo-band--short .photo-band__body { padding-block: var(--space-7); }

.photo-band__media { position: absolute; inset: 0; z-index: -1; }
.photo-band__media img { width: 100%; height: 100%; object-fit: cover; }
/* Two-layer scrim. The radial layer sits under the centred text and is
   strong enough that white type clears 4.5:1 even over a blown-out sky
   (worst case measured at 7.1:1); the linear layer only seats the band
   against the sections above and below, so the photo's edges stay open.
   A single 0.42 wash measured 2.95:1 here — not enough. */
.photo-band__media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(125% 95% at 50% 50%,
      rgba(8, 30, 47, 0.58) 0%,
      rgba(8, 30, 47, 0.34) 62%,
      rgba(8, 30, 47, 0.26) 100%),
    linear-gradient(180deg,
      rgba(8, 30, 47, 0.46) 0%,
      rgba(8, 30, 47, 0.32) 45%,
      rgba(8, 30, 47, 0.52) 100%);
}
.photo-band__body {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  max-width: 62ch;
}
/* A stat strip needs more room than a line of prose, or the last
   figure orphans onto its own row. */
.photo-band__body:has(.photo-band__stats) { max-width: min(94ch, 100%); }
.photo-band__body p.eyebrow { color: #DCE9F0; }
.photo-band blockquote,
.photo-band h2 {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  line-height: var(--lh-snug);
  color: var(--c-white);
  text-wrap: balance;
}
.photo-band cite,
.photo-band__note {
  display: block;
  margin-top: var(--space-4);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-style: normal;
  color: #DCE9F0;
}

/* Stat strip — facts over a photo, so the band earns its space */
.photo-band__stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5) var(--space-8);
  margin-top: var(--space-6);
  padding: 0;
  list-style: none;
}
.photo-band__stats li { text-align: center; }
.photo-band__stats b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.photo-band__stats span {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: #DCE9F0;
}

/* ---- Portrait image tiles --------------------------------
   A row of tall photo tiles with the label sitting on the
   image — the pattern Blue Horizon uses for its experiences
   row. Turns a list of text into something worth looking at. */
/* 150px min so a 375px phone still gets two across — four stacked
   full-width portrait tiles is 1,700px of scrolling for one section. */
.tile-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
}
@media (min-width: 700px) { .tile-grid { gap: var(--space-4); } }
.tile {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-lg);
  overflow: clip;
  isolation: isolate;
  text-decoration: none;
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--dur-mid) var(--ease-out),
              transform var(--dur-mid) var(--ease-out);
}
a.tile:hover { box-shadow: var(--shadow-3); transform: translateY(-4px); }
.tile img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
  transition: transform var(--dur-slow) var(--ease-out);
}
a.tile:hover img { transform: scale(1.05); }
/* Bottom scrim, strong enough that the label clears AA over any photo */
.tile::after {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgba(8, 30, 47, 0.10) 0%,
    rgba(8, 30, 47, 0.30) 45%,
    rgba(8, 30, 47, 0.80) 100%);
}
.tile__label {
  position: absolute;
  inset: auto 0 0;
  padding: var(--space-5) var(--space-4);
  color: var(--c-white);
}
.tile__label b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: var(--lh-snug);
}
.tile__label span {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--fs-sm);
  color: #E4EEF4;
}

/* ---- Diamond lattice -------------------------------------
   The rhombus from the mark, repeated as a faint lattice.
   Gives the flat sand blocks a surface without pattern noise. */
.section--tiles {
  background-image:
    repeating-linear-gradient(45deg,  rgba(12, 44, 69, 0.035) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(-45deg, rgba(12, 44, 69, 0.035) 0 1px, transparent 1px 26px);
}
.section--inverse.section--tiles {
  background-image:
    repeating-linear-gradient(45deg,  rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(-45deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 26px);
}

/* ---- Mosaic band -----------------------------------------
   Tesserae from the Oceano sign, as a thin ribbon that can sit
   under a section heading or close a block.                   */
.mosaic-rule {
  height: 10px;
  border-radius: var(--r-full);
  background-image: repeating-linear-gradient(
    90deg,
    var(--c-navy)      0 14px,
    var(--c-cobalt)   14px 26px,
    var(--c-turquoise) 26px 40px,
    var(--c-aqua)     40px 50px,
    var(--c-sand)     50px 58px
  );
  opacity: 0.85;
  margin-bottom: var(--space-5);
  max-width: 180px;
}
.section--inverse .mosaic-rule { opacity: 1; }
.section--inverse h2,
.section--inverse h3 { color: var(--text-on-dark); }
.section--inverse p  { color: var(--text-on-dark-muted); }

.section-head { max-width: var(--container-text); margin-bottom: var(--space-7); }
.section-head p { margin-top: var(--space-4); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 48px;               /* comfortable pointer + touch target */
  padding: var(--space-3) var(--space-6);
  border: 1px solid transparent;
  border-radius: var(--r-full);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn:active { transform: scale(0.98); }   /* no layout shift */

.btn--primary {
  background: var(--accent);
  color: var(--c-white);
  box-shadow: var(--shadow-1);
}
.btn--primary:hover { background: var(--accent-hover); color: var(--c-white); box-shadow: var(--shadow-2); }

.btn--warm { background: var(--accent-warm); color: var(--c-white); box-shadow: var(--shadow-1); }
.btn--warm:hover { background: var(--c-terracotta-dark); color: var(--c-white); box-shadow: var(--shadow-2); }

.btn--ghost {
  background: transparent;
  color: var(--text-strong);
  border-color: var(--border-strong);
}
.btn--ghost:hover { background: var(--bg-sunk); border-color: var(--text-muted); color: var(--text-strong); }

.btn--on-dark {
  background: transparent;
  color: var(--text-on-dark);
  border-color: rgba(255, 255, 255, 0.55);
}
.btn--on-dark:hover { background: rgba(255, 255, 255, 0.12); color: var(--text-on-dark); border-color: #fff; }

.btn--lg { min-height: 56px; padding: var(--space-4) var(--space-7); font-size: var(--fs-base); }
.btn--block { width: 100%; }

.btn[aria-disabled="true"], .btn:disabled {
  opacity: 0.45; cursor: not-allowed; pointer-events: none;
}

/* ---------- Header ---------- */
.header {
  position: fixed;
  inset: 0 0 auto;
  height: var(--header-h);
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  transition: background-color var(--dur-mid) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid) var(--ease-out);
  border-bottom: 1px solid transparent;
}
/* Transparent over the hero, solid once scrolled or on inner pages */
.header--transparent { background: linear-gradient(to bottom, rgba(12,44,69,0.55), transparent); }
.header--solid {
  background: rgba(251, 248, 244, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom-color: var(--border);
  box-shadow: var(--shadow-1);
}

.header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-5);
}
@media (min-width: 768px) { .header__inner { padding-inline: var(--space-6); } }

.brand { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; margin-right: auto; }

/* The mark is painted with `background-color: currentColor` through an SVG
   mask, so it inherits the brand colour from its context: white over the
   hero, ink on the solid header, light in the footer. An <img> could not do
   this — currentColor inside an external SVG cannot see the host page. */
/* The mark is now a photograph, so it can no longer be a currentColor mask —
   masking a photo flattens it to one solid colour. It is a background image
   instead, which keeps the markup a single empty <span> and avoids repeating
   a <picture> element a dozen times across the site.

   The plain PNG line comes first as the fallback: a browser that does not
   understand image-set() ignores the second declaration entirely and keeps
   the first. WebP is 12 KB against the PNG's 78 KB for the same image, which
   is worth having on a file that loads on every page. */
.brand__mark {
  flex: none;
  display: block;
  width: 31px;                 /* 76:100, the arch's true aspect */
  height: 41px;
  background-image: url("../img/brand/arch.png");
  background-image: image-set(
    url("../img/brand/arch.webp") type("image/webp"),
    url("../img/brand/arch.png")  type("image/png"));
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

/* "Shores" in the script, "OF VIEQUES" in letterspaced Marcellus beneath.
   Great Vibes sits high on its em box and carries long ascenders, so the
   line-height is pulled well under 1 to stop the lockup looking loose. */
.brand__text {
  font-family: var(--font-script);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 0.82;
  letter-spacing: 0;
}
.brand__sub {
  display: block;
  font-family: var(--font-display);
  font-size: 0.5rem;
  font-weight: 400;
  letter-spacing: 0.26em;
  /* The tracking above adds space after the final letter too, which throws
     the block off-centre; the indent puts it back. */
  text-indent: 0.26em;
  text-transform: uppercase;
  opacity: 0.9;
  margin-top: 0.35em;
}
.header--transparent .brand,
.header--transparent .nav__link { color: var(--c-white); }
.header--solid .brand,
.header--solid .nav__link { color: var(--text-strong); }

.nav { display: none; }
@media (min-width: 1024px) {
  .nav { display: flex; align-items: center; gap: var(--space-2); }
}
.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--r-full);
  font-size: var(--fs-sm);
  font-weight: 500;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.nav__link:hover { background: rgba(127, 203, 214, 0.22); }
.nav__link[aria-current="page"] { font-weight: 700; }
.nav__link[aria-current="page"]::after {
  content: ""; position: absolute; /* underline indicator */
}
.nav__item { position: relative; }
.nav__item [aria-current="page"] { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }

.header__cta { display: none; }
@media (min-width: 640px) { .header__cta { display: inline-flex; } }

/* Mobile menu toggle */
.nav-toggle {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 48px; height: 48px;
  background: transparent; border: 0; border-radius: var(--r-full);
  cursor: pointer; touch-action: manipulation;
}
@media (min-width: 1024px) { .nav-toggle { display: none; } }
.header--transparent .nav-toggle { color: var(--c-white); }
.header--solid .nav-toggle { color: var(--text-strong); }
.nav-toggle:hover { background: rgba(127, 203, 214, 0.22); }

.mobile-nav {
  position: fixed;
  inset: var(--header-h) 0 auto 0;
  z-index: var(--z-overlay);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-3);
  padding: var(--space-4) var(--space-5) var(--space-6);
  display: grid;
  gap: var(--space-1);
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
}
.mobile-nav[hidden] { display: none; }
.mobile-nav a {
  display: flex; align-items: center;
  min-height: 52px;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--r-md);
  color: var(--text-strong);
  text-decoration: none;
  font-weight: 500;
}
.mobile-nav a:hover { background: var(--bg-sunk); }
.mobile-nav a[aria-current="page"] { font-weight: 700; background: var(--bg-sunk); }

/* `.mobile-nav a` outranks `.btn--primary`, so the CTA inside the panel would
   inherit dark text on a coloured button (3.1:1). Restore the button colours. */
.mobile-nav a.btn { margin-top: var(--space-4); }
.mobile-nav a.btn--primary { background: var(--accent); color: var(--c-white); }
.mobile-nav a.btn--primary:hover { background: var(--accent-hover); color: var(--c-white); }
.mobile-nav a.btn--warm { background: var(--accent-warm); color: var(--c-white); }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: min(92dvh, 860px);
  display: flex;
  align-items: flex-end;
  color: var(--c-white);
  overflow: hidden;
}
.hero--short { min-height: min(62dvh, 560px); }

.hero__media { position: absolute; inset: 0; z-index: var(--z-base); }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
/* Scrim measured against the photo so headline text stays legible */
.hero__media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(8, 30, 47, 0.82) 0%, rgba(8, 30, 47, 0.38) 42%, rgba(8, 30, 47, 0.20) 70%, rgba(8, 30, 47, 0.35) 100%);
}

.hero__body {
  position: relative;
  z-index: var(--z-raised);
  width: 100%;
  padding-block: var(--space-8) var(--space-9);
}
/* The property heroes carry more text than the home page does, and it sits
   higher in the frame where the shared scrim is at its weakest. Measured
   against the Oceano photo, the eyebrow came out at 3.1:1 with the default
   gradient. This curve is tuned so every line of hero copy clears AA over
   the brightest pixel behind it. It replaces the shared scrim rather than
   layering on top of it, so there is one gradient to reason about.
   Not applied to --immersive: the home page hero has only a headline and a
   glass search pill, and darkening it would flatten the glass. */
.hero--short .hero__media::after {
  background: linear-gradient(to top,
    rgba(8, 30, 47, 0.90) 0%,
    rgba(8, 30, 47, 0.80) 40%,
    rgba(8, 30, 47, 0.66) 70%,
    rgba(8, 30, 47, 0.50) 88%,
    rgba(8, 30, 47, 0.38) 100%);
}
/* The muted on-dark grey is tuned for the flat navy footer, not for a photo.
   Over the hero it measured 3.4:1; this is the same colour the lede uses. */
.hero--short .eyebrow--light { color: #E8F1F6; }
.hero h1 { color: var(--c-white); max-width: 16ch; }
.hero__lede {
  margin-top: var(--space-5);
  max-width: 52ch;
  font-size: var(--fs-lg);
  color: #E8F1F6;
}
/* Rating line under the hero lede. Wraps to its own row on narrow screens
   rather than letting the stars and the sentence collide. */
.hero__proof {
  margin-top: var(--space-5);
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  color: #E8F1F6;
}
.hero__proof strong { color: var(--c-white); }
.hero__proof a { color: var(--c-white); text-underline-offset: 3px; }
.hero__actions {
  margin-top: var(--space-6);
  display: flex; flex-wrap: wrap; gap: var(--space-3);
}

/* ============================================================
   IMMERSIVE HERO  (Aman-style)
   Full-viewport media with a glass search pill docked bottom
   centre. Accepts a <video> or an <img> in the same slot.
   ============================================================ */
.hero--immersive {
  min-height: 100dvh;
  align-items: stretch;
  padding-bottom: 0;
}
.hero--immersive .hero__media video,
.hero--immersive .hero__media img {
  width: 100%; height: 100%; object-fit: cover;
}
/* A very slow drift keeps a still photo from reading as a dead
   backdrop. Purely decorative, so it is dropped for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .hero--immersive .hero__media > img,
  .hero--immersive .hero__media > video {
    animation: hero-drift 32s var(--ease-soft) infinite alternate;
  }
}
@keyframes hero-drift {
  from { transform: scale(1); }
  to   { transform: scale(1.07); }
}

.hero--immersive .hero__body {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: var(--space-5);
  padding-block: calc(var(--header-h) + var(--space-5)) var(--space-5);
}
@media (min-width: 860px) {
  .hero--immersive .hero__body {
    gap: var(--space-6);
    padding-block: calc(var(--header-h) + var(--space-8)) var(--space-7);
  }
}
.hero__headline { align-self: center; }

/* ---------- Glass search pill ---------- */
.search-pill {
  /* 0.78 alpha guarantees dark ink clears AA over any photo beneath —
     measured 9.7:1 over black, 16.5:1 over white. A thinner glass
     looked better but failed against bright sky. */
  background: rgba(255, 255, 255, 0.78);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
          backdrop-filter: blur(22px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--r-lg);
  box-shadow: 0 8px 32px rgba(8, 30, 47, 0.22);
  padding: var(--space-4);
  display: grid;
  gap: var(--space-3);
  width: min(100%, 940px);
  margin-inline: auto;
}
@media (min-width: 860px) {
  .search-pill {
    grid-template-columns: 1.3fr 1fr 1fr 0.8fr auto;
    align-items: end;
    border-radius: var(--r-full);
    padding: var(--space-3) var(--space-3) var(--space-3) var(--space-6);
    gap: var(--space-4);
  }
}
/* On a phone, five stacked rows pushed the pill past the fold — the one place
   it must never be. Pair the fields up so the whole hero fits 100dvh. */
@media (max-width: 859px) {
  .search-pill { grid-template-columns: 1fr 1fr; gap: var(--space-2) var(--space-3); }
  .search-pill__field:nth-child(1) { grid-column: 1 / -1; }
  .search-pill .btn { align-self: end; min-height: 48px; }
}

.search-pill__field { display: grid; gap: 2px; min-width: 0; }
.search-pill__field label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: #3E5163;                 /* 6.2:1 on the composited glass */
  padding-inline: var(--space-2);
}
.search-pill__field select,
.search-pill__field input {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--space-2);
  background: transparent;
  border: 0;
  border-radius: var(--r-md);
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--text-strong);
  appearance: none;
}
.search-pill__field select { cursor: pointer; }
.search-pill__field input::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .6; }
.search-pill__field select:focus-visible,
.search-pill__field input:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 1px;
}
.search-pill .btn { white-space: nowrap; }
@media (min-width: 860px) {
  .search-pill__field + .search-pill__field { border-left: 1px solid rgba(12, 44, 69, 0.16); padding-left: var(--space-4); }
}

/* ============================================================
   EDITORIAL GRID  (Aman-style)
   A 6-column bed. Items span 2-4 columns at deliberately
   different heights, so the page reads as a composed spread
   rather than a stack of equal bands. No flat filler blocks.
   ============================================================ */
.editorial {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .editorial {
    grid-template-columns: repeat(6, 1fr);
    gap: var(--space-5);
    align-items: stretch;
  }
  /* Spans — deliberately uneven */
  .ed-2 { grid-column: span 2; }
  .ed-3 { grid-column: span 3; }
  .ed-4 { grid-column: span 4; }
  /* Optical offset: nudge a block out of the row line */
  .ed-drop { margin-top: var(--space-7); }
}

.ed-media {
  position: relative;
  overflow: clip;
  border-radius: var(--r-lg);
  background: var(--bg-sunk);
  min-height: 220px;
}
.ed-media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
a.ed-media:hover img { transform: scale(1.04); }
.ed-media__cap {
  position: absolute; inset: auto 0 0;
  padding: var(--space-6) var(--space-5) var(--space-5);
  color: var(--c-white);
  background: linear-gradient(180deg, rgba(8,30,47,0) 0%, rgba(8,30,47,0.78) 100%);
}
.ed-media__cap b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 600;
  line-height: var(--lh-snug);
}
.ed-media__cap span { display: block; margin-top: var(--space-2); font-size: var(--fs-sm); color: #E4EEF4; }

/* A text block that sits in the grid without a filled background */
.ed-text { display: flex; flex-direction: column; justify-content: center; gap: var(--space-4); }
.ed-text > * { max-width: 46ch; }

/* ---------- A property's own listings, nested ----------
   Sun Bay and Media Luna are not properties. They are the two halves of
   Paradise Cove Suites, and set beside it as equal tiles they read as two
   more places to stay. The indent and the rule fix that structurally, so
   the hierarchy survives even when nobody reads the caption. The rule
   takes Paradise Cove's own accent, which ties the pair to their parent. */
.ed-nest {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  padding-left: var(--space-4);
  border-left: 2px solid var(--cove-accent);
}
.ed-nest__label {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  max-width: 60ch;
}
.ed-nest__label .eyebrow {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--cove-deep);
}

@media (min-width: 900px) {
  .ed-nest {
    grid-column: 1 / -1;
    grid-template-columns: repeat(6, 1fr);
    gap: var(--space-5);
    align-items: stretch;
    margin-left: var(--space-5);
    padding-left: var(--space-6);
  }
  .ed-nest__label { grid-column: 1 / -1; }
}

/* Row heights LAST — these share specificity with .ed-media, so they have to
   come after it in source order or its 220px floor wins and every block
   collapses to the same height, which is the exact thing we are avoiding. */
@media (min-width: 900px) {
  .ed-tall  { min-height: clamp(360px, 34vw, 620px); }
  .ed-mid   { min-height: clamp(280px, 26vw, 460px); }
  .ed-short { min-height: clamp(210px, 19vw, 340px); }
}

/* ---------- Cards ---------- */
.card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--dur-mid) var(--ease-out),
              transform var(--dur-mid) var(--ease-out);
}
.card:hover { box-shadow: var(--shadow-3); transform: translateY(-4px); }
.card__media { aspect-ratio: 4 / 3; background: var(--bg-sunk); }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__body { padding: var(--space-5) var(--space-5) var(--space-6); }
.card__title { margin-bottom: var(--space-2); }
.card__meta {
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  margin-bottom: var(--space-4);
}

/* ---------- Property cards (home) ---------- */
.property-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .property-grid { grid-template-columns: 1fr 1fr; gap: var(--space-7); } }

.property-card { position: relative; display: flex; flex-direction: column; }
.property-card__media { aspect-ratio: 3 / 2; }
.property-card__body { display: flex; flex-direction: column; flex: 1; padding: var(--space-6); }
.property-card__actions { margin-top: auto; padding-top: var(--space-5); display: flex; flex-wrap: wrap; gap: var(--space-3); }
.property-card__accent { height: 5px; }
.property-card--oceano .property-card__accent { background: var(--oceano-accent); }
.property-card--cove   .property-card__accent { background: var(--cove-accent); }

.price {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--text-strong);
}
.price small { font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted); }

/* ---------- Chips / badges ---------- */
.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  min-height: 30px;
  background: var(--bg-sunk);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-body);
  white-space: nowrap;
}
.chip svg { width: 15px; height: 15px; flex: none; }
.chip--accent { background: rgba(30, 155, 174, 0.12); border-color: rgba(30, 155, 174, 0.35); color: #0B5A66; }

/* ---------- Feature grid ---------- */
.feature-grid {
  display: grid; gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}
.feature { display: flex; flex-direction: column; gap: var(--space-3); }
.feature__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px;
  border-radius: var(--r-full);
  background: rgba(15, 92, 140, 0.10);
  color: var(--accent);
}
.section--inverse .feature__icon { background: rgba(255,255,255,0.12); color: var(--c-aqua); }
.feature__icon svg { width: 24px; height: 24px; }

/* ---------- Split / alternating content ---------- */
.split {
  display: grid; gap: var(--space-6);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--space-8); }
  .split--reverse .split__media { order: 2; }
}
.split__media img { width: 100%; border-radius: var(--r-lg); box-shadow: var(--shadow-2); aspect-ratio: 4/3; object-fit: cover; }
.split__body > * + * { margin-top: var(--space-4); }

/* ---------- Gallery ---------- */
/* Sized against the CONTAINER, not the viewport — the gallery sits in a
   narrow column on property pages and full width elsewhere. */
.gallery {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr));
}
@media (min-width: 700px) { .gallery { gap: var(--space-4); } }

.gallery__item {
  position: relative;
  padding: 0; border: 0;
  aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-sunk);
  cursor: zoom-in;
  touch-action: manipulation;
}
.gallery__item img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.gallery__item:hover img { transform: scale(1.05); }
.gallery__item--wide { grid-column: span 2; aspect-ratio: 2 / 1; }

/* Lightbox */
.lightbox {
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  display: grid; place-items: center;
  background: rgba(6, 22, 35, 0.94);
  padding: var(--space-4);
  border: 0;
}
.lightbox[hidden] { display: none; }
.lightbox__img { max-width: 100%; max-height: 82dvh; border-radius: var(--r-md); object-fit: contain; }
.lightbox__caption { color: var(--text-on-dark-muted); font-size: var(--fs-sm); margin-top: var(--space-3); text-align: center; }
.lightbox__btn {
  position: absolute;
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px;
  background: rgba(255,255,255,0.12);
  color: #fff; border: 1px solid rgba(255,255,255,0.30);
  border-radius: var(--r-full); cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.lightbox__btn:hover { background: rgba(255,255,255,0.24); }
.lightbox__close { top: var(--space-4); right: var(--space-4); }
.lightbox__prev  { left: var(--space-4);  top: 50%; transform: translateY(-50%); }
.lightbox__next  { right: var(--space-4); top: 50%; transform: translateY(-50%); }
.lightbox__btn svg { width: 24px; height: 24px; }

/* ---------- Booking widget slot ---------- */
.booking-slot {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-2);
}
.booking-slot__placeholder {
  border: 2px dashed var(--border-strong);
  border-radius: var(--r-md);
  padding: var(--space-6);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
.booking-slot__placeholder strong { display: block; color: var(--text-strong); margin-bottom: var(--space-2); font-size: var(--fs-base); }

.book-sticky {
  position: sticky;
  top: calc(var(--header-h) + var(--space-5));
}

.booking-layout { display: grid; gap: var(--space-7); grid-template-columns: 1fr; }
/* A grid item defaults to min-width:auto, so its widest indivisible child sets
   the floor for the track. The rate table is 460px wide, which on a 375px phone
   dragged the whole column out to 460 and let `overflow-x: clip` on <html>
   silently shear the right edge off the body copy — the table never got to
   scroll, because it was never the thing being squeezed. The desktop rule
   below already uses minmax(0, 1fr) for exactly this reason; the base case
   needs it too. Removing this brings the clipping straight back. */
.booking-layout > * { min-width: 0; }
@media (min-width: 1024px) {
  .booking-layout { grid-template-columns: minmax(0, 1fr) 400px; gap: var(--space-8); align-items: start; }
}

/* ---------- Document / download card ---------- */
.doc-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  text-decoration: none;
  box-shadow: var(--shadow-1);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              transform var(--dur-mid) var(--ease-out);
}
.doc-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}
.doc-card__icon {
  flex: none;
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--r-md);
  background: rgba(15, 92, 140, 0.10);
  color: var(--accent);
}
.doc-card__icon svg { width: 24px; height: 24px; }
.doc-card__body { min-width: 0; }
.doc-card__title {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--text-strong);
  line-height: var(--lh-snug);
}
.doc-card__desc { font-size: var(--fs-sm); color: var(--text-body); margin-top: var(--space-2); }
/* File type and weight, so nobody starts a 21 MB download by accident */
.doc-card__meta {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.section--inverse .doc-card { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.20); }
.section--inverse .doc-card__title { color: var(--text-on-dark); }
.section--inverse .doc-card__desc { color: var(--text-on-dark-muted); }
.section--inverse .doc-card__icon { background: rgba(255,255,255,0.12); color: var(--c-aqua); }

/* ---------- Jeep cards ---------- */
.jeep-grid { display: grid; gap: var(--space-6); grid-template-columns: 1fr; }
@media (min-width: 800px) { .jeep-grid { grid-template-columns: 1fr 1fr; } }

.jeep-card { display: flex; flex-direction: column; }
.jeep-card__accent { height: 5px; background: var(--accent-warm); }
.jeep-card__media { aspect-ratio: 16 / 10; }

/* ---------- Rate table ---------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.rates {
  width: 100%;
  min-width: 460px;
  border-collapse: collapse;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;   /* stops price columns jittering */
}
table.rates caption { text-align: left; color: var(--text-muted); font-size: var(--fs-sm); margin-bottom: var(--space-3); }
table.rates th, table.rates td { padding: var(--space-3) var(--space-4); text-align: left; border-bottom: 1px solid var(--border); }
table.rates thead th { background: var(--bg-sunk); font-weight: 600; color: var(--text-strong); white-space: nowrap; }
table.rates tbody tr:last-child td { border-bottom: 0; }
table.rates td.num, table.rates th.num { text-align: right; }

/* ---------- FAQ ---------- */
.faq { max-width: var(--container-text); }
.faq__item { border-bottom: 1px solid var(--border); }
.faq__item summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  min-height: 60px;
  padding: var(--space-4) 0;
  cursor: pointer;
  font-weight: 600;
  color: var(--text-strong);
  list-style: none;
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after {
  content: ""; flex: none;
  width: 12px; height: 12px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg) translateY(-25%);
  transition: transform var(--dur-mid) var(--ease-out);
}
.faq__item[open] summary::after { transform: rotate(225deg) translateY(-25%); }
.faq__answer { padding-bottom: var(--space-5); color: var(--text-body); }
/* Most answers are a single paragraph, so this never mattered until the
   longer ones arrived. Without it, consecutive paragraphs butt together and
   read as one block. */
.faq__answer > * + * { margin-top: var(--space-4); }

/* ---------- Forms ---------- */
.form { display: grid; gap: var(--space-5); }
.field { display: grid; gap: var(--space-2); }
.field__label { font-size: var(--fs-sm); font-weight: 600; color: var(--text-strong); }
.field__req { color: var(--danger); }
.field__hint { font-size: var(--fs-xs); color: var(--text-muted); }
.field__error { font-size: var(--fs-xs); color: var(--danger); font-weight: 600; }
.field__error:empty { display: none; }

.input, .select, .textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  font-size: var(--fs-base);   /* >=16px avoids iOS zoom-on-focus */
  color: var(--text-strong);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.textarea { min-height: 132px; resize: vertical; line-height: var(--lh-body); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--text-muted); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15, 92, 140, 0.18);
  outline: none;
}
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(163, 52, 31, 0.15);
}
.field-row { display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 600px) { .field-row { grid-template-columns: 1fr 1fr; } }

fieldset { border: 0; padding: 0; }
legend { font-size: var(--fs-sm); font-weight: 600; color: var(--text-strong); padding: 0; margin-bottom: var(--space-3); }

.choice {
  display: flex; align-items: flex-start; gap: var(--space-3);
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.choice:hover { background: var(--bg-sunk); }
.choice input { margin-top: 3px; width: 20px; height: 20px; accent-color: var(--accent); flex: none; }
.choice:has(input:checked) { border-color: var(--accent); background: rgba(15, 92, 140, 0.06); }
.choice__text { display: grid; gap: 2px; }
.choice__title { font-weight: 600; color: var(--text-strong); font-size: var(--fs-sm); }
.choice__desc { font-size: var(--fs-xs); color: var(--text-muted); }

.form-status {
  padding: var(--space-4);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: 500;
  border: 1px solid transparent;
}
.form-status[hidden] { display: none; }
.form-status--ok    { background: rgba(44,110,73,0.10);  border-color: rgba(44,110,73,0.35);  color: #1E5133; }
.form-status--error { background: rgba(163,52,31,0.10);  border-color: rgba(163,52,31,0.35);  color: #7E2716; }

.error-summary {
  padding: var(--space-4) var(--space-5);
  background: rgba(163, 52, 31, 0.08);
  border: 1px solid rgba(163, 52, 31, 0.35);
  border-radius: var(--r-md);
}
.error-summary[hidden] { display: none; }
.error-summary h3 { font-size: var(--fs-base); color: #7E2716; margin-bottom: var(--space-2); }
.error-summary ul { margin: 0; padding-left: var(--space-5); }
.error-summary a { color: #7E2716; font-weight: 600; }

/* ---------- Testimonials ---------- */
.quote-grid { display: grid; gap: var(--space-6); grid-template-columns: repeat(auto-fit, minmax(min(280px,100%), 1fr)); }
.quote {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-1);
  display: flex; flex-direction: column; gap: var(--space-4);
}
.quote blockquote { font-family: var(--font-display); font-size: var(--fs-lg); line-height: var(--lh-snug); color: var(--text-strong); }
.quote figcaption { font-size: var(--fs-sm); color: var(--text-muted); margin-top: auto; }
.stars { display: flex; gap: 2px; color: #C9922B; }
/* fill: currentColor is load-bearing — the stars are <use> references to a
   <symbol> whose path sets no fill, so without this they render black. */
.stars svg { width: 18px; height: 18px; fill: currentColor; }
/* On the dark hero the mustard reads muddy against the photo; go brighter. */
.hero__proof .stars { color: #F2C14E; }

/* ---------- Category ratings ----------
   The bar is decoration; the number beside it carries the value, so a
   screen reader gets the rating either way and the bar stays aria-hidden. */
.rating-grid {
  list-style: none; padding: 0; margin: 0 0 var(--space-7);
  display: grid; gap: var(--space-5) var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
}
.rating-grid li { display: grid; gap: var(--space-2); }
.rating-grid__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--text-body);
}
.rating-grid__head b { font-family: var(--font-display); font-size: var(--fs-lg); color: var(--text-strong); }
.rating-grid__bar {
  height: 4px; border-radius: var(--r-full);
  background: var(--border);
  overflow: clip;
}
.rating-grid__bar i { display: block; height: 100%; background: var(--accent); }

/* ---------- Plain lists inside a feature card ----------
   Used for the walk-to-town lists, where each line is a place and the
   dash carries no meaning a bullet would not. */
.walk-list { list-style: none; padding: 0; display: grid; gap: var(--space-2); font-size: var(--fs-sm); }
.walk-list li { color: var(--text-body); }
.walk-list b { color: var(--text-strong); font-weight: 600; }

/* ---------- Footer ---------- */
.footer { background: var(--bg-inverse); color: var(--text-on-dark-muted); padding-block: var(--space-8) var(--space-6); }
.footer a { color: var(--text-on-dark); text-decoration: none; }
.footer a:hover { color: var(--c-aqua); text-decoration: underline; }
.footer h3 { color: var(--text-on-dark); margin-bottom: var(--space-4); font-family: var(--font-body); font-weight: 600; letter-spacing: var(--ls-wide); text-transform: uppercase; font-size: var(--fs-xs); }
.footer__grid { display: grid; gap: var(--space-7); grid-template-columns: 1fr; }
@media (min-width: 700px)  { .footer__grid { grid-template-columns: 1.5fr 1fr 1fr; } }
@media (min-width: 1024px) { .footer__grid { grid-template-columns: 2fr 1fr 1fr 1.2fr; } }
.footer__list { list-style: none; padding: 0; display: grid; gap: var(--space-3); font-size: var(--fs-sm); }
.footer__bottom {
  margin-top: var(--space-7); padding-top: var(--space-5);
  border-top: 1px solid rgba(255,255,255,0.16);
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  justify-content: space-between; align-items: center;
  font-size: var(--fs-xs);
}
.footer .brand__text { color: var(--text-on-dark); }
.social { display: flex; gap: var(--space-2); }
.social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid rgba(255,255,255,0.28);
  border-radius: var(--r-full);
  transition: background-color var(--dur-fast) var(--ease-out);
}
.social a:hover { background: rgba(255,255,255,0.14); }
.social svg { width: 20px; height: 20px; }

/* ---------- Scroll reveal (progressive enhancement) ---------- */
.reveal { opacity: 0; transform: translateY(18px); }
.reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
/* THE ONE THAT MATTERS ON WINDOWS.
   While a block is mid-reveal it has a transform and opacity < 1, so the
   browser promotes it to its own compositing layer. Text on a composited
   layer cannot use ClearType subpixel antialiasing and falls back to
   grayscale — headings render thinner and slightly soft. Every heading in
   the reported screenshots was inside a .reveal.
   Once the reveal is finished we strip everything that keeps the layer
   alive, so the text is re-rasterised by the OS at full quality. */
.reveal.is-revealed {
  transition: none;
  transform: none;
  will-change: auto;
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}
/* If JS never runs, content must still be visible */
.no-js .reveal { opacity: 1; transform: none; }

/* ---------- Utilities ---------- */
.stack > * + * { margin-top: var(--space-4); }
.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }
.measure { max-width: var(--container-text); }

/* ---------- Third-party booking widgets ---------- */
/* OwnerRez renders into an iframe that sizes itself, so the only jobs here
   are stopping a wide one from pushing the page sideways on a phone, and
   giving it room to breathe. The ribbon calendar wants about 600px; below
   that it scrolls inside this box rather than the body scrolling. */
.widget-wrap {
  margin-top: var(--space-6);
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.widget-wrap iframe {
  display: block;
  border: 0;
  max-width: none;   /* the iframe sets its own width; do not squash it */
}
