/* ============================================================
   VEC Residential — VECResidential.com
   Design system: 09-Website-Design-Language.md (Sims teardown)
   Palette: "vacation sunset" tokens — dusk navy / sunset amber /
   coral / seafoam (logo accent) over a white, photography-first
   layout. Cinzel (display, 300) + Montserrat (everything else).
   ============================================================ */

:root {
  /* color — sunset edition of the 09 §2.2 tokens */
  --color-primary:  #16395F;   /* dusk navy — headings, footer text, input borders */
  --color-accent:   #C9872F;   /* sunset amber — rules, ghost buttons, icons, keylines ONLY */
  --color-coral:    #C4573F;   /* coral — status chips, hover deepen; never body text */
  --color-seafoam:  #5898A0;   /* logo accent — social icons, tiny details only */
  --color-body:     #666666;   /* paragraph text — never pure black */
  --color-muted:    #999A9D;
  --color-cream:    #FBF4E8;   /* peach-sand-derived soft section bg */
  --color-panel:    #F7F7F7;   /* form panel bg */
  --color-bg:       #FFFFFF;
  --scrim-hero:     rgba(16, 24, 38, .48);

  /* type */
  --font-display: 'Cinzel', serif;          /* weight 300 only at display sizes */
  --font-body:    'Montserrat', sans-serif;
  --h1-size: clamp(34px, 4.5vw, 50px);  --h1-lh: 1.2;
  --h2-size: clamp(24px, 3vw, 30px);    --h2-lh: 1.4;
  --lead-size: clamp(19px, 2.2vw, 24px); --lead-lh: 1.45;
  --body-size: 17px;                    /* 55+ readability */

  /* shape & space */
  --header-h: 112px;   /* fixed-header height: 14px×2 padding + 84px logo */
  --radius-btn: 8px;
  --radius-img: 16px;   /* softened edges (owner direction 2026-08-14) */
  --section-pad: clamp(72px, 10vw, 140px);
  --gutter: clamp(20px, 4vw, 64px);
  --maxw: 1200px;
}

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

/* skip-to-content for keyboard users — hidden until focused */
.skip-link {
  position: absolute; left: -9999px; top: 12px; z-index: 300;
  background: #FFF; color: var(--color-primary);
  font: 700 12px/1 var(--font-body); letter-spacing: 1px; text-transform: uppercase;
  padding: 12px 20px; border: 1px solid var(--color-accent); border-radius: var(--radius-btn);
}
.skip-link:focus { left: 12px; }

@media print {
  .js .reveal { opacity: 1 !important; transform: none !important; }
  .site-header { position: static; background: #FFF; }
  .hero-divisions, .scroll-cue, .nav-toggle { display: none; }
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

body {
  font-family: var(--font-body);
  font-size: var(--body-size);
  font-weight: 400;
  line-height: 1.6;
  color: var(--color-body);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 300; color: var(--color-primary); text-wrap: pretty; }
p { text-wrap: pretty; }

a { color: var(--color-primary); text-decoration: none; transition: color .25s ease; }
a:hover { color: var(--color-accent); }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

.container { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

/* ---------- buttons: ghost only ---------- */
.btn {
  display: inline-block;
  font: 700 12px/1 var(--font-body);
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 15px 30px;
  border-radius: var(--radius-btn);
  background: transparent;
  cursor: pointer;
  transition: background-color .3s ease, color .3s ease, border-color .3s ease;
}
.btn-light { border: 1px solid #FFF; color: #FFF; }
.btn-light:hover { background: rgba(255,255,255,.18); color: #FFF; }
.btn-light:active { background: rgba(255,255,255,.3); }
.btn-accent { border: 1px solid var(--color-accent); color: var(--color-accent); }
.btn-accent:hover { background: var(--color-accent); color: #FFF; }
.btn-accent:active { background: #B3761F; border-color: #B3761F; color: #FFF; }
.btn[disabled], .btn.is-disabled { opacity: .4; pointer-events: none; }

.arrow-link {
  font: 700 12px/1 var(--font-body);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-primary);
}
.arrow-link::after { content: " \203A"; color: var(--color-accent); }
.arrow-link:hover { color: var(--color-accent); }

/* ---------- heading rules ---------- */
.rule { width: 40px; height: 2px; background: var(--color-accent); border: 0; margin: 22px 0 26px; }
.rule.centered { margin-left: auto; margin-right: auto; }

.section-head { text-align: center; max-width: 760px; margin: 0 auto; }
.section-head h2 { font-size: var(--h2-size); line-height: var(--h2-lh); text-transform: uppercase; letter-spacing: 2px; }
.section-head .lead { font-size: var(--lead-size); line-height: var(--lead-lh); font-weight: 300; margin-top: 18px; }

/* ---------- header ---------- */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  transition: background-color .3s ease, box-shadow .3s ease;
  background: transparent;
}
.site-header .bar {
  display: flex; align-items: center; justify-content: space-between;
  max-width: 1380px; margin: 0 auto; padding: 14px var(--gutter);
}
.logo img { height: 84px; width: auto; transition: opacity .3s ease; }
@media (max-width: 1240px) { .logo img { height: 64px; } }
.logo .logo-dark { display: none; }

.site-header.solid, .site-header.scrolled { background: #FFF; border-bottom: 1px solid rgba(22,57,95,.08); }
.site-header.solid .logo-light, .site-header.scrolled .logo-light { display: none; }
.site-header.solid .logo-dark,  .site-header.scrolled .logo-dark  { display: block; }

.main-nav { display: flex; align-items: center; flex: 1; justify-content: space-between; gap: 14px; margin-left: clamp(28px, 4vw, 64px); }
.main-nav a.nav-link {
  font: 500 14px/1 var(--font-body);
  letter-spacing: 1.5px; text-transform: uppercase;
  color: #FFF; padding: 10px 0; white-space: nowrap;
}
.site-header.solid .main-nav a.nav-link, .site-header.scrolled .main-nav a.nav-link { color: var(--color-primary); }
.main-nav a.nav-link:hover { color: var(--color-accent); }
.main-nav a.nav-link[aria-current="page"] { color: var(--color-accent); }

.nav-item { position: relative; }
.nav-item .dropdown {
  position: absolute; top: 100%; left: -14px; min-width: 210px;
  background: #FFF; border-top: 2px solid var(--color-accent);
  border-left: 1px solid rgba(22,57,95,.08); border-right: 1px solid rgba(22,57,95,.08); border-bottom: 1px solid rgba(22,57,95,.08);
  padding: 8px 0; display: none;
}
.nav-item:hover .dropdown, .nav-item:focus-within .dropdown { display: block; }
.dropdown a {
  display: block; padding: 10px 16px;
  font: 500 13.5px/1.3 var(--font-body); letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--color-primary);
}
.dropdown a:hover { color: var(--color-accent); background: var(--color-panel); }

.header-phone {
  font: 500 14px/1 var(--font-body); letter-spacing: .5px;
  color: #FFF; white-space: nowrap;
}
.header-phone a { color: inherit; }
.site-header.solid .header-phone, .site-header.scrolled .header-phone { color: var(--color-primary); }
.btn-contact { border: 1px solid #FFF; color: #FFF; padding: 11px 20px; white-space: nowrap; }
.site-header.solid .btn-contact, .site-header.scrolled .btn-contact { border-color: var(--color-accent); color: var(--color-accent); }
.btn-contact:hover { background: var(--color-accent); border-color: var(--color-accent); color: #FFF; }

.nav-toggle { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.nav-toggle span { display: block; width: 24px; height: 2px; background: #FFF; margin: 5px 0; transition: transform .3s ease; }
.site-header.solid .nav-toggle span, .site-header.scrolled .nav-toggle span { background: var(--color-primary); }

@media (max-width: 1240px) {
  :root { --header-h: 92px; }
  .nav-toggle { display: block; }
  .main-nav .header-phone { color: var(--color-primary); padding: 8px 0; }
  .main-nav {
    display: none; position: absolute; top: 100%; right: var(--gutter); left: auto;
    min-width: 250px; width: max-content; max-width: 86vw;
    background: #FFF; flex-direction: column; align-items: flex-start;
    padding: 14px 26px 20px; gap: 2px; margin-left: 0;
    border: 1px solid rgba(22,57,95,.10); border-top: 2px solid var(--color-accent);
    border-radius: 0 0 var(--radius-img) var(--radius-img);
  }
  .main-nav.open { display: flex; }
  .main-nav a.nav-link { color: var(--color-primary) !important; padding: 10px 0; }
  .nav-item .dropdown { position: static; display: block; border: 0; padding: 0 0 4px 16px; }
  .nav-item .dropdown a { padding: 7px 0; }
  .btn-contact { border-color: var(--color-accent); color: var(--color-accent); margin-top: 10px; }
}

/* ---------- hero ---------- */
.hero {
  position: relative; display: grid; place-items: center;
  min-height: 92vh; overflow: hidden; text-align: center;
}
.hero.short { min-height: 56vh; }
.hero-bg { position: absolute; inset: 0; }
.hero-bg img, .hero-bg video { width: 100%; height: 100%; object-fit: cover; }
.hero-bg::after { content: ""; position: absolute; inset: 0; background: var(--scrim-hero); }
.hero-inner { position: relative; z-index: 2; padding: 140px var(--gutter) 90px; max-width: 900px; }
.hero h1 { font-size: var(--h1-size); line-height: var(--h1-lh); color: #FFF; }
.hero .hero-lead { font-size: var(--lead-size); line-height: var(--lead-lh); font-weight: 300; color: #FFF; margin-top: 22px; }
.hero .hero-ctas { margin-top: 38px; display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; }
.breadcrumb {
  font: 500 11px/1 var(--font-body); letter-spacing: 2px; text-transform: uppercase;
  color: rgba(255,255,255,.85); margin-bottom: 20px;
}
.breadcrumb a { color: rgba(255,255,255,.85); }
.breadcrumb a:hover { color: #FFF; }

/* division link-outs at the base of the home hero */
.hero-divisions {
  position: absolute; bottom: 0; left: 0; right: 0; z-index: 2;
  padding: 24px var(--gutter) 30px; text-align: center;
  border-top: 1px solid rgba(255,255,255,.25);
}
.hero-divisions .divisions-lead {
  font: 500 12px/1.6 var(--font-body); letter-spacing: 2px; text-transform: uppercase;
  color: rgba(255,255,255,.9); margin-bottom: 16px;
}
.hero-divisions .divisions-btns { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.hero-divisions .btn { padding: 11px 20px; }
.hero:has(.hero-divisions) .hero-inner { padding-bottom: 200px; }
@media (max-width: 620px) {
  .hero:has(.hero-divisions) { min-height: 100vh; }
  .hero:has(.hero-divisions) .hero-inner { padding-bottom: 230px; }
}

.scroll-cue {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%); z-index: 2;
  width: 24px; height: 40px; border: 1.5px solid rgba(255,255,255,.8); border-radius: 12px;
}
.scroll-cue::after {
  content: ""; position: absolute; top: 8px; left: 50%; margin-left: -1.5px;
  width: 3px; height: 7px; border-radius: 2px; background: #FFF;
  animation: cue 2s infinite ease-in-out;
}
@keyframes cue { 0%,100% { transform: translateY(0); opacity: 1; } 60% { transform: translateY(10px); opacity: .2; } }

/* ---------- sections ---------- */
.section { padding: var(--section-pad) 0; }
.section.cream, .split.cream { background: var(--color-cream); }
/* Photo band (owner direction 2026-08-28) — "Minutes from what matters" drops its
   cream fill for the El Jobean bridge photo, which is the actual anchor point the
   drive times are measured from. Text inverts to white over a scrim; the gold rule
   and icons carry over, and the white map card reads as a panel on top. */
/* Bottom of the photo fades and blurs into the closing "We'll build more…" band
   (owner direction 2026-08-28). The seam was a hard jump from the photo's dark
   slate rgb(30,36,39) straight to the ember band's measured top row rgb(119,90,62). The band's own
   background is now that same ember tone, and .band-bg — image AND its scrim, so
   they fade together — is masked out over the last quarter, so the photo dissolves
   into the colour the next section starts on. The ::after strip adds a real
   backdrop blur that ramps up toward the seam so no sharp photographic detail
   meets the edge. Degrades to a plain fade where backdrop-filter is unsupported. */
.section.photo-band { position: relative; overflow: hidden; background-color: rgb(121, 92, 64); }
/* Sky trim, 2026-08-29 (owner: cut the empty run between the map and the closing
   headline by ~35%). Taken proportionally from both sides of the join so the
   balance is unchanged: the band keeps a full top pad and drops to 65% below. */
.section.photo-band { padding-bottom: calc(var(--section-pad) * .65); }
.section.photo-band > .band-bg {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 70%, rgba(0,0,0,.4) 88%, transparent 96%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 70%, rgba(0,0,0,.4) 88%, transparent 96%);
}
.section.photo-band::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 190px;
  z-index: 1; pointer-events: none;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 72%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 72%);
}
.section.photo-band > .band-bg { position: absolute; inset: 0; }
.section.photo-band > .band-bg img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 58%;
}
.section.photo-band > .band-bg::after {
  content: ""; position: absolute; inset: 0; background: rgba(16, 24, 38, .58);
}
.section.photo-band > .container { position: relative; z-index: 2; }
.section.photo-band h2 { color: #FFF; }
.section.photo-band .lead { color: rgba(255,255,255,.92); }
.section.photo-band .spec .spec-label { color: #FFF; }
.section.photo-band .spec .spec-sub { color: rgba(255,255,255,.75); }
.section.photo-band .form-note { color: rgba(255,255,255,.72); }
@media (min-width: 901px) { .section.photo-band .spec { border-left-color: rgba(255,255,255,.45); } }

/* Map: feather the hard rectangle into the photo with a soft dark halo plus a
   faint light keyline, instead of the navy hairline that is invisible on a photo.
   Owner direction 2026-08-28 — a scoped exception to the 09 no-shadows rule, in
   the same category as the carousel arrows' glow, and used here to soften an edge
   rather than to lift a card. */
.section.photo-band .map-frame {
  border-color: rgba(255,255,255,.22);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.10),
    0 8px 34px 10px rgba(16,24,38,.42),
    0 0 90px 42px rgba(16,24,38,.40);
}

/* Half-pixel black outline on the band's text so it holds its edge over the
   photo. paint-order puts the stroke behind the fill, so the glyphs stay their
   proper weight instead of being thinned from the inside. */
.section.photo-band h2,
.section.photo-band .lead,
.section.photo-band .spec-label,
.section.photo-band .spec-sub,
.section.photo-band .form-note {
  -webkit-text-stroke: 0.5px rgba(0, 0, 0, .6);
  paint-order: stroke fill;
}
@media (max-width: 900px) { .section.photo-band .spec { border-bottom-color: rgba(255,255,255,.38); } }

.section.sand-bg {
  position: relative;
  /* translucent white veil over the sand so token text passes AA on its own */
  background-image: linear-gradient(rgba(255,255,255,.55), rgba(255,255,255,.55)), url('../assets/img/sand-static.webp');
  background-size: cover; background-position: center;
  background-attachment: fixed; /* static backdrop; scrolls normally on iOS */
}
.section.sand-bg .container { background: transparent; position: relative; z-index: 1; }
/* feather the seams: the white sections above/below fade into the sand over 10px */
.section.sand-bg::before, .section.sand-bg::after {
  content: ""; position: absolute; left: 0; right: 0; height: 10px; pointer-events: none;
}
.section.sand-bg::before { top: 0; background: linear-gradient(to bottom, #FFF, rgba(255,255,255,0)); }
.section.sand-bg::after  { bottom: 0; background: linear-gradient(to top, #FFF, rgba(255,255,255,0)); }

/* Standard-features backdrop (owner direction 2026-08-29) — the El Jobean sunset
   behind the feature panels. Same light-veil family as .sand-bg, with three
   differences forced by the photograph: it is far darker and more contrasty than
   the sand, so the veil is heavier; `background-attachment` stays `scroll`
   because `fixed` re-crops the image on every scroll position and makes text
   contrast unmeasurable; and the seam feathers are white, because the plan grid
   above and the quote band below are both white (measured, not assumed — the
   section's own `cream` class is only the pre-load fallback under the image).
   The .feature-box panels are already solid #FFF, so only the heading, rule,
   lead and footnote sit on the photo. */
#standard-features {
  position: relative;
  background-image: url('../assets/img/sunset-landscape.webp');
  background-size: cover;
  background-position: center 42%;
  background-repeat: no-repeat;
}
#standard-features > .container { position: relative; z-index: 1; }
#standard-features::before, #standard-features::after {
  content: ""; position: absolute; left: 0; right: 0; height: 12px; pointer-events: none;
}
#standard-features::before { top: 0; background: linear-gradient(to bottom, #FFF, rgba(255,255,255,0)); }
#standard-features::after  { bottom: 0; background: linear-gradient(to top, #FFF, rgba(255,255,255,0)); }
/* Owner direction 2026-08-29: no veil over the photograph, and the text that is
   not inside an expandable panel goes white with a half-pixel black outline —
   the same treatment as the photo band on available-homes. paint-order puts the
   stroke behind the fill so the glyphs keep their weight instead of being thinned
   from the inside, which matters most on the 13px footnote. The .feature-box
   panels are solid #FFF and keep their navy text. */
#standard-features .section-head h2,
#standard-features .lead,
#standard-features .form-note {
  color: #FFF;
  -webkit-text-stroke: 0.5px rgba(0, 0, 0, .6);
  paint-order: stroke fill;
}
/* Lead steps 300 -> 500 here (owner direction 2026-08-29, "slightly bolder so it
   is easier to read"). Montserrat 500 is a real loaded cut — not a synthesised
   bold — so the letterforms thicken cleanly instead of smearing. Beats the .5px
   stroke alone where the line crosses the palm fronds. This raises perceived
   legibility only; it does NOT change the measured contrast ratio, which is
   still failing on this unscrimmed photo — see the note above. */
#standard-features .lead { font-weight: 500; }

/* 50/50 split with rotated rail */
.split { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
.split .split-text {
  position: relative; padding: var(--section-pad) var(--gutter);
  display: flex; flex-direction: column; justify-content: center;
}
.split .split-text .inner { max-width: 520px; margin-left: auto; }
.split.flip .split-text .inner { margin-left: 0; margin-right: auto; }
.split h2 { font-size: var(--h2-size); line-height: var(--h2-lh); text-transform: uppercase; letter-spacing: 2px; }
.split .split-photo { position: relative; min-height: 420px; margin: clamp(18px, 3vw, 40px); border-radius: var(--radius-img); overflow: hidden; }
.split .split-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.rail {
  position: absolute; left: 18px; top: 50%;
  transform: rotate(180deg) translateY(50%);
  writing-mode: vertical-rl;
  font: 700 11px/1 var(--font-body); letter-spacing: 4px; text-transform: uppercase;
  color: var(--color-accent); white-space: nowrap;
}
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; }
  .split .split-photo { min-height: 320px; order: -1; }
  .split .split-text .inner { margin: 0; }
  .rail { display: none; }
}

/* serif pull-quote band */
.quote-band { padding: var(--section-pad) var(--gutter); text-align: center; }
.quote-band.photo { position: relative; overflow: hidden; }
.quote-band.photo .band-bg { position: absolute; inset: 0; }
.quote-band.photo .band-bg img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; }
.quote-band.photo .band-bg::after { content: ""; position: absolute; inset: 0; background: var(--scrim-hero); }
/* Deeper scrim for a bright photograph (about.html, 2026-08-29). The shore
   aerial behind the Zach Barker quote is roughly half pale sand — measured
   underlying value ~252, so the standard .48 hero scrim left the 12px
   attribution at 3.44-4.05:1 against a 4.5 requirement. .58 is the same weight
   the available-homes photo band already uses. The quote itself is large text
   and passed either way; this is for the small line under it. */
.quote-band.photo.deep-scrim .band-bg::after { background: rgba(16, 24, 38, .58); }
/* ...and the attribution goes fully opaque here. At .85 alpha it still measured
   4.46:1 at 1024px — 0.04 short. Full white clears it at every width without
   darkening the photograph any further; the hierarchy under the quote is
   carried by size and tracking, not by transparency. */
.quote-band.photo.deep-scrim .attribution { color: #FFF; }
.quote-band.photo blockquote { color: #FFF; position: relative; z-index: 2; }
/* Emphasis inside a display-face quote (owner request 2026-08-31, "paradise").
   The blockquote sets font-weight: 300, and <strong>'s UA default is the relative
   keyword `bolder`, which from 300 resolves to 400 — one step, and invisible in
   Cinzel, whose self-hosted face covers 300-400 with a single cut. An explicit
   weight is required for the word to read as bold at all. */
.quote-band blockquote strong { font-weight: 700; }
.quote-band.photo .attribution { color: rgba(255,255,255,.85); position: relative; z-index: 2; }
/* feather the seams into the white sections above/below */
.quote-band.photo::before, .quote-band.photo::after {
  content: ""; position: absolute; left: 0; right: 0; height: 10px; z-index: 1; pointer-events: none;
}
/* Seam colour is a variable so a band can feather into whatever is actually
   next to it (2026-08-29). It defaults to white, which is right on index where
   the neighbours are white; on about the band sits between two CREAM sections
   and a white feather read as a pale line. Measured, not assumed. */
.quote-band.photo { --band-seam: #FFF; --band-seam-fade: rgba(255,255,255,0); }
.quote-band.photo.on-cream { --band-seam: var(--color-cream); --band-seam-fade: rgba(251,244,232,0); }
.quote-band.photo::before { top: 0; background: linear-gradient(to bottom, var(--band-seam), var(--band-seam-fade)); }
.quote-band.photo::after  { bottom: 0; background: linear-gradient(to top, var(--band-seam), var(--band-seam-fade)); }
.quote-band blockquote {
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(24px, 3.4vw, 38px); line-height: 1.45;
  color: var(--color-primary); max-width: 900px; margin: 0 auto;
}
.quote-band .attribution {
  margin-top: 26px;
  font: 500 12px/1 var(--font-body); letter-spacing: 2px; text-transform: uppercase;
  color: var(--color-muted);
}

/* tile grids (services band / portfolio) */
.tile-grid { display: grid; gap: clamp(18px, 3vw, 36px); margin-top: clamp(36px, 5vw, 64px); }
.tile-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.tile-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.tile-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 1000px) { .tile-grid.cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 860px)  { .tile-grid.cols-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px)  { .tile-grid.cols-4, .tile-grid.cols-3, .tile-grid.cols-2 { grid-template-columns: 1fr; } }

/* "How would you like to live?" tiles (owner report 2026-08-31).
   The four tiles shipped with no rules of their own, so every photo rendered at its
   own intrinsic aspect ratio: three sources are 1080x810 (4:3), but the Standard
   Features kitchen is 1400x882. Measured, that made it 29.3px shorter at 1440 and
   38.6px shorter at 720, and because the tile is a plain block the whole column —
   heading, rule, copy, button — rode up with it. The buttons also sized to their own
   labels, so "What's Included" ran 197.4px against 157px for "View Homes", a 40.5px
   spread. Photos now sit in the same 4:3 box the paradise tiles already use, and the
   button is pinned to the bottom of the tile at a shared width, so the row stays
   aligned at any viewport and however the copy wraps. */
.tile { display: flex; flex-direction: column; height: 100%; }
.tile .tile-photo { display: block; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-img); }
.tile .tile-photo img { width: 100%; height: 100%; object-fit: cover; }
.tile .btn { margin-top: auto; width: 100%; text-align: center; }

/* Available Homes and Our Lots sit next to each other and are both white, so the
   two full section paddings stacked into a ~280px empty seam with no band or rule
   to justify it (owner report 2026-08-28). Halved on both sides of that one seam;
   every other section keeps the standard --section-pad rhythm. */
.section.tight-bottom { padding-bottom: clamp(40px, 5vw, 72px); }
/* Our Lots became a cream band 2026-08-29 (owner: separate it from Available
   Homes with the same warm fill used on About / Standard Features / What's
   included). The colour now does the separating, so the band gets its own
   balanced padding rather than the tight-top/full-bottom mix it inherited —
   an 84px top against a 140px bottom read lopsided once the fill was visible.
   Still well under --section-pad, so the page does not grow back. */
#our-lots { padding-top: clamp(48px, 5.5vw, 84px); padding-bottom: clamp(48px, 5.5vw, 84px); }

/* Touch behaviour for every carousel (owner report 2026-08-28).
   The tracks are horizontal scrollers, so a finger-drag that began on a card was
   being captured as a sideways pan — the picture slid around instead of the page
   scrolling. `touch-action: pan-y` hands every touch gesture on the track back to
   the page for vertical scrolling and refuses horizontal panning, so cards are
   static and tappable only. Arrow paging is unaffected: main.js calls scrollBy(),
   which is programmatic and not a touch gesture. The image rules kill the native
   drag-ghost you get when dragging an <img> inside a link. */
.carousel-track,
.plan-track {
  touch-action: pan-y;
  overscroll-behavior-x: contain;
  /* Setting overflow-x makes the browser compute overflow-y as `auto` too, so the
     track became a vertical scroll container and swallowed the pan-y gesture that
     was supposed to reach the page. Pinning overflow-y removes that container. */
  overflow-y: hidden;
}
/* Cards inside a carousel are exempt from the scroll-reveal. An off-track card
   never intersects the viewport, so its observer never fires and its 22px
   translateY sat there permanently — that offset was the vertical overflow that
   made the track a scroll container in the first place. Revealing them up front
   also removes any chance of a card being stuck invisible after paging. */
.js .carousel-track .reveal,
.js .plan-track .reveal { opacity: 1; transform: none; }

.carousel-track img,
.plan-track img,
.lightbox img {
  -webkit-user-drag: none;
  user-select: none; -webkit-user-select: none;
}

/* 2x2 paged grid carousel (owner direction 2026-08-28) — the lots read as a
   long listing when every card stacked down the page. Now four per view on
   desktop (2 rows x 2 columns), paged with the same arrows; two per view on
   tablet; one per view on phones, unchanged. Same .carousel-track hook, so
   main.js needs no change. Cards flow column-major, matching the models page. */
.grid-carousel { position: relative; }
.grid-carousel .carousel-track {
  --gc-gap: clamp(20px, 3vw, 40px);
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(2, auto);
  grid-template-columns: none;
  grid-auto-columns: calc((100% - var(--gc-gap)) / 2);
  gap: var(--gc-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.grid-carousel .carousel-track::-webkit-scrollbar { display: none; }
.grid-carousel .carousel-track > * { scroll-snap-align: start; }
.grid-carousel .carousel-arrow { display: grid; top: calc(50% - 46px); }
.grid-carousel .carousel-arrow.prev { left: -20px; }
.grid-carousel .carousel-arrow.next { right: -20px; }
@media (min-width: 1340px) {
  .grid-carousel .carousel-arrow.prev { left: -68px; }
  .grid-carousel .carousel-arrow.next { right: -68px; }
}
@media (max-width: 900px) {
  .grid-carousel .carousel-track { grid-auto-columns: 100%; }
  .grid-carousel .carousel-arrow.prev { left: 4px; }
  .grid-carousel .carousel-arrow.next { right: 4px; }
}
@media (max-width: 600px) {
  .grid-carousel .carousel-track { grid-template-rows: auto; gap: 0; }
  .grid-carousel .carousel-arrow { top: calc(50% - 44px); }
}

/* Always-on carousel (owner direction 2026-08-28) — unlike .mobile-carousel this
   scrolls at every width: 3 items per view on desktop, 2 on tablet, 1 on phone.
   Used for the project gallery absorbed onto the Team page. Same .carousel-track
   hook and .carousel-arrow styling as everywhere else. */
.scroll-carousel { position: relative; }
.scroll-carousel .carousel-track {
  --sc-gap: clamp(18px, 2.5vw, 32px);
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100% - 2 * var(--sc-gap)) / 3);
  gap: var(--sc-gap);
  grid-template-columns: none;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
  padding-bottom: 2px;
}
.scroll-carousel .carousel-track::-webkit-scrollbar { display: none; }
.scroll-carousel .carousel-track > * { scroll-snap-align: start; }
.scroll-carousel .carousel-arrow { display: grid; top: calc(50% - 42px); }
.scroll-carousel .carousel-arrow.prev { left: -20px; }
.scroll-carousel .carousel-arrow.next { right: -20px; }
@media (min-width: 1340px) {
  .scroll-carousel .carousel-arrow.prev { left: -68px; }
  .scroll-carousel .carousel-arrow.next { right: -68px; }
}
@media (max-width: 900px) {
  .scroll-carousel .carousel-track { grid-auto-columns: calc((100% - var(--sc-gap)) / 2); }
  .scroll-carousel .carousel-arrow.prev { left: 4px; }
  .scroll-carousel .carousel-arrow.next { right: 4px; }
}
@media (max-width: 600px) {
  .scroll-carousel .carousel-track { grid-auto-columns: 100%; gap: 0; }
  .scroll-carousel .carousel-arrow { top: calc(50% - 46px); }
}

/* Carousel for grids that would otherwise WRAP (added 2026-08-26, reworked
   2026-08-29 after a wrapping audit). Originally this only engaged below 600px,
   but the underlying grids start dropping to a second row at 860-980px — so
   between roughly 620 and 980 the sections silently reflowed to two (and at
   620, three) rows instead of paging. Owner direction: shrink slightly, then
   become a click-to-scroll section, never wrap.

   Now the track pages at every width below 1024 and steps its per-view count
   down instead of adding rows: --mc-cols per-view, defaulting to 3 and
   overridden per section. The 1024 entry point is chosen so the first paged
   view is the same card size the grid was already showing — paging switches on
   without a visible jump. Same ladder as .scroll-carousel, which has been doing
   this correctly on the About gallery all along. */
.mobile-carousel { position: relative; }
.mobile-carousel .carousel-arrow { display: none; }
.mobile-carousel .carousel-track { --mc-cols: 3; --mc-gap: clamp(18px, 2.5vw, 32px); }
.tile-carousel .carousel-track { --mc-cols: 4; }   /* "How would you like to live" ships 4 tiles */

@media (max-width: 1023px) {
  .mobile-carousel .carousel-track {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - (var(--mc-cols) - 1) * var(--mc-gap)) / var(--mc-cols));
    gap: var(--mc-gap);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .mobile-carousel .carousel-track::-webkit-scrollbar { display: none; }
  .mobile-carousel .carousel-track > * { scroll-snap-align: start; }
  .mobile-carousel .carousel-arrow { display: grid; top: 50%; }
  .mobile-carousel .carousel-arrow.prev { left: 4px; }
  .mobile-carousel .carousel-arrow.next { right: 4px; }
}
@media (max-width: 900px) {
  .mobile-carousel .carousel-track { --mc-cols: 2; }
}
/* Arrow centring for the paged band above 600px. The ≤600 block below has its
   own offsets tuned for the 1-up card; at 2-up and 3-up the cards are shorter
   but the caption below the photo is not, so a flat 50% lands well under the
   picture. Measured arrow-centre minus photo-centre before these: tiles +77 to
   +90px, amenities +40 to +49px, listings +73px. Only .homes-carousel needs no
   offset — its overlay is hover-only, so the whole card is photo. */
@media (min-width: 601px) and (max-width: 1023px) {
  .tile-carousel .carousel-arrow    { top: calc(50% - 82px); }
  .amenity-carousel .carousel-arrow { top: calc(50% - 45px); }
  /* the caption banner is a constant 145px tall at every width, so the same
     -72px raise that centres the arrow on the photo at 1-up is correct here */
  .listing-carousel .carousel-arrow { top: calc(50% - 72px); }
}
@media (max-width: 600px) {
  .mobile-carousel .carousel-track { --mc-cols: 1; gap: 0; }
  .mobile-carousel .carousel-arrow { top: 50%; }
  .mobile-carousel .carousel-arrow.prev { left: 4px; }
  .mobile-carousel .carousel-arrow.next { right: 4px; }
  /* per-section offsets: centre the arrow on the photo, not on photo+caption */
  .tile-carousel .carousel-arrow    { top: calc(50% - 88px); }  /* h3 + rule + copy + button */
  .amenity-carousel .carousel-arrow { top: calc(50% - 46px); }  /* h3 + sub */
  /* cards with a permanent caption banner: centre on the picture above it.
     Banner heights are fixed (144px listing / 89px lot) at every width. */
  .listing-carousel .carousel-arrow { top: calc(50% - 72px); }
  .lots-carousel .carousel-arrow    { top: calc(50% - 44px); }
  /* .homes-carousel (homepage) keeps top: 50% — those .pcard captions sit inside the photo */
}

/* frosted-overlay hover cards (portfolio / homes / models) */
.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 3vw, 40px); }
@media (max-width: 960px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .card-grid { grid-template-columns: 1fr; } }

.pcard { position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden; border-radius: var(--radius-img); }
.pcard.wide { aspect-ratio: 4 / 3; }
.pcard.plan { aspect-ratio: 3 / 4; background: #FFF; border: 1px solid rgba(22,57,95,.10); }
.pcard.lot { aspect-ratio: 16 / 9; }   /* lot aerials are 16:9 (added 2026-08-26) */
.lot-grid { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 620px) { .lot-grid { grid-template-columns: 1fr; } }
.pcard.plan img { object-fit: contain; }
.pcard img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s ease; }
.pcard .overlay {
  position: absolute; inset: 0; background: rgba(255,255,255,.92);
  opacity: 0; transition: opacity .35s ease;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 30px;
}
.pcard .overlay::before {
  content: ""; position: absolute; inset: 15px;
  border: 1px solid var(--color-accent); border-radius: calc(var(--radius-img) - 8px); pointer-events: none;
}

/* Permanent caption banner (owner direction 2026-08-26). Used on the Our Homes
   page so the address and photo count read without hovering, on every device —
   the frosted hover overlay of 09 §1.7 is kept everywhere else. */
.pcard.captioned .overlay {
  inset: auto 0 0 0;
  opacity: 1;
  background: rgba(255,255,255,.94);
  align-items: flex-start;
  justify-content: flex-end;
  text-align: left;
  padding: 13px 18px 14px;
  border-top: 1px solid rgba(22,57,95,.10);
}
.pcard.captioned .overlay::before { display: none; }
.pcard.captioned .overlay h3 { font-size: 16px; letter-spacing: 1.2px; }
.pcard.captioned .overlay .rule { margin: 7px 0; }
.pcard.captioned .overlay .meta { margin-bottom: 0; }
/* Street numbers under the title on a multi-parcel card (owner direction
   2026-09-01). Sentence case and no tracking — a list of house numbers is
   harder to scan in the uppercase, letter-spaced treatment .meta uses. */
.pcard.captioned .overlay .lot-addr {
  font: 500 13px/1.5 var(--font-body); letter-spacing: .3px;
  color: var(--color-body); margin-bottom: 5px;
}
.pcard.captioned .overlay .chip { margin-top: 9px; }
.pcard .overlay h3 { font-size: 20px; letter-spacing: 1.5px; text-transform: uppercase; }
.pcard .overlay .rule { margin: 12px auto; }
.pcard .overlay .meta { font: 500 12px/1.6 var(--font-body); letter-spacing: 1px; text-transform: uppercase; color: var(--color-body); margin-bottom: 14px; }
.pcard:hover .overlay, .pcard:focus-visible .overlay { opacity: 1; }
.pcard:hover img { transform: scale(1.03); }
/* touch devices get no hover: show the card info as a persistent bottom strip */
@media (hover: none) {
  .pcard .overlay { opacity: 1; inset: auto 0 0 0; padding: 18px 16px 16px; }
  .pcard .overlay::before { display: none; }
}

/* status chips */
.chip {
  display: inline-block; font: 700 11px/1 var(--font-body);
  letter-spacing: 1.5px; text-transform: uppercase;
  padding: 7px 12px; border: 1px solid currentColor; border-radius: var(--radius-btn);
}
.chip.available { color: var(--color-seafoam); }
.chip.construction { color: var(--color-coral); }
.chip.soon { color: var(--color-primary); }

.price { color: var(--color-primary); font-weight: 500; }

/* honest placeholders */
.ph {
  color: var(--color-muted); font-style: normal;
  border: 1px dashed var(--color-muted); border-radius: 8px;
  padding: 1px 7px; font-size: .88em; white-space: normal;
}
.ph-photo {
  display: flex; align-items: center; justify-content: center; text-align: center;
  background: var(--color-panel); border: 1px dashed var(--color-muted); border-radius: var(--radius-img);
  color: var(--color-muted); font: 500 12px/1.6 var(--font-body);
  letter-spacing: 1px; text-transform: uppercase; padding: 20px;
  width: 100%; height: 100%;
}

/* spec strip */
.spec-strip {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: clamp(22px, 4vw, 56px); margin: 40px 0 0;
}
.spec { text-align: center; min-width: 96px; }
.spec svg { width: 34px; height: 34px; stroke: var(--color-accent); fill: none; stroke-width: 1.4; margin: 0 auto 10px; display: block; }
.spec .spec-label {
  font-family: var(--font-display); font-weight: 400; font-size: 15px;
  letter-spacing: 1px; text-transform: uppercase; color: var(--color-primary);
}
.spec .spec-sub { font: 400 12px/1.4 var(--font-body); letter-spacing: 1px; text-transform: uppercase; color: var(--color-muted); margin-top: 3px; }

/* Condensed spec strip (owner direction 2026-08-26). The five drive-time items
   used to flex-wrap into a ragged 3+2 (desktop) or 2+2+1 (phone) block of
   floating icon stacks. Now: one even, hairline-divided row on desktop, and a
   compact left-aligned list on phones. Markup is unchanged — this is CSS only,
   and it applies equally to the six-item strip on the home-detail template. */
@media (min-width: 901px) {
  .spec-strip { flex-wrap: nowrap; gap: 0; margin-top: 34px; }
  .spec {
    flex: 1 1 0; min-width: 0;
    padding: 0 clamp(6px, 1.1vw, 16px);
    border-left: 1px solid rgba(22,57,95,.12);
    /* column flex so a label that wraps to two lines still leaves every
       drive time sitting on the same baseline across the strip */
    display: flex; flex-direction: column;
  }
  .spec:first-child { border-left: 0; }
  .spec svg { width: 26px; height: 26px; margin-bottom: 7px; }
  .spec .spec-label { font-size: 13.5px; letter-spacing: .5px; flex: 1 0 auto; }
  .spec .spec-sub { font-size: 12px; margin-top: 4px; }
}
@media (max-width: 900px) {
  .spec-strip {
    display: grid; grid-template-columns: 1fr; gap: 0;
    max-width: 460px; margin: 30px auto 0;
  }
  .spec {
    display: grid; grid-template-columns: 24px 1fr auto;
    align-items: center; column-gap: 14px;
    text-align: left; min-width: 0;
    padding: 12px 2px;
    border-bottom: 1px solid rgba(22,57,95,.10);
  }
  .spec:last-child { border-bottom: 0; }
  .spec svg { width: 21px; height: 21px; margin: 0; }
  .spec .spec-label { font-size: 15px; letter-spacing: .6px; }
  .spec .spec-sub { margin-top: 0; text-align: right; white-space: nowrap; font-size: 12px; }
  /* 3D model pages have no icon: drop the 24px icon column (QA 2026-09-07) */
  .spec:not(:has(svg)) { grid-template-columns: 1fr auto; }
}

/* sticky anchor sub-nav (home detail) */
#details, #photos { scroll-margin-top: calc(var(--header-h) + 64px); }
.subnav {
  position: sticky; top: var(--header-h); z-index: 90;
  background: #FFF; border-bottom: 1px solid rgba(22,57,95,.10);
  display: flex; justify-content: center; gap: clamp(18px, 4vw, 48px);
  padding: 16px var(--gutter);
}
.subnav a { font: 700 12px/1 var(--font-body); letter-spacing: 1.5px; text-transform: uppercase; color: var(--color-primary); }
.subnav a:hover, .subnav a.cta { color: var(--color-accent); }

/* feature list (standard features) */
.feature-cols { columns: 2; column-gap: clamp(40px, 6vw, 80px); margin-top: 30px; }
@media (max-width: 760px) { .feature-cols { columns: 1; } }
.feature-cols ul { list-style: none; }
.feature-cols li, .checklist li, .feature-box li {
  padding: 9px 0 9px 26px; position: relative;
  border-bottom: 1px solid rgba(22,57,95,.07);
  break-inside: avoid; font-size: 16px;
}
.feature-cols li::before, .checklist li::before, .feature-box li::before {
  content: ""; position: absolute; left: 2px; top: 17px;
  width: 12px; height: 2px; background: var(--color-accent);
}
.feature-group h3 {
  font-size: 18px; letter-spacing: 1.5px; text-transform: uppercase;
  margin: 38px 0 6px; break-after: avoid;
}
.checklist { list-style: none; margin-top: 22px; }

/* standard-features boxes (models page) — expandable white panels on the cream band */
#standard-features { scroll-margin-top: 90px; }
.feature-boxes {
  display: grid; grid-template-columns: repeat(2, 1fr); align-items: start;
  gap: clamp(20px, 3vw, 36px); margin-top: clamp(36px, 5vw, 64px);
}
@media (max-width: 860px) { .feature-boxes { grid-template-columns: 1fr; } }
.feature-box {
  background: #FFF; border: 1px solid rgba(22,57,95,.10);
  border-radius: var(--radius-img);
}
.feature-box summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: clamp(20px, 3vw, 26px) clamp(26px, 4vw, 40px);
}
.feature-box summary::-webkit-details-marker { display: none; }
.feature-box summary h3 { font-size: 18px; letter-spacing: 1.5px; text-transform: uppercase; transition: color .25s ease; }
.feature-box summary:hover h3 { color: var(--color-accent); }
.fb-toggle { position: relative; width: 14px; height: 14px; flex: none; }
.fb-toggle::before, .fb-toggle::after { content: ""; position: absolute; background: var(--color-accent); }
.fb-toggle::before { left: 0; right: 0; top: 6px; height: 2px; }
.fb-toggle::after { top: 0; bottom: 0; left: 6px; width: 2px; transition: transform .3s ease; }
.feature-box[open] .fb-toggle::after { transform: scaleY(0); }
.feature-box .fb-body { padding: 0 clamp(26px, 4vw, 40px) clamp(24px, 3vw, 32px); }
.feature-box .rule { margin: 0 0 10px; }
.feature-box ul { list-style: none; }
.feature-box li:last-child { border-bottom: 0; }

/* contact / split-panel pages */
.panel-split { display: grid; grid-template-columns: 1.05fr .95fr; gap: 0; align-items: stretch; }
/* min-width:0 stops a long unbreakable string (email, .ph chip) from widening the
   grid track past the viewport on phones (QA 2026-09-07). */
.panel-split > * { min-width: 0; }
@media (max-width: 900px) { .panel-split { grid-template-columns: 1fr; } }
.panel-split .sell { padding: var(--section-pad) var(--gutter); }
.panel-split .sell .inner { max-width: 520px; margin-left: auto; }
@media (max-width: 900px) { .panel-split .sell .inner { margin: 0; } }
.panel-split .panel { background: var(--color-panel); padding: var(--section-pad) var(--gutter); }
.panel-split .panel .inner { max-width: 480px; margin-right: auto; }

.contact-rows { margin-top: 30px; }
.contact-rows .row { padding: 14px 0; border-bottom: 1px solid rgba(22,57,95,.08); display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: baseline; }
.contact-rows .row > span:not(.k) { min-width: 0; overflow-wrap: anywhere; }
.contact-rows .row .k {
  font-family: var(--font-display); font-weight: 400; font-size: 14px;
  letter-spacing: 1.5px; text-transform: uppercase; color: var(--color-primary);
  min-width: 92px;
}

/* forms — square inputs per 1.9 */
form .field { margin-bottom: 16px; }
form .two-up { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 520px) { form .two-up { grid-template-columns: 1fr; } }
label {
  display: block; font: 500 11px/1 var(--font-body);
  letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--color-primary); margin-bottom: 7px;
}
input, select, textarea {
  width: 100%; padding: 12px 14px;
  font: 400 13px/1.4 var(--font-body); color: var(--color-primary);
  background: #FFF; border: 1px solid var(--color-primary); border-radius: 8px;
}
input::placeholder, textarea::placeholder { color: var(--color-muted); }
input:hover, select:hover, textarea:hover { border-color: var(--color-accent); }
input:disabled, select:disabled, textarea:disabled { background: var(--color-panel); color: var(--color-muted); border-color: var(--color-muted); }
textarea { min-height: 120px; resize: vertical; }
.btn-submit {
  border: 2px solid var(--color-accent); color: var(--color-accent);
  background: transparent; border-radius: var(--radius-btn);
  font: 700 12px/1 var(--font-body); letter-spacing: 1px; text-transform: uppercase;
  padding: 15px 34px; cursor: pointer;
  transition: background-color .3s ease, color .3s ease;
}
.btn-submit:hover { background: var(--color-accent); color: #FFF; }
.form-note { font-size: 13px; color: var(--color-muted); margin-top: 14px; }
.form-status { margin-top: 14px; font-size: 14px; min-height: 1.4em; }
.form-status.is-ok { color: var(--color-seafoam); }
.form-status.is-error { color: var(--color-coral); }
.form-status.is-busy { color: var(--color-muted); }
input.invalid, textarea.invalid, select.invalid { border-color: var(--color-coral); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* lots table */
.lot-table { width: 100%; border-collapse: collapse; margin-top: 34px; }
.lot-table th {
  font-family: var(--font-display); font-weight: 400; font-size: 14px;
  letter-spacing: 1.5px; text-transform: uppercase; color: var(--color-primary);
  text-align: left; padding: 12px 14px; border-bottom: 2px solid var(--color-accent);
}
.lot-table td { padding: 13px 14px; border-bottom: 1px solid rgba(22,57,95,.08); font-size: 15px; }
.lot-table tr:hover td { background: var(--color-cream); }
@media (max-width: 640px) {
  .lot-table thead { display: none; }
  .lot-table tr { display: block; padding: 12px 0; border-bottom: 1px solid rgba(22,57,95,.12); }
  .lot-table td { display: block; border: 0; padding: 3px 0; }
}

/* map embed */
.map-frame { width: 100%; height: 560px; border: 1px solid rgba(22,57,95,.14); border-radius: var(--radius-img); margin-top: 40px; }

/* team */
.team-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(30px, 5vw, 70px); margin-top: clamp(40px, 5vw, 70px); }
@media (max-width: 820px) { .team-grid { grid-template-columns: 1fr; } }
/* Team cards (owner direction 2026-08-26) — each person in a self-contained
   panel, matching the .feature-box card treatment, with the bio broken into
   labelled facts instead of one block of prose. */
.person-card {
  background: #FFF; border: 1px solid rgba(22,57,95,.10);
  border-radius: var(--radius-img);
  padding: clamp(22px, 3vw, 32px);
  height: 100%;
}
.pc-head { display: grid; grid-template-columns: 108px 1fr; gap: 20px; align-items: center; }
.pc-head img { width: 108px; height: 136px; object-fit: cover; border-radius: calc(var(--radius-img) - 6px); }
.person-card h3 { font-size: 21px; letter-spacing: 1px; }
.person-card .role {
  font: 500 11px/1 var(--font-body); letter-spacing: 2px; text-transform: uppercase;
  color: var(--color-accent); margin-top: 7px;
}
.pc-lead { font-size: var(--body-size); margin-top: 20px; padding-top: 18px; border-top: 1px solid rgba(22,57,95,.10); }
.pc-facts { margin-top: 4px; }
.pc-fact { padding: 13px 0; border-bottom: 1px solid rgba(22,57,95,.08); }
.pc-fact:last-child { border-bottom: 0; padding-bottom: 0; }
.pc-fact dt {
  font: 700 11px/1 var(--font-body); letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--color-primary); margin-bottom: 7px;
}
.pc-fact dd { font-size: 15.5px; line-height: 1.6; color: var(--color-body); }
@media (max-width: 420px) {
  .pc-head { grid-template-columns: 84px 1fr; gap: 15px; }
  .pc-head img { width: 84px; height: 106px; }
  .person-card h3 { font-size: 19px; }
}

/* reveal on scroll — only hides when JS is present (html.js) */
.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s ease; }
.js .reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .js .reveal { opacity: 1; transform: none; } }

/* ---------- footer (white) ---------- */
.site-footer { border-top: 1px solid rgba(22,57,95,.10); padding: clamp(56px, 7vw, 90px) 0 0; background: #FFF; }
.footer-cols { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: clamp(24px, 3.5vw, 48px); align-items: start; }

/* brand: logo left, blurb wrapping beside it, social centred underneath */
.fb-id { display: grid; grid-template-columns: auto 1fr; gap: 20px; align-items: center; }
.fb-id p { margin: 0; }

/* Visit spans the full width and reads as one separated line */
.footer-visit {
  grid-column: 1 / -1; text-align: center;
  margin-top: -6px; padding-top: 22px;
  border-top: 1px solid rgba(22,57,95,.10);
}
.footer-visit h4 { margin-bottom: 10px; }
.inline-sep { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; }
.site-footer .inline-sep li { margin: 0; display: inline-flex; align-items: center; }
/* Separator hangs off the END of each item rather than the start of the next
   (changed 2026-08-29). With ::before, a wrapped line began with a stray "|";
   as ::after the bar is inside the item's own box and can never be orphaned
   onto the next line. */
.inline-sep li:not(:last-child)::after {
  content: "|"; margin: 0 14px; color: rgba(22,57,95,.28); font-weight: 400;
}

/* Contact button — lives in the brand block, directly above the social row
   (owner direction 2026-08-28); centred to match. */
/* max-width:none defeats `.footer-brand p { max-width: 300px }`, which was
   capping this paragraph and throwing the button off the social row's centre. */
.site-footer .fc-btn { margin-top: 24px; text-align: center; max-width: none; }
.site-footer .fc-btn a {
  display: inline-block;
  font: 700 12.5px/1 var(--font-body); letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--color-accent); border: 1px solid var(--color-accent);
  border-radius: 999px; padding: 11px 26px;
  transition: background-color .3s ease, color .3s ease;
}
.site-footer .fc-btn a:hover, .site-footer .fc-btn a:focus-visible { background: var(--color-accent); color: #FFF; }
.footer-brand img.footer-logo-circle { width: 170px; margin-bottom: 18px; }
.footer-brand p { font-size: 14px; max-width: 300px; }
.site-footer h4 {
  /* Montserrat 700 rather than Cinzel: Cinzel ships only a 400 cut here, so
     "bold" would be browser-synthesised and smeared. Owner direction
     2026-08-26 — these must read as section labels, not as links. */
  font-family: var(--font-body);
  font-size: 13px; font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--color-primary);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 6px;
  text-decoration-color: rgba(22,57,95,.35);
  margin-bottom: 11px;
}
.site-footer ul { list-style: none; }
.site-footer li { margin-bottom: 10px; }
.site-footer li a, .site-footer li span { font-size: 14px; color: var(--color-body); }
.site-footer li a:hover { color: var(--color-accent); }
.social { display: flex; gap: 12px; margin-top: 16px; justify-content: center; }
.social a {
  width: 36px; height: 36px; border: 1px solid var(--color-seafoam); border-radius: 50%;
  display: grid; place-items: center; color: var(--color-seafoam);
  font: 600 12px/1 var(--font-body);
  transition: background-color .3s ease, color .3s ease;
}
.social a:hover { background: var(--color-seafoam); color: #FFF; }
.footer-legal {
  margin-top: clamp(40px, 5vw, 64px); padding: 22px var(--gutter);
  border-top: 1px solid rgba(22,57,95,.08);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 22px;
  font-size: 12.5px; color: var(--color-muted); text-align: center;
}
.eho { display: inline-flex; align-items: center; gap: 8px; }
.eho svg { width: 26px; height: 26px; stroke: var(--color-muted); fill: none; stroke-width: 1.6; }

/* Footer layout below the three-column width (owner direction 2026-08-29).
   This band used to be `grid-template-columns: 1fr 1fr`, which squeezed the brand
   blurb into a 73px column — 19 lines of one word each at 561px, and a 1,129px
   footer. The stacked arrangement from the mobile block now starts here instead:
   brand across the top, Homes beside Company under it, Visit last. Only the
   ARRANGEMENT moves up to 960px; the mobile block below still owns the size
   compression, so 600-960px keeps full-size type and the 170px logo.
   ORDER MATTERS: this must stay after the base footer rules and before the
   max-width:560px block, or equal-specificity declarations silently lose. */
@media (max-width: 960px) {
  .footer-cols {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "brand brand" "homes company" "visit visit";
  }
  .footer-brand { grid-area: brand; }
  .footer-cols > div:nth-child(2) { grid-area: homes; }
  .footer-cols > div:nth-child(3) { grid-area: company; }
  .footer-visit { grid-area: visit; margin-top: 2px; padding-top: 20px; }
  /* the brand row is now full-bleed, so the blurb is uncapped but the whole
     logo+text unit is centred — that keeps it on the same axis as the Contact
     button and the social row, which centre in the grid area. */
  .fb-id { max-width: 560px; margin: 0 auto; }
  .footer-brand p { max-width: none; }
}

/* Visit line: hold it to ONE line as far down as it will physically go.
   Measured 2026-08-29 — at full size it breaks between 561 and 589px; at
   12.5px with 7px separator margins it holds unbroken from 520px up. Below
   520 the three items are wider than the container at any legible size, so it
   wraps to two lines there and nothing can be done about it. */
@media (max-width: 640px) {
  .footer-visit .inline-sep li span, .footer-visit .inline-sep li a { font-size: 12.5px; }
  .inline-sep li:not(:last-child)::after { margin: 0 7px; }
}

/* Compact mobile footer (owner direction 2026-08-26). Was a single stacked
   column of 13 links plus the brand block, which ran the footer very long.
   Now two columns with the brand spanning both, and every metric tightened. */
@media (max-width: 560px) {
  .site-footer { padding-top: clamp(40px, 9vw, 56px); }
  /* brand across the top, then Homes stacked over Visit beside Company —
     Company is the tall list, so this fills the space its overhang leaves. */
  .footer-cols {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "brand brand" "homes company" "visit visit";
    gap: 20px; align-items: start;
  }
  .footer-visit { grid-area: visit; margin-top: 2px; padding-top: 18px; }
  .fb-id { grid-template-columns: 84px 1fr; gap: 14px; }
  .footer-brand img.footer-logo-circle { width: 84px; margin-bottom: 0; }
  .footer-brand p { font-size: 13px; line-height: 1.55; max-width: none; }
  .fc-btn { margin-top: 18px; }
  .social { margin-top: 13px; gap: 10px; }
  .social a { width: 32px; height: 32px; }
  .site-footer h4 { font-size: 12.5px; letter-spacing: 1.3px; margin-bottom: 8px; }
  .site-footer li { margin-bottom: 6px; }
  .site-footer li a, .site-footer li span { font-size: 13.5px; }
  .site-footer .fc-btn a { font-size: 12px; padding: 10px 22px; }
  .footer-legal { margin-top: 24px; padding: 15px var(--gutter); gap: 6px 12px; font-size: 11.5px; line-height: 1.45; }
  .footer-legal .eho svg { width: 22px; height: 22px; }
}

/* ------------------------------------------------------------------ *
   Footer height pass (owner request 2026-08-31: "compress it down").
   Measured on index.html at 17 widths, 1920 -> 320. Every band is scoped
   with an explicit min-width so nothing can leak into a narrower one —
   this block sits after all the others, so unbounded rules here would
   silently beat the phone block above.

   Baseline heights: 615-663px on desktop, 828-854px from 600-960, and
   653-785px on phones.
 * ------------------------------------------------------------------ */

/* The 561-960 band was the expensive one. The STACKED arrangement starts at
   960 but the size compression only started at 560, so those widths rendered
   the tall layout at full desktop sizing: a 170px logo, 14px type, 10px list
   margins. Same arrangement, compressed metrics. -165 to -184px. */
@media (max-width: 960px) and (min-width: 561px) {
  .site-footer { padding-top: clamp(40px, 6vw, 56px); }
  .footer-cols { gap: 20px clamp(24px, 3.5vw, 48px); }
  .fb-id { grid-template-columns: 110px 1fr; gap: 18px; }
  .footer-brand img.footer-logo-circle { width: 110px; }
  .footer-brand p { font-size: 13.5px; line-height: 1.55; }
  .site-footer .fc-btn { margin-top: 16px; }
  .social { margin-top: 12px; }
  .site-footer h4 { margin-bottom: 8px; }
  .site-footer li { margin-bottom: 7px; }
  .footer-visit { padding-top: 18px; }
  .footer-legal { margin-top: 24px; padding: 15px var(--gutter); gap: 6px 16px; }
}

/* Desktop and tablet trims. The logo's 18px margin-bottom is a leftover from
   when it sat ABOVE the blurb; inside .fb-id (a centred 2-col grid) it just
   pads the row. Removing it costs nothing visually. */
@media (min-width: 561px) {
  .site-footer { padding-top: clamp(48px, 5.5vw, 68px); }
  .footer-legal { margin-top: clamp(26px, 3.2vw, 40px); }
  .footer-brand img.footer-logo-circle { margin-bottom: 0; }
}

/* .footer-cols set one `gap` for both axes, so the seam between the columns
   row and the full-width Visit row inherited the 48px COLUMN gap. Only the
   column gap needs to be that wide. */
@media (min-width: 961px) {
  .footer-cols { gap: clamp(20px, 2.2vw, 30px) clamp(24px, 3.5vw, 48px); }
}

/* Phones: the arrangement is already tight, so this is padding only. */
@media (max-width: 560px) {
  .footer-cols { gap: 18px; }
  .footer-visit { padding-top: 15px; }
  .footer-legal { margin-top: 20px; padding: 13px var(--gutter); gap: 5px 12px; }
}

/* ---------- 3D model viewer (model-1683.html, added 2026-08-29) ----------
   <model-viewer> in the same card language as the plan photos: 16px radius,
   the standard hairline border, panel-gray ground, no shadow. touch-action
   pan-y so a vertical swipe still scrolls the page on a phone instead of being
   eaten by the orbit control — the same rule the carousels needed. The reset
   button is a ghost button parked in the corner, since it is easy to tumble a
   model somewhere confusing and there is no other way back. */
.viewer-frame { position: relative; }
.viewer-frame model-viewer {
  display: block; width: 100%;
  height: clamp(340px, 64vh, 680px);
  background-color: var(--color-panel);
  border: 1px solid rgba(22,57,95,.10);
  border-radius: var(--radius-img);
  --poster-color: var(--color-panel);
  --progress-bar-color: var(--color-accent);
  --progress-mask: var(--color-panel);
}
.viewer-frame .viewer-reset {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  font: 700 11.5px/1 var(--font-body); letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--color-accent); background: rgba(255,255,255,.92);
  border: 1px solid var(--color-accent); border-radius: 999px;
  padding: 9px 18px; cursor: pointer;
  transition: background-color .3s ease, color .3s ease;
}
.viewer-frame .viewer-reset:hover,
.viewer-frame .viewer-reset:focus-visible { background: var(--color-accent); color: #FFF; }
@media (max-width: 600px) {
  .viewer-frame .viewer-reset { top: 10px; right: 10px; padding: 8px 14px; font-size: 11px; }
}

/* "Explore in 3D" chip under the 1683 plan card */
.plan-card .card-3d { margin-top: 12px; }
.plan-card .card-3d a {
  display: inline-flex; align-items: center; gap: 8px;
  font: 700 11.5px/1 var(--font-body); letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--color-accent); border: 1px solid var(--color-accent);
  border-radius: 999px; padding: 9px 18px;
  transition: background-color .3s ease, color .3s ease;
}
.plan-card .card-3d a:hover,
.plan-card .card-3d a:focus-visible { background: var(--color-accent); color: #FFF; }
.plan-card .card-3d svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.7; }

/* misc */
.center { text-align: center; }
.mt-lg { margin-top: clamp(36px, 5vw, 60px); }
.mt-md { margin-top: 26px; }
.narrative { max-width: 720px; margin: 0 auto; }
.narrative p + p { margin-top: 18px; }


/* paradise amenity tiles */
.amenity { text-align: center; }
.amenity .tile-photo { display: block; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-img); }
.amenity .tile-photo img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s ease; }
.amenity:hover .tile-photo img { transform: scale(1.04); }
.amenity h3 { font-size: 19px; letter-spacing: 1.5px; text-transform: uppercase; margin-top: 22px; }
.amenity .sub { font: 500 12px/1.6 var(--font-body); letter-spacing: 1px; text-transform: uppercase; color: var(--color-muted); margin-top: 8px; }

/* closing plea band */
.cta-band { position: relative; display: grid; place-items: center; text-align: center; min-height: 54vh; overflow: hidden; }
.cta-band .band-bg { position: absolute; inset: 0; }
.cta-band .band-bg img { width: 100%; height: 100%; object-fit: cover; }
.cta-band .band-bg::after { content: ""; position: absolute; inset: 0; background: var(--scrim-hero); }
.cta-band .inner { position: relative; z-index: 2; padding: 90px var(--gutter); max-width: 860px; }
.cta-band h2 { font-size: clamp(26px, 3.6vw, 40px); line-height: 1.35; color: #FFF; }
.cta-band .btn { margin-top: 34px; }

/* Seam continuation, 2026-08-29 (owner direction: "fade and blur into the
   'We'll build more...' section"). Where a photo-band sits directly above the
   closing band, the photo-band already dissolves to the ember tone measured off
   this band's first row. Fading THIS band's photo in from the same flat tone
   removes the last tell — the abrupt start of cloud texture at the join. Scoped
   to the adjacency, so the closing band is untouched on every other page. */
.section.photo-band + .cta-band { background-color: rgb(121, 92, 64); }
/* The other half of the sky trim. min-height is dropped so the head is the
   padding and nothing else — 54vh made the gap swing 90-150px with window
   height, which is why it read as "excess" on tall screens. Padding stays
   symmetric, so the band is shorter but still balanced. Scoped to the
   adjacency: every other page keeps the full-height closing band. */
.section.photo-band + .cta-band { min-height: 0; }
.section.photo-band + .cta-band .inner {
  padding-top: clamp(72px, 6.8vw, 98px);
  padding-bottom: clamp(72px, 6.8vw, 98px);
}
.section.photo-band + .cta-band > .band-bg {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 13%, #000 32%);
          mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 13%, #000 32%);
}


/* ---------- floor-plan cards (models page) ----------
   Exterior rendering in the frame, model name captioned below,
   plan sheet opens in the lightbox. Cards live in a horizontal
   arrow-paged carousel: 4-up desktop, 2-up mobile, swipe on touch. */
.plan-carousel { position: relative; }
.plan-track {
  --track-gap: clamp(20px, 3vw, 40px);
  display: grid; grid-auto-flow: column;
  grid-template-rows: repeat(2, auto);            /* 2 rows tall — cards stack in 2×2 pages */
  grid-auto-columns: calc((100% - var(--track-gap)) / 2);
  gap: var(--track-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; padding: 4px 2px;
}
.plan-track::-webkit-scrollbar { display: none; }
.plan-track .plan-card { scroll-snap-align: start; }
@media (max-width: 860px) {
  .plan-track { grid-auto-columns: 100%; }        /* 1 column × 2 rows = 2 stacked homes per view */
}

.carousel-arrow {
  /* 50% centers on the full block (photos + captions); pulling up half a
     caption (~120px tall) centers the arrow on the photo cluster instead —
     exactly in the seam between the two image rows at any width. */
  position: absolute; top: calc(50% - 60px); transform: translateY(-50%); z-index: 5;
  width: 55px; height: 55px; border-radius: 50%;
  border: 1px solid var(--color-accent); color: var(--color-accent);
  background: rgba(255,255,255,.95);
  font: 300 30px/1 var(--font-body); cursor: pointer;
  display: grid; place-items: center; padding: 0 0 3px; /* optical centering of the chevron */
  transition: background-color .3s ease, color .3s ease, opacity .3s ease;
}
/* sunset gradient glow halo (owner-approved deviation, 2026-08-23) */
.carousel-arrow::before {
  content: ""; position: absolute; inset: -12px; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(201,135,47,.45), rgba(196,87,63,.22) 55%, transparent 75%);
  transition: opacity .3s ease;
}
.carousel-arrow:hover { background: var(--color-accent); color: #FFF; }
.carousel-arrow:hover::before {
  background: radial-gradient(circle, rgba(201,135,47,.65), rgba(196,87,63,.32) 55%, transparent 78%);
}
.carousel-arrow:active { background: #B3761F; border-color: #B3761F; color: #FFF; }
.carousel-arrow.prev { left: -20px; }
.carousel-arrow.next { right: -20px; }
/* room permitting, float the arrows fully clear of the photos */
@media (min-width: 1340px) {
  .carousel-arrow.prev { left: -72px; }
  .carousel-arrow.next { right: -72px; }
}
@media (max-width: 860px) {
  .carousel-arrow.prev { left: 4px; }
  .carousel-arrow.next { right: 4px; }
}
.carousel-arrow[disabled] { opacity: .3; cursor: default; pointer-events: none; }
/* main.js sets [hidden] when a track has nothing to scroll; .carousel-arrow is
   display:grid, which would otherwise beat the UA's [hidden] rule. */
.carousel-arrow[hidden] { display: none !important; }
.carousel-arrow[disabled]::before { opacity: 0; }

.plan-card { margin: 0; text-align: center; }
.plan-card .plan-photo {
  position: relative; display: block; aspect-ratio: 2.35 / 1;
  overflow: hidden; border-radius: var(--radius-img); cursor: zoom-in;
}
.plan-card .plan-photo img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s ease; }
.plan-card .plan-photo .peek {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.92); opacity: 0; transition: opacity .35s ease;
}
.plan-card .plan-photo .peek::before {
  content: ""; position: absolute; inset: 15px;
  border: 1px solid var(--color-accent); border-radius: calc(var(--radius-img) - 8px); pointer-events: none;
}
.plan-card .plan-photo:hover img, .plan-card .plan-photo:focus-visible img { transform: scale(1.03); }
.plan-card .plan-photo:hover .peek, .plan-card .plan-photo:focus-visible .peek { opacity: 1; }
.plan-card figcaption h3 { font-size: 20px; letter-spacing: 1.5px; text-transform: uppercase; margin-top: 22px; }
.plan-card figcaption .rule { margin: 12px auto 14px; }
.plan-card figcaption .meta {
  font: 500 12px/1.9 var(--font-body); letter-spacing: 1px; text-transform: uppercase;
  color: var(--color-body);
}

/* plan-sheet lightbox */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(16,24,38,.9); padding: clamp(16px, 4vw, 48px);
}
.lightbox[hidden] { display: none; }
.lightbox figure { margin: 0; max-width: min(920px, 100%); max-height: 100%; }
.lightbox img {
  display: block; margin: 0 auto; width: auto; max-width: 100%;
  max-height: calc(100vh - 150px); object-fit: contain;
  background: #FFF; border-radius: var(--radius-img);
}
.lightbox figcaption {
  text-align: center; margin-top: 16px;
  font: 500 13px/1.5 var(--font-body); letter-spacing: 2px; text-transform: uppercase;
  color: #FFF;
}
/* selectable views inside the pop-out (e.g. 2D plan / 3D renders) */
.lightbox figure.has-views img { max-height: calc(100vh - 220px); }
.lightbox-views { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 16px; }
.lightbox-views[hidden] { display: none; }
.lightbox-view {
  border: 1px solid #FFF; color: #FFF; background: transparent;
  border-radius: var(--radius-btn);
  font: 700 11px/1 var(--font-body); letter-spacing: 1px; text-transform: uppercase;
  padding: 10px 16px; cursor: pointer;
  transition: background-color .3s ease, color .3s ease;
}
.lightbox-view:hover { background: rgba(255,255,255,.18); }
.lightbox-view.active { background: #FFF; color: var(--color-primary); }
.lightbox-close {
  position: absolute; top: 22px; right: 26px;
  width: 44px; height: 44px; border: 1px solid #FFF; border-radius: 50%;
  background: transparent; color: #FFF; font: 300 22px/1 var(--font-body);
  cursor: pointer; transition: background-color .3s ease;
}
.lightbox-close:hover { background: rgba(255,255,255,.18); }
.lightbox-close:active { background: rgba(255,255,255,.3); }
body.lightbox-open { overflow: hidden; }

/* legal pages */
.legal-hero { padding: 170px 0 40px; }
.legal-hero h1 { font-size: clamp(28px, 3.6vw, 40px); }
/* The base .breadcrumb is white for hero pages; on the hero-less .legal-hero
   pages it needs a dark colour or it is invisible on white. faq / privacy /
   terms each carry an inline muted override from an earlier build (inline wins
   over this rule, so they are unaffected). This uses --color-body rather than
   --color-muted: 5.7:1 against white instead of 2.8:1, on what is navigation. */
.legal-hero .breadcrumb, .legal-hero .breadcrumb a { color: var(--color-body); }
.legal-hero .breadcrumb a:hover { color: var(--color-accent); }
.legal-hero .updated { font: 500 12px/1 var(--font-body); letter-spacing: 1.5px; text-transform: uppercase; color: var(--color-muted); margin-top: 14px; }
.legal-doc { max-width: 760px; margin: 0 auto; }
.legal-doc h2 { font-size: 20px; letter-spacing: 1.5px; text-transform: uppercase; margin: 44px 0 6px; }
.legal-doc h2 + hr.rule { margin: 14px 0 18px; }
.legal-doc p { margin-bottom: 16px; font-size: var(--body-size); }
.legal-doc ul { margin: 0 0 16px 22px; }
.legal-doc li { margin-bottom: 8px; font-size: var(--body-size); }
