/* ==========================================================================
   KYARA EYRE | WILLIAMS LUXURY HOMES
   Shared stylesheet for every page on the site.
   Edit brand colors and fonts in the :root block below and the whole
   site updates. See README.md for a plain-language guide to this file.
   ========================================================================== */

/* -----------------------------
   1. Google Fonts
   ----------------------------- */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&family=Montserrat:wght@300;400;500;600;700&display=swap');

/* -----------------------------
   2. Brand variables
   ----------------------------- */
:root {
  /* Brand colors */
  --color-black: #000000;
  --color-white: #FFFFFF;
  --color-sand: #F3EDE5;
  --color-taupe: #D6C7B3;
  --color-bronze: #B29B88;

  /* Functional aliases */
  --color-bg: var(--color-sand);
  --color-bg-alt: var(--color-white);
  --color-text: #2a231d;
  --color-heading: #2b2117;
  --color-text-muted: #5C5750;
  --color-border: var(--color-taupe);
  --color-accent: var(--color-bronze);
  --color-accent-dark: #8f7860;

  /* Fonts */
  --font-serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-sans: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;

  /* Spacing scale */
  --space-xs: 0.5rem;
  --space-sm: 1rem;
  --space-md: 2rem;
  --space-lg: 4rem;
  --space-xl: 6rem;

  /* Layout */
  --container-width: 1180px;
  --radius: 2px;
  --nav-height: 82px;
}

/* -----------------------------
   3. Reset
   ----------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Safety net: no element on the site should ever be able to make the page
   itself horizontally scrollable. (This is what let the mobile off-canvas
   nav menu, below, escape the screen sideways rather than simply staying
   hidden off to the right.) Set on html only, not body -- setting it on
   both turns body into its own separate scrollable box, which introduced
   a different glitch (its scroll position could drift independently of
   the page's, shifting the header sideways). html alone fully blocks
   page-level horizontal scrolling without that side effect. */
html { overflow-x: hidden; }
body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  line-height: 1.65;
  font-size: 16px;
}
img { max-width: 100%; display: block; height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { padding-left: 1.25em; }
button { font-family: inherit; cursor: pointer; }
h1, h2, h3, h4 {
  font-family: var(--font-serif);
  font-weight: 500;
  line-height: 1.15;
  margin: 0 0 var(--space-sm);
  color: var(--color-heading);
}
h1 { font-size: clamp(2.4rem, 5vw, 3.8rem); font-weight: 500; letter-spacing: 0.01em; }
h2 { font-size: clamp(1.9rem, 3.4vw, 2.6rem); }
h3 { font-size: clamp(1.4rem, 2.2vw, 1.7rem); }
h4 { font-size: 1.15rem; font-family: var(--font-sans); font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; }
p { margin: 0 0 var(--space-sm); }
.container {
  width: 100%;
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 1.5rem;
}
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--color-black);
  color: var(--color-white);
  padding: 0.75em 1.25em;
  z-index: 10000;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* -----------------------------
   4. Header / Navigation
   ----------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 900;
  background: rgba(255,255,255,0.96);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--color-border);
  transition: box-shadow 0.3s ease;
}
.site-header.is-scrolled { box-shadow: 0 4px 18px rgba(0,0,0,0.06); }
.nav-wrap {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-height);
}
.nav-name-link { display: flex; align-items: center; }
.nav-name {
  font-family: var(--font-serif);
  font-size: 2.1rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--color-black);
  white-space: nowrap;
}
/* Right-hand cluster: nav links, then the WLH brandmark, hugging the
   header's right edge. On mobile, .nav-links goes fixed/off-canvas (see
   below) so this cluster naturally reduces to just the brandmark and
   the hamburger toggle. */
.nav-right { display: flex; align-items: center; gap: 1.65rem; }
.nav-brandmark { display: flex; align-items: center; }
.nav-brandmark img { height: 50px; width: auto; image-rendering: -webkit-optimize-contrast; }
.nav-links {
  display: flex;
  align-items: center;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a {
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-black);
  padding: 0.4rem 0.1rem;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { border-color: var(--color-accent); color: var(--color-accent-dark); }
.nav-cta {
  border: 1px solid var(--color-black) !important;
  padding: 0.6rem 1.05rem !important;
  border-radius: var(--radius);
  white-space: nowrap;
}
.nav-cta:hover { background: var(--color-black); color: var(--color-white) !important; }
.nav-toggle {
  display: none;
  background: none;
  border: none;
  width: 44px;
  height: 44px;
  position: relative;
  z-index: 950;
}
.nav-toggle span, .nav-toggle::before, .nav-toggle::after {
  content: "";
  position: absolute;
  left: 10px;
  right: 10px;
  height: 2px;
  background: var(--color-black);
  transition: transform 0.25s ease, opacity 0.25s ease, top 0.25s ease;
}
.nav-toggle::before { top: 15px; }
.nav-toggle span { top: 21px; }
.nav-toggle::after { top: 27px; }
.nav-toggle[aria-expanded="true"]::before { top: 21px; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span { opacity: 0; }
.nav-toggle[aria-expanded="true"]::after { top: 21px; transform: rotate(-45deg); }

/* Communities dropdown */
.has-dropdown { position: relative; }
.dropdown-toggle {
  display: flex;
  align-items: center;
  gap: 0.35em;
  background: none;
  border: none;
  font-family: inherit;
  color: var(--color-black);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.82rem;
  font-weight: 500;
  padding: 0.4rem 0.1rem;
  cursor: pointer;
}
.dropdown-toggle::after { content: "\2304"; font-size: 0.8rem; color: var(--color-accent-dark); }
.dropdown-menu {
  position: absolute;
  top: 100%;
  left: -1rem;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  min-width: 230px;
  padding: 0.5rem 0;
  box-shadow: 0 16px 32px rgba(0,0,0,0.12);
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
  z-index: 20;
  list-style: none;
  margin: 0;
}
.has-dropdown:hover .dropdown-menu,
.has-dropdown:focus-within .dropdown-menu,
.has-dropdown.is-open .dropdown-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.dropdown-menu a {
  display: block;
  padding: 0.65rem 1.1rem;
  font-size: 0.82rem;
  text-transform: none;
  letter-spacing: 0.02em;
  font-weight: 400;
  border-bottom: none !important;
}
.dropdown-menu a:hover { background: var(--color-sand); }

/* -----------------------------
   5. Buttons & links
   ----------------------------- */
.btn {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.95rem 2rem;
  border: 1px solid var(--color-black);
  border-radius: var(--radius);
  background: var(--color-black);
  color: var(--color-white);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.btn:hover { background: var(--color-white); color: var(--color-black); }
.btn-outline { background: transparent; color: var(--color-black); }
.btn-outline:hover { background: var(--color-black); color: var(--color-white); }
.btn-bronze { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-white); }
.btn-bronze:hover { background: var(--color-accent-dark); border-color: var(--color-accent-dark); color: var(--color-white); }

/* Call + Text as one combined control: a single bordered pill split
   into two tap targets, since a link can only be tel: or sms:, not
   both, but the two can still read as one button visually. */
.btn-split {
  display: inline-flex;
  border: 1px solid var(--color-black);
  border-radius: var(--radius);
  overflow: hidden;
}
.btn-split a {
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.95rem 1.7rem;
  color: var(--color-black);
  background: transparent;
  transition: background 0.25s ease, color 0.25s ease;
}
.btn-split a:first-child { border-right: 1px solid var(--color-black); }
.btn-split a:hover { background: var(--color-black); color: var(--color-white); }
.hero-full .btn-split { border-color: rgba(255,255,255,0.7); }
.hero-full .btn-split a { color: var(--color-white); }
.hero-full .btn-split a:first-child { border-right-color: rgba(255,255,255,0.7); }
.hero-full .btn-split a:hover { background: var(--color-white); color: var(--color-black); }
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-accent-dark);
  border-bottom: 1px solid var(--color-accent);
  padding-bottom: 2px;
}
.text-link:hover { color: var(--color-black); border-color: var(--color-black); }

/* -----------------------------
   6. Sections & layout helpers
   ----------------------------- */
section { padding: var(--space-xl) 0; }
.section-alt { background: var(--color-bg-alt); }
.section-tight { padding: var(--space-lg) 0; }
.eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-accent-dark);
  margin-bottom: 0.75rem;
}
.section-head { max-width: 720px; margin-bottom: var(--space-md); }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.about-faq .section-head.center { max-width: 920px; }
.text-lg { font-size: 1.1rem; margin-bottom: 1.5rem; }
hr.hairline {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-lg) 0;
}
.lede { font-size: 1.15rem; color: var(--color-text-muted); max-width: 62ch; }
.grid {
  display: grid;
  gap: 2.25rem;
}
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Communities grid: center the incomplete last row (5 cards in a 3-col grid) */
#communities .grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
#communities .grid .card { flex: 1 1 calc(33.333% - 1.5rem); max-width: calc(33.333% - 1.5rem); }
.two-col {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-lg);
  align-items: center;
}

/* -----------------------------
   7. Placeholder image blocks
   ----------------------------- */
.placeholder-img {
  background: repeating-linear-gradient(135deg, #ffffff, #ffffff 10px, #e9e0d2 10px, #e9e0d2 20px);
  border: 1px dashed var(--color-bronze);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  padding: 1.5rem;
  min-height: 260px;
  border-radius: var(--radius);
}
.placeholder-img.tall { min-height: 420px; }
.placeholder-img.short { min-height: 160px; }
.placeholder-img span { max-width: 30ch; }
.placeholder-img.hero-ph { min-height: 560px; }
.placeholder-img.square { min-height: 0; aspect-ratio: 1 / 1; }

/* Stock/interim photo fill: once a real photo replaces the "build note"
   text, add has-photo so the dashed placeholder styling drops away and
   the image covers the same box the placeholder reserved. Swap the img's
   src for Kyara's own photo later; no markup or CSS changes needed. */
.placeholder-img.has-photo {
  background: none;
  border: none;
  padding: 0;
  overflow: hidden;
}
/* Fixed aspect-ratio so every "short" photo card (community grid, listing
   tiles, area-page photo grids) renders the same box size regardless of
   the source photo's native dimensions. Without this, height:100% below
   has no basis to resolve against and photos fall back to their own
   aspect ratio, making some cards render visibly smaller than others. */
.placeholder-img.short.has-photo { aspect-ratio: 3 / 2; min-height: 0; }
.placeholder-img.has-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;
}

/* Clickable-photo affordance for .gallery-item: a slow zoom on the
   photo plus an expand icon overlay, so it reads as "click to enlarge"
   before a visitor ever taps it. Works with the lightbox click handler
   already wired up in main.js. Safe to reuse on any gallery-item. */
.gallery-item .placeholder-img.has-photo { position: relative; }
.gallery-item .placeholder-img.has-photo img { transition: transform 0.5s ease; }
.gallery-item:hover .placeholder-img.has-photo img,
.gallery-item:focus-visible .placeholder-img.has-photo img { transform: scale(1.06); }
.gallery-expand-icon {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20,16,12,0);
  opacity: 0;
  transition: opacity 0.3s ease, background 0.3s ease;
  pointer-events: none;
}
.gallery-item:hover .gallery-expand-icon,
.gallery-item:focus-visible .gallery-expand-icon { opacity: 1; background: rgba(20,16,12,0.22); }
.gallery-expand-icon svg { width: 30px; height: 30px; color: #fff; }
.instagram-tile { display: block; color: inherit; transition: opacity 0.2s ease; }
.instagram-tile:hover { opacity: 0.85; }

/* WLH Listings tiles: photo + address/price under it, with an optional
   status badge (Active / Sale Pending) in the top corner of the photo. */
.listing-tile-photo { position: relative; }
.listing-tile-badge {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2;
  background: var(--color-heading);
  color: var(--color-white);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.35rem 0.7rem;
  border-radius: 3px;
}
.listing-tile-badge.pending { background: var(--color-bronze); }
.listing-tile-badge.sold { background: var(--color-heading); }
.listing-tile-info { padding-top: 0.85rem; }
.listing-tile-info h3 { margin: 0 0 0.3rem; font-size: 1.05rem; }
.listing-tile-info p { margin: 0; color: var(--color-text-muted); font-size: 0.85rem; }
.view-all-tile {
  background: var(--color-heading);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.view-all-tile span {
  color: var(--color-white);
  font-family: var(--font-serif, serif);
  font-size: 1.3rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.view-all-arrow { font-size: 1.5rem; transition: transform 0.2s ease; }
.instagram-tile:hover .view-all-arrow { transform: translateX(6px); }

/* Status badge for a listing hero (e.g. Under Contract), shown near the
   eyebrow when a listing is not actively available for showings. */
.hero-status-badge {
  display: inline-block;
  background: var(--color-bronze);
  color: var(--color-white);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.35rem 0.75rem;
  border-radius: 3px;
  margin-top: 0.9rem;
}
.hero-status-badge.sold { background: var(--color-heading); }

/* Listings page tabs: Current / Sold / Rentals. Only the active panel
   is shown; content for every tab still lives in the page's HTML. */
.listing-tabs {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0 0 2.5rem;
}
.listing-tab-btn {
  font: inherit;
  cursor: pointer;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  padding: 0.6rem 1.5rem;
  border-radius: 999px;
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.listing-tab-btn:hover { border-color: var(--color-accent-dark); color: var(--color-heading); }
.listing-tab-btn.is-active {
  background: var(--color-heading);
  border-color: var(--color-heading);
  color: var(--color-white);
}
.listing-tab-panel { display: none; }
.listing-tab-panel.is-active { display: block; }
.listing-tab-empty {
  text-align: center;
  color: var(--color-text-muted);
  max-width: 50ch;
  margin: 0 auto;
  padding: 2rem 0;
}

/* HubSpot embedded form wrapper (Home Search concierge form).
   HubSpot's embed script injects its own markup and inline styles;
   this just aligns the container width and base typography with the
   rest of the site without fighting the widget's own field styling. */
.hubspot-embed-wrap {
  max-width: 640px;
  margin: 0 auto;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 2rem;
}
.hubspot-embed-wrap,
.hubspot-embed-wrap * {
  font-family: var(--font-sans) !important;
}
.hubspot-embed-loading {
  text-align: center;
  color: var(--color-text-muted);
  padding: 1.5rem 0;
}

/* Instagram carousel: horizontal scroll with hover-revealed arrows */
.instagram-carousel { position: relative; }
.instagram-track {
  display: flex;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-bottom: 0.25rem;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.instagram-track::-webkit-scrollbar { display: none; }
.instagram-track .instagram-tile {
  flex: 0 0 340px;
  max-width: 340px;
  scroll-snap-align: start;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-white);
}
.instagram-track .instagram-tile iframe {
  display: block;
  width: 100%;
  border: 0;
}
.instagram-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-heading);
  opacity: 0;
  transition: opacity 0.2s ease, background 0.2s ease, color 0.2s ease;
  cursor: pointer;
  z-index: 2;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.instagram-arrow svg { width: 18px; height: 18px; }
.instagram-arrow.prev { left: -22px; }
.instagram-arrow.next { right: -22px; }
.instagram-arrow:hover { background: var(--color-heading); color: var(--color-white); }
.instagram-carousel:hover .instagram-arrow,
.instagram-arrow:focus-visible { opacity: 1; }
@media (max-width: 980px) {
  .instagram-track .instagram-tile { flex-basis: 300px; max-width: 300px; }
  .instagram-arrow.prev { left: 4px; }
  .instagram-arrow.next { right: 4px; }
}
@media (max-width: 620px) {
  .instagram-track .instagram-tile { flex-basis: 88%; max-width: 88%; }
  .instagram-arrow { opacity: 1; }
}

/* Lifestyle photo carousel (about page): back to the original, larger
   photo size the old 3-across static grid used ((1180px container -
   2 gaps) / 3 = 380px), instead of the smaller 340px default the
   Instagram-embed carousel tiles use. Same arrow/scroll mechanics,
   scoped so the actual Instagram embeds below are untouched. */
.lifestyle-carousel .instagram-track .instagram-tile {
  flex: 0 0 380px;
  max-width: 380px;
}
@media (max-width: 980px) {
  .lifestyle-carousel .instagram-track .instagram-tile { flex-basis: 340px; max-width: 340px; }
}
@media (max-width: 620px) {
  .lifestyle-carousel .instagram-track .instagram-tile { flex-basis: 90%; max-width: 90%; }
}
/* These tiles reuse the site-wide .placeholder-img.short.has-photo box,
   which is a landscape 3/2 crop shared by area-page and listing photo
   grids elsewhere. These particular shots are candid, mostly upright
   photos, so that wide crop was clipping them into a squat landscape
   shape. Taller portrait crop (4/5, an Instagram-post shape, fitting
   for this carousel) scoped to just this carousel's tiles. */
.lifestyle-carousel .instagram-track .instagram-tile .placeholder-img.short.has-photo {
  aspect-ratio: 4 / 5;
}

/* Instagram follow card: a single CTA in place of live post embeds
   (Instagram's own embed widget does not reliably resize on this
   domain, so we link out instead rather than show broken placeholders). */
.instagram-cta {
  max-width: 420px;
  margin: 0 auto;
  text-align: center;
  padding: 2.5rem 2rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-white);
}
.instagram-cta-icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 1.1rem;
  border-radius: 50%;
  background: var(--color-sand);
  color: var(--color-heading);
  display: flex;
  align-items: center;
  justify-content: center;
}
.instagram-cta-icon svg { width: 24px; height: 24px; }
.instagram-cta-handle {
  font-family: var(--font-serif);
  font-size: 1.3rem;
  color: var(--color-heading);
  margin: 0 0 0.5rem;
}
.instagram-cta-text {
  color: var(--color-text-muted);
  font-size: 0.92rem;
  line-height: 1.6;
  margin: 0 0 1.5rem;
}

/* -----------------------------
   8. Hero
   ----------------------------- */
.hero {
  position: relative;
  padding-top: var(--space-lg);
  padding-bottom: var(--space-xl);
}
.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-md);
}
.hero-inner.has-photo {
  grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
  gap: var(--space-lg);
  align-items: center;
}
.hero-inner.has-photo .hero-photo {
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 3 / 4;
}
.hero-inner.has-photo .hero-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero h1 { max-width: 16ch; }
.hero.center-text { text-align: center; }
.hero.center-text h1 { max-width: 46ch; margin-left: auto; margin-right: auto; }
.hero.center-text .lede { max-width: 90ch; font-size: 1.28rem; margin-top: 2.75rem; margin-left: auto; margin-right: auto; }
.hero-actions { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: var(--space-md); }
.hero-stats {
  display: flex;
  gap: var(--space-md);
  margin-top: var(--space-lg);
  flex-wrap: wrap;
}
.hero-stats div { border-left: 1px solid var(--color-border); padding-left: 1rem; }
.hero-stats div:last-child { border-right: 1px solid var(--color-border); padding-right: 1rem; }
.hero-stats strong { display: block; font-family: var(--font-serif); font-size: 1.6rem; color: var(--color-black); }
.hero-stats span { font-size: 0.78rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-text-muted); }

/* -----------------------------
   8b. Full-bleed photo/video hero (home + area pages)
   Markup:
     <section class="hero-full">
       <div class="hero-bg"><div class="placeholder-img">...photo/video goes here...</div></div>
       <div class="hero-content"> ...eyebrow / h1 / lede / actions / stats... </div>
     </section>
   Swap the placeholder-img div for an <img> or <video> covering the
   same space (object-fit: cover) when real footage is available.
   ----------------------------- */
.hero-full {
  position: relative;
  min-height: 82vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: var(--space-xl) 1.5rem;
  text-align: center;
  color: var(--color-white);
}
.hero-full .hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-full .hero-bg > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
  border: none;
  margin: 0;
}
.hero-full .hero-bg img,
.hero-full .hero-bg video {
  object-fit: cover;
}
.hero-full .hero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,16,12,0.4) 0%, rgba(20,16,12,0.62) 100%);
}
.hero-full .hero-content {
  position: relative;
  z-index: 1;
  max-width: 920px;
  margin: 0 auto;
}
.hero-full .eyebrow { color: var(--color-sand); }
.hero-full h1 { color: var(--color-white); max-width: none; }
.hero-full .lede { color: rgba(255,255,255,0.9); max-width: 76ch; margin-left: auto; margin-right: auto; }
.hero-full .hero-actions { justify-content: center; }
.hero-full .hero-stats { justify-content: center; }
.hero-full .hero-stats div { border-left-color: rgba(255,255,255,0.35); }
.hero-full .hero-stats div:last-child { border-right-color: rgba(255,255,255,0.35); }
.hero-full .hero-stats strong { color: var(--color-white); }
.hero-full .hero-stats span { color: rgba(255,255,255,0.75); }
.hero-full .btn-outline { border-color: rgba(255,255,255,0.7); color: var(--color-white); }
.hero-full .btn-outline:hover { background: var(--color-white); color: var(--color-black); }

/* Placeholder-only: pins the "photo/video goes here" build note to a small
   corner tag so it never overlaps the centered headline. This note (and this
   rule) disappears once a real photo/video replaces the placeholder markup. */
.hero-full .hero-bg .placeholder-img {
  display: block;
  padding: 0;
}
.hero-full .hero-bg .placeholder-img span {
  position: absolute;
  top: 1rem;
  left: 1rem;
  max-width: 32ch;
  font-size: 0.65rem;
  line-height: 1.4;
  text-align: left;
  color: rgba(255,255,255,0.75);
  background: rgba(0,0,0,0.4);
  padding: 0.45rem 0.65rem;
  border-radius: 4px;
}

/* Hero background carousel: several photos/videos cross-fading and
   drifting gently to the right on a continuous loop. Swap each
   placeholder-img for a real <img> or <video> (object-fit: cover) when
   footage is available; the slide/animation mechanics stay the same. */
.hero-carousel { position: absolute; inset: 0; }
.hero-carousel .hero-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  animation-name: heroSlideCycle;
  animation-duration: 24s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animation-fill-mode: both;
}
.hero-carousel .hero-slide .placeholder-img { position: absolute; inset: 0; }
/* Bug fix: the carousel nests each photo/video three levels deep inside
   .hero-bg (hero-bg > hero-carousel > hero-slide > placeholder-img > img/video),
   but the earlier ".hero-full .hero-bg > *" sizing rule only reaches a DIRECT
   child of .hero-bg, so it never applied width/height/position to the actual
   media element. Without an explicit box, a replaced element (img/video) that's
   absolutely positioned with inset:0 but no width/height falls back to its own
   intrinsic size instead of stretching to fill the slide — so every hero video
   was rendering at its native pixel size, anchored top-left, and just getting
   clipped by the section's overflow:hidden. That silently defeated object-fit
   and object-position (both need the box to differ from the intrinsic size to
   do anything), which is why the per-clip framing/position rules above had no
   visible effect. This rule reaches the actual media element so it fills its
   slide properly and the object-fit/object-position rules can take effect. */
.hero-carousel .hero-slide .placeholder-img img,
.hero-carousel .hero-slide .placeholder-img video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-carousel .hero-slide:nth-child(1) { animation-delay: 0s; }
.hero-carousel .hero-slide:nth-child(2) { animation-delay: 6s; }
.hero-carousel .hero-slide:nth-child(3) { animation-delay: 12s; }
.hero-carousel .hero-slide:nth-child(4) { animation-delay: 18s; }
@keyframes heroSlideCycle {
  0% { opacity: 0; transform: translateX(-2.5%) scale(1.04); }
  4% { opacity: 1; transform: translateX(0) scale(1.04); }
  20% { opacity: 1; transform: translateX(0) scale(1.07); }
  25% { opacity: 0; transform: translateX(2.5%) scale(1.07); }
  100% { opacity: 0; }
}
@media (max-width: 760px) {
  .hero-full { min-height: 72vh; padding: var(--space-lg) 1.25rem; }
}

/* When JavaScript is available, main.js adds .js-carousel and drives
   slide changes itself (each video plays its full natural length;
   each photo holds for a fixed duration) instead of the fixed CSS
   timing above, toggling .is-active on the current .hero-slide. */
.js-carousel .hero-slide {
  animation: none;
  opacity: 0;
  transition: opacity 1.1s ease;
}
.js-carousel .hero-slide.is-active {
  opacity: 1;
  z-index: 1;
}
.js-carousel .hero-slide.is-active .placeholder-img img,
.js-carousel .hero-slide.is-active .placeholder-img video {
  animation: heroKenBurns 9s ease-out forwards;
}
@keyframes heroKenBurns {
  from { transform: scale(1); }
  to { transform: scale(1.06); }
}

/* -----------------------------
   9. Cards (areas, blog, listings)
   ----------------------------- */
.card {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: 0 16px 32px rgba(0,0,0,0.08); }
a.card { text-decoration: none; color: inherit; }
.card-body { padding: 1.5rem 1.5rem 1.75rem; flex: 1; display: flex; flex-direction: column; }
.card-body h3 { margin-bottom: 0.5rem; }
.card-body p { color: var(--color-text-muted); font-size: 0.95rem; }
.card-meta {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-dark);
  margin-bottom: 0.5rem;
}
.card-footer-link { margin-top: auto; padding-top: 1rem; }

/* -----------------------------
   10. Testimonial
   ----------------------------- */
.testimonial {
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
}
.testimonial blockquote {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(1.3rem, 2.6vw, 1.7rem);
  line-height: 1.5;
  margin: 0 0 1.25rem;
  color: var(--color-black);
}
.testimonial cite {
  display: block;
  font-style: normal;
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-top: 1.25rem;
}
.testimonial cite::before {
  content: "";
  display: block;
  width: 32px;
  height: 1px;
  background: var(--color-accent);
  margin: 0 auto 0.9rem;
}

/* -----------------------------
   11. Forms
   ----------------------------- */
.form-field { margin-bottom: 1.4rem; }
.form-field label {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
  color: var(--color-black);
}
.form-field input,
.form-field textarea,
.form-field select {
  width: 100%;
  padding: 0.85rem 1rem;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-white);
  color: var(--color-text);
}
.form-field input:focus,
.form-field textarea:focus,
.form-field select:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.form-note { font-size: 0.82rem; color: var(--color-text-muted); }
.form-success {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 2rem;
  text-align: center;
}
.form-success h3 { font-family: var(--font-serif); margin-bottom: 0.5rem; }
.form-success p { color: var(--color-text-muted); margin: 0; }
.form-error {
  font-size: 0.85rem;
  color: #a33;
  margin-top: 1rem;
}

/* -----------------------------
   12. FAQ accordion
   ----------------------------- */
.faq-block { max-width: 820px; }
.faq-item {
  border-bottom: 1px solid var(--color-border);
  padding: 1.25rem 0;
}
.faq-item summary {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--color-black);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary h3 { font-size: 1.2rem; font-weight: 500; margin: 0; color: inherit; font-family: var(--font-serif); }
.faq-item summary::after {
  content: "+";
  font-size: 1.5rem;
  color: var(--color-accent-dark);
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { margin-top: 0.9rem; color: var(--color-text-muted); }

/* -----------------------------
   13. Breadcrumbs
   ----------------------------- */
.breadcrumb {
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  padding: 1.25rem 0 0;
}
.breadcrumb a { color: var(--color-text-muted); border-bottom: 1px solid transparent; }
.breadcrumb a:hover { color: var(--color-black); border-color: var(--color-black); }
.breadcrumb span[aria-hidden] { margin: 0 0.5em; }

/* -----------------------------
   14. Footer
   ----------------------------- */
.site-footer {
  background: var(--color-accent);
  color: #241c14;
  padding: 2rem 0 0;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr 1fr;
  align-items: center;
  gap: var(--space-md);
  padding-bottom: var(--space-md);
  border-bottom: 1px solid rgba(0,0,0,0.18);
}
.footer-logo img { height: 64px; width: auto; margin-bottom: 1rem; image-rendering: -webkit-optimize-contrast; }
.footer-col h4 { color: #1a140e; font-size: 0.78rem; margin-bottom: 1rem; }
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin-bottom: 0.6rem; }
.footer-col a { color: #3d3226; font-size: 0.9rem; }
.footer-col a:hover { color: #1a140e; }
.footer-socials { display: flex; gap: 1.4rem; flex-wrap: wrap; justify-content: center; margin: var(--space-md) 0 1.25rem; }
.footer-socials a {
  border: 1px solid rgba(0,0,0,0.3);
  border-radius: 50%;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: inherit;
}
.footer-socials a:hover { background: #1a140e; color: var(--color-white); border-color: #1a140e; }
.footer-socials svg { display: block; width: 16px; height: 16px; }
.footer-profiles {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.25rem;
  margin-top: 0;
  margin-bottom: 1.25rem;
  font-size: 0.78rem;
}
.footer-profiles a { color: #3d3226; text-decoration: underline; text-underline-offset: 2px; }
.footer-profiles a:hover { color: #1a140e; }
.footer-bottom {
  background: var(--color-black);
  color: #cfc9c0;
  margin-top: var(--space-md);
  padding: 1.1rem 0;
}
.footer-bottom .container {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  font-size: 0.72rem;
}
.footer-bottom a { color: #cfc9c0; }
.footer-bottom a:hover { color: var(--color-white); }
.footer-eho { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; max-width: 100%; }
.footer-eho-badge {
  border: 1px solid #cfc9c0;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6rem;
  flex-shrink: 0;
}
.footer-eho > span:not(.footer-eho-badge) { min-width: 0; }
.footer-legal-links { display: flex; gap: 1rem; flex-wrap: wrap; }
.footer-legal-links span { min-width: 0; }

/* -----------------------------
   14b. Headshot frame: offset rectangle behind the photo
   ----------------------------- */
.headshot-frame { position: relative; display: inline-block; max-width: 100%; }
.headshot-frame > img { display: block; position: relative; z-index: 1; }
.headshot-frame::before {
  content: "";
  position: absolute;
  top: 7%;
  left: -8%;
  width: 92%;
  height: 96%;
  background: var(--color-accent);
  opacity: 0.9;
  border-radius: 2px;
  z-index: 0;
}
@media (max-width: 560px) {
  .headshot-frame::before { top: 5%; left: -5%; width: 90%; height: 94%; }
}
/* Listings-page hero photo reuses the headshot-frame accent, but wraps a
   full-width placeholder-img box instead of a bare img, so it needs the
   frame to stay block-level/full-width and the nested box lifted above
   the offset rectangle (headshot-frame > img alone won't reach it). */
.hero.section-tight .headshot-frame { display: block; width: 100%; }
.headshot-frame > .placeholder-img { position: relative; z-index: 1; }

/* Homepage-only hero overlay: lighter and more transparent than the
   standard .hero-full overlay used on listing pages (those stay darker
   on purpose, for text legibility over varied, sometimes bright listing
   photos). Scoped to .hero-home so listing pages are unaffected. */
.hero-full.hero-home .hero-bg::after {
  background: linear-gradient(180deg, rgba(43,33,23,0.32) 0%, rgba(43,33,23,0.4) 55%, rgba(43,33,23,0.6) 100%);
}
/* Sized a bit shorter than the hero footage's native 16:9 (1600x900) shape
   so the banner reads as a smaller block, not a full-height slab. The box
   is wider than the media now, so object-fit:cover trims a little off the
   top and bottom only (never the sides) — object-position defaults to
   center, so the video/photo stays centered in the crop. Fixed AR (not a
   viewport-height min-height) keeps this identical at any screen size.
   Keeps listing-page photo heroes (plain .hero-full) untouched. */
.hero-full.hero-home {
  aspect-ratio: 2.3 / 1;
  min-height: 0;
}
.hero-full.hero-home .hero-content .eyebrow,
.hero-full.hero-home .hero-content h1,
.hero-full.hero-home .hero-content .lede {
  text-shadow: 0 2px 14px rgba(0,0,0,0.4);
}

/* Per-clip vertical centering. At this box shape, the crop always comes
   out of the top and bottom only (see above) — default center/center
   splits that crop evenly, but each clip frames Kyara at a different
   height, so an even split isn't the same as *her* being centered: in
   some clips it was clipping into her hair, in others it was needlessly
   cutting her feet while leaving empty headroom above her untouched.
   These per-video offsets (matched by each clip's poster filename, so
   they apply wherever a clip is used) shift the crop to keep her fully
   in frame first, giving up the least-noticeable margin (headroom,
   rather than her feet or face) wherever the full body doesn't fit. */
.hero-full.hero-home .hero-bg video[poster*="hero-home-windows"] {
  object-position: center 100%;
}
.hero-full.hero-home .hero-bg video[poster*="hero-home-grass"] {
  object-position: center 20%;
}
.hero-full.hero-home .hero-bg video[poster*="hero-about-pinkdress-door"] {
  object-position: center 50%;
}

/* About-page video reel: now matches the homepage hero banner exactly
   (same min-height and overlay, via the shared .hero-home class on the
   section) so the two full-bleed video banners feel identical site-wide. */

/* On narrow phones, the 2.3:1 box above gets so short (e.g. ~170px on a
   390px-wide screen) that the video reads as a cramped, badly-cropped
   strip. Taller ratio on mobile only, so the video banner still reads as
   a real, presentable moment instead of a sliver. */
@media (max-width: 760px) {
  /* aspect-ratio alone isn't enough: it makes the box shrink faster than
     the text does as the screen gets narrower (checked at 606px wide,
     where the fix looked fine, but a real phone at 375-430px wide is
     narrow enough that the box outruns the text again and clips it).
     min-height is a floor aspect-ratio can't undercut, so the box only
     gets taller than 4:3 on the narrowest phones, never shorter than
     the content needs regardless of width. */
  /* width:100% pins this box to its container BEFORE the ratio/min-height
     below are applied. Without it, Chrome sometimes derives the box's
     WIDTH from min-height via the aspect-ratio (480px x 4/3 = 640px)
     instead of the normal direction (deriving height from width) -- 34px
     wider than the screen, which quietly pushed the whole page into
     being horizontally scrollable and let the header/logo get cropped
     on the right edge. Locking width first removes the ambiguity. */
  .hero-full.hero-home { width: 100%; aspect-ratio: 4 / 3; min-height: 480px; }
  /* The video banner's box is much shorter than a typical full hero, so
     the headline/lede/stats stack (sized for a tall hero) was overflowing
     the box and getting visually cut off by .hero-full's overflow:hidden.
     Scaled the whole content stack down to fit comfortably. */
  .hero-full.hero-home .hero-content .eyebrow {
    font-size: 0.68rem;
    margin-bottom: 0.5rem;
  }
  .hero-full.hero-home .hero-content h1 {
    font-size: clamp(1.4rem, 6vw, 1.85rem);
    line-height: 1.2;
  }
  .hero-full.hero-home .hero-content .lede {
    font-size: 0.85rem;
    line-height: 1.5;
    margin-top: 0.65rem;
  }
  .hero-full.hero-home .hero-actions {
    margin-top: 1rem;
    gap: 0.6rem;
  }
  .hero-full.hero-home .hero-actions .btn {
    padding: 0.65rem 1rem;
    font-size: 0.78rem;
  }
  .hero-full.hero-home .hero-stats {
    margin-top: 1rem;
    gap: 0.75rem;
  }
  .hero-full.hero-home .hero-stats strong { font-size: 1.15rem; }
  .hero-full.hero-home .hero-stats span { font-size: 0.62rem; }
}

/* Personal K/E monogram badge (kept in case it's reused elsewhere later) */
.personal-mark {
  position: absolute;
  bottom: -24px;
  right: -24px;
  width: 116px;
  height: 116px;
  background: var(--color-black);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 50%;
  box-shadow: 0 10px 24px rgba(20,16,12,0.22);
  display: flex;
  align-items: center;
  justify-content: center;
}
.personal-mark img { width: 68%; height: 68%; object-fit: contain; display: block; }
@media (max-width: 560px) {
  .personal-mark { width: 78px; height: 78px; bottom: -14px; right: -14px; }
}

/* Large decorative watermark: the personal K/E mark, oversized and faint,
   bleeding off the edge of a section as a background texture. Give the
   parent section position:relative and wrap its inner content in
   .watermark-content (position:relative; z-index:1) so text stays on top. */
.section-watermark {
  position: relative;
  overflow: hidden;
}
.section-watermark::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -6%;
  width: 46%;
  max-width: 620px;
  aspect-ratio: 444 / 381;
  transform: translateY(-50%);
  background-image: url("../assets/images/monogram-script-bronze.png");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0.16;
  pointer-events: none;
  z-index: 0;
}
.watermark-content { position: relative; z-index: 1; }
@media (max-width: 760px) {
  .section-watermark::before { width: 70%; left: -12%; opacity: 0.13; }
}
.section-watermark.watermark-corner::before {
  top: 30px;
  bottom: auto;
  transform: none;
  width: 30%;
  max-width: 420px;
  left: 2%;
  opacity: 0.13;
}
@media (max-width: 760px) {
  .section-watermark.watermark-corner::before { width: 50%; left: -6%; top: 10px; }
}

/* About page bio section only: mirror the watermark to sit behind the
   blurb column (right side of the two-col layout) instead of behind the
   headshot photo. Scoped with .watermark-corner-right so every other
   page's .watermark-corner (photo/left-column layouts) is untouched. */
.section-watermark.watermark-corner.watermark-corner-right::before {
  left: auto;
  right: 2%;
  width: 40%;
  max-width: 560px;
}
@media (max-width: 760px) {
  .section-watermark.watermark-corner.watermark-corner-right::before { left: auto; right: -10%; width: 62%; }
}

/* Blog index hero only: nudge the watermark up from its default vertical
   center. Scoped with .watermark-high so every other page's default
   .section-watermark centering is untouched. */
.section-watermark.watermark-high::before {
  top: 32%;
}

/* -----------------------------
   15. Lightbox
   ----------------------------- */
.gallery-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.gallery-item { cursor: pointer; border: none; padding: 0; background: none; text-align: left; }
.lightbox-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.92);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 2rem;
}
.lightbox-overlay.is-open { display: flex; }
.lightbox-content { max-width: 900px; width: 100%; color: var(--color-white); text-align: center; }
.lightbox-close {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  background: none;
  border: 1px solid rgba(255,255,255,0.4);
  color: var(--color-white);
  width: 42px;
  height: 42px;
  border-radius: 50%;
  font-size: 1rem;
}
.lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(255,255,255,0.4);
  color: var(--color-white);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  font-size: 1.6rem;
  line-height: 1;
  display: none;
  align-items: center;
  justify-content: center;
}
.lightbox-overlay.has-nav .lightbox-arrow { display: flex; }
.lightbox-arrow:hover { background: rgba(0,0,0,0.6); }
.lightbox-prev { left: 1rem; }
.lightbox-next { right: 1rem; }
@media (max-width: 640px) {
  .lightbox-arrow { width: 40px; height: 40px; font-size: 1.3rem; }
  .lightbox-prev { left: 0.4rem; }
  .lightbox-next { right: 0.4rem; }
}

/* -----------------------------
   15b. Listing video tour
   ----------------------------- */
.video-tour-frame {
  max-width: 380px;
  margin: 2rem auto 0;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 18px 40px rgba(0,0,0,0.18);
  background: var(--color-black);
}
.video-tour-frame video {
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
}

/* Horizontal variant for a proper landscape walkthrough video */
.video-tour-frame.horizontal {
  max-width: 860px;
}
.video-tour-frame.horizontal video {
  aspect-ratio: 16 / 9;
  object-fit: contain;
}
.video-tour-frame.horizontal iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
}

/* -----------------------------
   16. Cookie consent banner
   ----------------------------- */
.cookie-banner {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  max-width: 560px;
  margin: 0 auto;
  background: var(--color-white);
  border: 1px solid var(--color-black);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px rgba(0,0,0,0.18);
  padding: 1.5rem;
  z-index: 3000;
  display: none;
}
.cookie-banner.is-visible { display: block; }
.cookie-banner p { font-size: 0.88rem; color: var(--color-text-muted); margin-bottom: 1rem; }
.cookie-banner-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.cookie-banner .btn { padding: 0.7rem 1.4rem; font-size: 0.72rem; }

/* -----------------------------
   17. Scroll reveal motion
   ----------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* -----------------------------
   18. Misc content blocks
   ----------------------------- */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
  text-align: center;
}
.stat-strip strong { display: block; font-family: var(--font-serif); font-size: 2.1rem; color: var(--color-black); }
.stat-strip span { font-size: 0.78rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); }
.verify-flag {
  display: inline-block;
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background: #fff3d6;
  color: #7a5b00;
  border: 1px solid #e3c168;
  border-radius: var(--radius);
  padding: 0.1em 0.5em;
  margin-left: 0.35em;
}
.callout {
  background: var(--color-bg-alt);
  border-left: 3px solid var(--color-accent);
  padding: 1.5rem 1.75rem;
  border-radius: var(--radius);
}
.author-byline {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: var(--space-sm);
}
.author-byline img { width: 46px; height: 46px; border-radius: 50%; object-fit: cover; }
.tag-pill {
  display: inline-block;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.3em 0.9em;
  color: var(--color-text-muted);
}
.cta-band {
  background: var(--color-accent);
  color: #241c14;
  text-align: center;
  padding: var(--space-lg) 0;
}
.cta-band h2 { color: var(--color-white); }
.cta-band .lede { color: #3d3226; margin-left: auto; margin-right: auto; }
.cta-band { padding: var(--space-lg) 0 0; }
.cta-band .container {
  padding-bottom: 3rem;
  border-bottom: 1px solid rgba(0,0,0,0.18);
}
.cta-band .container > div:last-child { margin-top: 2.5rem; }
.cta-band .btn { margin: 0 0.5rem; }
.cta-band .btn-bronze { background: var(--color-black); border-color: var(--color-black); color: var(--color-white); }
.cta-band .btn-bronze:hover { background: var(--color-white); color: var(--color-black); border-color: var(--color-black); }
.cta-band .btn-outline { border-color: #1a140e; color: #1a140e; }
.cta-band .btn-outline:hover { background: #1a140e; color: var(--color-white); border-color: #1a140e; }
table.data-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.data-table th, table.data-table td {
  text-align: left;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--color-border);
}
table.data-table th { font-family: var(--font-sans); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); }
figure.table-wrap { overflow-x: auto; margin: 0; }

/* -----------------------------
   19. Responsive breakpoints
   ----------------------------- */
@media (max-width: 980px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  /* minmax(0, 1fr), not bare 1fr: a grid item's default min-width is
     "auto" (its own content's min-content size), so a plain 1fr track
     refuses to shrink past that -- if any text block inside happens to
     need ~440px to fit its longest unbreakable run, the column (and the
     text) sits 440px wide no matter how narrow the screen is, running
     off the right edge instead of wrapping. minmax(0, 1fr) removes that
     floor so the column, and the text inside it, always shrinks to fit
     the actual screen. */
  .two-col { grid-template-columns: minmax(0, 1fr); }
  .stat-strip { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
  #communities .grid .card { flex: 1 1 calc(50% - 1.125rem); max-width: calc(50% - 1.125rem); }
}

/* Contact page office map + blurb: this pair is short enough to stay
   side by side well past the general .two-col tablet breakpoint above,
   so it gets its own narrower stacking point instead of collapsing to a
   single column (map on top, blurb pushed down) as early as everything
   else does. Higher specificity than both .two-col rules above so it
   wins at 980px; still stacks on true mobile widths. */
.office-map-row.two-col { grid-template-columns: 1fr 1fr; }
@media (max-width: 560px) {
  .office-map-row.two-col { grid-template-columns: minmax(0, 1fr); }
}
/* The map's .placeholder-img box uses aspect-ratio:3/2 (shared with photo
   gallery tiles elsewhere on the site). In a narrow grid column that
   aspect-ratio computes a width wider than the column itself, so the box
   overflows its own grid cell and covers the blurb text next to it.
   Constrain it to the column width so it stays inside its own cell. */
.office-map-row.two-col > .placeholder-img { width: 100%; max-width: 100%; }

@media (max-width: 760px) {
  :root { --nav-height: 62px; }
  /* .site-header's backdrop-filter (blur) makes it the containing block
     for any position:fixed descendant, instead of the real viewport.
     That broke the off-canvas .nav-links panel two ways: its height had
     to be worked around with a viewport unit below, and worse, the panel
     was no longer truly "fixed to the screen" -- so its off-canvas
     (closed) position past the right edge counted as real, scrollable
     page content instead of being safely off-screen, letting the page
     scroll sideways and land on what looked like a menu stuck against
     the right edge. Disabling the blur here removes the whole class of
     bug at its source; the header's background is already an opaque 96%
     white, so the blur was never doing much visible work on mobile
     anyway. */
  .site-header { backdrop-filter: none; }
  .nav-links {
    position: fixed;
    top: var(--nav-height);
    left: 0;
    right: 0;
    height: calc(100vh - var(--nav-height));
    background: var(--color-white);
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 0;
    padding: 1rem 1.5rem 1.5rem;
    transform: translateX(100%);
    transition: transform 0.3s ease;
    overflow-y: auto;
  }
  .nav-links.is-open { transform: translateX(0); }
  .nav-links li { width: 100%; border-bottom: 1px solid var(--color-border); }
  .nav-links a { display: block; padding: 0.8rem 0.1rem; font-size: 0.92rem; }
  .nav-cta { border: none !important; margin-top: 0.3rem; }
  .nav-toggle { display: block; }
  .nav-right { gap: 1rem; }
  .nav-brandmark img { height: 38px; }
  .nav-name { font-size: 1.4rem; }
  .dropdown-menu {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    box-shadow: none;
    border: none;
    padding-left: 1rem;
    display: none;
  }
  .has-dropdown.is-open .dropdown-menu { display: block; }
  .dropdown-toggle { width: 100%; justify-content: space-between; padding: 0.8rem 0.1rem; font-size: 0.92rem; }
  .has-dropdown { border-bottom: 1px solid var(--color-border); }
  .has-dropdown .dropdown-menu a { border-bottom: 1px solid var(--color-border); padding: 0.65rem 0.1rem; font-size: 0.88rem; }
  .has-dropdown .dropdown-menu li:last-child a { border-bottom: none; }
  section { padding: var(--space-lg) 0; }
  /* minmax(0, 1fr) everywhere below, not bare 1fr -- see the .two-col
     comment above. A grid item's default min-width is "auto" (its own
     content's min-content size), so a plain 1fr column refuses to
     shrink past whatever text or media it holds needs, quietly running
     it off the right edge on a narrow phone instead of wrapping/scaling
     it down to fit. minmax(0, 1fr) removes that floor. */
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .hero-inner.has-photo { grid-template-columns: minmax(0, 1fr); }
  .hero-inner.has-photo .hero-photo { max-width: 320px; margin: 0 auto; }
  #communities .grid .card { flex: 1 1 100%; max-width: 100%; }
  .form-row { grid-template-columns: minmax(0, 1fr); }
  .footer-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-md); }
  .footer-bottom .container { flex-direction: column; align-items: flex-start; }
  .gallery-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-strip { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; text-align: left; }
  .hero-stats { gap: 1.25rem; }
  h1 { font-size: clamp(2.1rem, 8vw, 2.8rem); }
  .btn { width: 100%; text-align: center; }
  .hero-actions .btn { width: auto; }
  .cta-band .btn { width: auto; }

  /* Most sections (hero, testimonials, section-heads) are already
     centered on mobile; the plain text+photo two-column blocks were the
     one place still reading left-aligned once they stack to a single
     column. Centered those here (heading/paragraph text, even when a
     short list sits alongside it, like the WLH Studios block). The list
     itself always stays left-aligned for readability. Left alone
     entirely: a .card block (property-fact / listing-detail lists,
     where the list *is* the content and reads far better left-aligned
     as a title+list card) and any block with a form or iframe
     (tour-request panels), since those read worse centered. */
  .two-col > div:not(.card):not(:has(iframe)):not(:has(form)) {
    text-align: center;
  }
  .two-col > div:not(.card) ul {
    text-align: left;
  }
}

@media (max-width: 420px) {
  .gallery-grid { grid-template-columns: minmax(0, 1fr); }
  .nav-name { font-size: 1.15rem; }
  .nav-brandmark img { height: 32px; }
  .nav-right { gap: 0.75rem; }
}
