/* ========================================
   ROHT — Design System & Global Styles
   ======================================== */

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

:root {
  --navy: #262654;
  --navy-rgb: 38, 38, 84;

  /* ROHT brand palette — navy / white / gold only. Yellow and green are
     retired; Grenada no longer carries a separate accent.

     Gold is a mid-tone, so it does not behave like the 9.66:1 yellow it
     replaces. Three ramps, chosen by contrast rather than taste:
       --gold        #A88659  4.2:1 on navy, 3.4:1 on white
                              -> large text, icons, rules, borders,
                                 focus rings, gold-as-a-background
       --gold-light  #C2AA8A  6.3:1 on navy  -> small text on dark
       --gold-deep   #725A3C  6.5:1 on white -> small text on light,
                                 and solid buttons (white text on it) */
  --gold: #A88659;
  --gold-rgb: 168, 134, 89;
  --gold-light: #C2AA8A;
  --gold-deep: #725A3C;

  --white: #FFFFFF;
  --off-white: #F5F5F2;
  --light-gray: #E4E4E0;
  --mid-gray: #8A8A8A;
  --dark-gray: #2E2E2E;
  --black: #1A1A1A;

  /* Canonical scrim behind captions that sit over photography (mosaic tiles,
     journal/post/featured cards, homepage highlight + social tiles). One
     source of truth so every "text over image" caption reads identically.
     Bottom-anchored + percentage stops, so it scales to any card height.
     (Hero full-bleed photos use their own navy --hero scrim, by design.) */
  --caption-scrim: linear-gradient(to top,
    rgba(0,0,0,0.85) 0%,
    rgba(0,0,0,0.58) 30%,
    rgba(0,0,0,0.20) 62%,
    transparent 100%);
  --caption-scrim-hover: linear-gradient(to top,
    rgba(0,0,0,0.90) 0%,
    rgba(0,0,0,0.66) 35%,
    rgba(0,0,0,0.30) 70%,
    transparent 100%);

  --font-display: 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-body: 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;

  --text-xs: 0.75rem;      /* 12px */
  --text-sm: 0.875rem;     /* 14px */
  --text-base: 1rem;       /* 16px */
  --text-lg: 1.125rem;     /* 18px */
  --text-xl: 1.25rem;      /* 20px */
  --text-2xl: 1.5rem;      /* 24px */
  --text-3xl: 2rem;        /* 32px */
  --text-4xl: 2.5rem;      /* 40px */
  --text-5xl: 3.25rem;     /* 52px */
  --text-6xl: 4rem;        /* 64px */

  --leading-tight: 1.08;
  --leading-snug: 1.2;
  --leading-normal: 1.5;
  --leading-relaxed: 1.7;

  --tracking-tight: -0.025em;
  --tracking-normal: 0;
  --tracking-wide: 0.03em;
  --tracking-wider: 0.07em;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  --max-width: 1440px;
  --content-width: 1120px;
  --narrow-width: 720px;
  --gutter: 2rem;
  --section-pad: 7rem;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 200ms;
  --duration-normal: 400ms;
  --duration-slow: 600ms;

  --radius-sm: 2px;
  --radius-md: 3px;
  --radius-lg: 4px;
  --radius-xl: 6px;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base); /* 16px — web standard minimum */
  line-height: var(--leading-normal);
  color: var(--dark-gray);
  background: var(--white);
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

/* --- Typography --- */
h1, h2, h3 {
  font-family: var(--font-serif);
  font-weight: 400;
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  color: var(--dark-gray);
}

h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--dark-gray);
}

h1 { font-size: var(--text-5xl); }
h2 { font-size: var(--text-4xl); }
h3 { font-size: var(--text-3xl); }
h4 { font-size: var(--text-2xl); }
h5 { font-size: var(--text-xl); }
h6 { font-size: var(--text-lg); }

p {
  line-height: var(--leading-relaxed);
  max-width: 60ch;
}

.overline {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  line-height: 1;
  color: var(--mid-gray);
}

.subtitle {
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--mid-gray);
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.8125rem 1.75rem;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  border: 1px solid transparent;
  border-radius: 100px;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
  text-decoration: none;
  white-space: nowrap;
}

.btn-primary {
  background: var(--dark-gray);
  color: var(--white);
  border-color: var(--dark-gray);
}

.btn-primary:hover {
  background: var(--black);
  border-color: var(--black);
}

.btn-outline {
  background: transparent;
  color: var(--white);
  border-color: rgba(255,255,255,0.3);
}

.btn-outline:hover {
  background: var(--white);
  color: var(--dark-gray);
  border-color: var(--white);
}

.btn-outline-dark {
  background: transparent;
  color: var(--dark-gray);
  border-color: rgba(0,0,0,0.15);
}

.btn-outline-dark:hover {
  background: var(--dark-gray);
  color: var(--white);
  border-color: var(--dark-gray);
}

/* Solid-gold buttons: #A88659 carries only 4.2:1 against navy text and
   3.4:1 against white, and .btn's label is 12px uppercase — small text,
   so it needs 4.5:1. --gold-deep with white text gets 6.5:1 and keeps the
   gold identity. Hover resolves to navy (white on navy = 15:1) rather
   than the old transparent/coloured-text inversion, which would have put
   3.4:1 gold text on whatever surface the button happened to sit on. */
.btn-gold {
  background: var(--gold-deep);
  color: var(--white);
  border-color: var(--gold-deep);
}

.btn-gold:hover {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}

.btn-sm {
  padding: 0.625rem 1.25rem;
  font-size: var(--text-xs);
}

.btn-lg {
  padding: 1rem 2.25rem;
  font-size: var(--text-xs);
}

/* --- Layout --- */
.container {
  width: 100%;
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.container-narrow { max-width: var(--narrow-width); }
.container-full { max-width: var(--max-width); }

.section { padding: var(--section-pad) 0; }
.section-sm { padding: var(--space-16) 0; }

.grid { display: grid; gap: var(--gutter); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

.flex { display: flex; }
.flex-center { align-items: center; justify-content: center; }
.flex-between { align-items: center; justify-content: space-between; }

.text-center { text-align: center; }
.text-white { color: var(--white); }
.text-navy { color: var(--navy); }
.text-gold { color: var(--gold); }

.bg-navy { background-color: var(--navy); }
.bg-white { background-color: var(--white); }
.bg-off-white { background-color: var(--off-white); }

/* --- Header --- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: var(--space-6) 0;
  transition: background var(--duration-normal) var(--ease-out),
              padding var(--duration-normal) var(--ease-out);
}

.site-header--transparent { background: transparent; }

/* Top-down scrim behind the transparent header. On the property home pages
   the header floats over the WHITE sticky property-nav, so the white logo
   and links had no contrast and only appeared once scrolling turned the
   header solid. This gradient gives them a dark backing at all times,
   fading out below the header so it reads as a soft vignette, not a bar. */
.site-header--transparent::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 160%;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(to bottom,
    rgba(0,0,0,0.55) 0%,
    rgba(0,0,0,0.28) 45%,
    rgba(0,0,0,0) 100%);
}
.site-header--transparent .container { position: relative; z-index: 1; }

.site-header--solid {
  background: var(--dark-gray);
  padding: var(--space-4) 0;
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: var(--max-width);
}

.site-logo {
  display: flex;
  align-items: center;
  gap: 0;
  color: var(--white);
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
}

.site-logo .logo-mark {
  display: none;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-10);
}

.site-nav a {
  color: rgba(255,255,255,0.5);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  transition: color var(--duration-fast) var(--ease-out);
}

.site-nav a:hover,
.site-nav a.active {
  color: var(--white);
}

.nav-book-btn {
  margin-left: var(--space-4);
  padding: 0.5rem 1.25rem;
  /* was 10px — 12px is the legibility floor; tightened tracking so the
     label still fits the same pill width */
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  min-height: auto;
}

/* --- Nav Dropdown --- */
.nav-dropdown {
  position: relative;
}

.nav-dropdown-trigger {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
}

.nav-dropdown-trigger i {
  font-size: 8px;
  opacity: 0.5;
  transition: transform var(--duration-fast);
}

.nav-dropdown:hover .nav-dropdown-trigger i {
  transform: rotate(180deg);
}

.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(16px);
  width: 320px;
  background: var(--white);
  box-shadow: 0 12px 48px rgba(0,0,0,0.15);
  padding: var(--space-3);
  opacity: 0;
  visibility: hidden;
  transition: all var(--duration-fast) var(--ease-out);
  z-index: 200;
  pointer-events: none;
}

.nav-dropdown:hover .nav-dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

/* Invisible bridge so hover doesn't break */
.nav-dropdown-menu::before {
  content: '';
  position: absolute;
  top: -20px;
  left: 0;
  right: 0;
  height: 20px;
}

.nav-drop-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4);
  transition: background var(--duration-fast);
  text-decoration: none;
}

.nav-drop-item:hover {
  background: var(--off-white);
}

.nav-drop-icon {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--mid-gray);
  font-size: var(--text-base);
  flex-shrink: 0;
  margin-top: 2px;
}

.nav-drop-item:hover .nav-drop-icon {
  color: var(--dark-gray);
}

.nav-drop-title {
  display: block;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--dark-gray);
  margin-bottom: 2px;
  letter-spacing: 0;
  text-transform: none;
}

.nav-drop-desc {
  display: block;
  font-size: var(--text-xs);
  color: var(--mid-gray);
  line-height: var(--leading-relaxed);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 400;
}

@media (max-width: 768px) {
  .nav-dropdown-menu { display: none; }
}

/* --- Property Sub-Navigation --- */
.property-nav {
  background: var(--white);
  border-bottom: 1px solid rgba(0,0,0,0.06);
  padding: 0;
  position: sticky;
  top: 72px;
  z-index: 90;
}

.property-nav .container {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  max-width: var(--max-width);
}

.property-nav a {
  display: block;
  padding: var(--space-4) 0;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--mid-gray);
  border-bottom: 1px solid transparent;
  transition: all var(--duration-fast) var(--ease-out);
}

.property-nav a:hover,
.property-nav a.active {
  color: var(--dark-gray);
  border-bottom-color: var(--dark-gray);
}

/* 12px uppercase on white — small text, so --gold-deep (6.5:1), not
   --gold (3.4:1). The rule underneath can stay full --gold. */
.property-nav--grenada a:hover,
.property-nav--grenada a.active {
  color: var(--gold-deep);
  border-bottom-color: var(--gold);
}

/* --- Footer --- */
.site-footer {
  background: var(--black);
  color: rgba(255,255,255,0.5);
  padding: var(--space-20) 0 var(--space-10);
}

/* Pre-footer tagline section */
.pre-footer-tagline {
  position: relative;
  padding: var(--space-24) 0;
  text-align: center;
  overflow: hidden;
}

.pre-footer-tagline .pft-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  z-index: 0;
}

.pre-footer-tagline .pft-left,
.pre-footer-tagline .pft-right {
  flex: 1;
  min-height: 100%;
}

.pre-footer-tagline .pft-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.55);
  z-index: 1;
}

.pre-footer-tagline .pft-content {
  position: relative;
  z-index: 3;
  max-width: 600px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.pft-text {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--text-4xl);
  color: #fff;
  margin: 0 auto var(--space-5);
  max-width: none;
  line-height: var(--leading-tight);
}

.pft-sub {
  font-size: var(--text-base);
  color: rgba(255,255,255,0.45);
  max-width: 50ch;
  margin: 0 auto var(--space-8);
  line-height: var(--leading-relaxed);
}

.pft-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
}

.pft-links a {
  color: rgba(255,255,255,0.6);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  padding: 0.75rem 1.75rem;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 100px;
  transition: all var(--duration-fast);
}

.pft-links a:hover {
  color: #fff;
  border-color: rgba(255,255,255,0.5);
  background: rgba(255,255,255,0.06);
}

.pft-links span { display: none; }

@media (max-width: 768px) {
  .pre-footer-tagline { padding: var(--space-16) 0; }
  .pft-text { font-size: var(--text-2xl); }
  .pft-sub { font-size: var(--text-sm); }
  .pft-links { flex-direction: column; gap: var(--space-3); }
  .pft-links span { display: none; }
}

.footer-newsletter {
  padding-bottom: var(--space-12);
  margin-bottom: var(--space-12);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
}

.footer-newsletter .nl-text h4 {
  color: var(--white);
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--text-lg);
  font-weight: 400;
  margin-bottom: 2px;
}

.footer-newsletter .nl-text p {
  font-size: var(--text-xs);
  color: rgba(255,255,255,0.3);
  margin: 0;
}

.footer-newsletter .nl-form {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

.footer-newsletter .nl-input {
  width: 240px;
  padding: 11px 16px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 100px;
  color: var(--white);
  font-size: var(--text-sm);
  font-family: inherit;
  outline: none;
  transition: border-color var(--duration-fast);
}

.footer-newsletter .nl-input::placeholder {
  color: rgba(255,255,255,0.2);
}

.footer-newsletter .nl-input:focus {
  border-color: rgba(255,255,255,0.2);
}

.footer-newsletter .nl-btn {
  padding: 11px 20px;
  background: rgba(255,255,255,0.08);
  color: rgba(255,255,255,0.6);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 100px;
  font-size: var(--text-xs); /* was 10px */
  font-weight: 500;
  letter-spacing: var(--tracking-wide); /* tightened to hold the button width */
  text-transform: uppercase;
  cursor: pointer;
  font-family: inherit;
  transition: all var(--duration-fast);
  white-space: nowrap;
}

.footer-newsletter .nl-btn:hover {
  background: var(--white);
  color: var(--navy);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-16);
  padding-bottom: var(--space-12);
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.footer-property h4 {
  color: var(--white);
  font-size: var(--text-base);
  font-weight: 400;
  margin-bottom: var(--space-4);
}

.footer-property .overline {
  color: rgba(255,255,255,0.25);
  margin-bottom: var(--space-5);
}

.footer-property p {
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  line-height: var(--leading-relaxed);
}

.footer-property a {
  transition: color var(--duration-fast) var(--ease-out);
}

.footer-property a:hover { color: var(--white); }

.footer-social {
  display: flex;
  gap: var(--space-4);
  margin-top: var(--space-5);
}

.footer-social a {
  color: rgba(255,255,255,0.25);
  font-size: 14px;
  transition: color var(--duration-fast);
}

.footer-social a:hover { color: var(--white); }

/* Footer contact icons */
.footer-property p i {
  width: 14px;
  text-align: center;
  margin-right: var(--space-2);
  font-size: var(--text-xs);
  opacity: 0.4;
}

.footer-legal {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding-top: var(--space-6);
  padding-bottom: var(--space-3);
}

.footer-legal a {
  font-size: var(--text-xs); /* was 10px */
  letter-spacing: var(--tracking-wide);
  color: rgba(255,255,255,0.2);
  transition: color var(--duration-fast);
}

.footer-legal a:hover { color: rgba(255,255,255,0.5); }

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--space-3);
  font-size: var(--text-xs); /* was 10px */
  color: rgba(255,255,255,0.15);
}

/* --- Map Embed --- */
.map-section {
  padding: var(--section-pad) 0;
}

.map-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
}

.map-block {
  position: relative;
  overflow: hidden;
}

.map-block .map-frame {
  aspect-ratio: 16/10;
  position: relative;
  background: #EAEAE7;
  overflow: hidden;
}

.map-block .map-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
}

.map-block .map-frame .map-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(0,0,0,0.12);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
}

.map-block .map-info {
  padding: var(--space-5) 0;
}

.map-block .map-info h5 {
  font-size: var(--text-sm);
  font-weight: 400;
  margin-bottom: var(--space-1);
}

.map-block .map-info p {
  font-size: var(--text-xs);
  color: var(--mid-gray);
}

/* Full-width single map */
.map-full {
  aspect-ratio: 21/9;
  position: relative;
  background: #EAEAE7;
  overflow: hidden;
}

.map-full iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
}

.map-full .map-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(0,0,0,0.12);
  font-size: var(--text-xs);
}

@media (max-width: 768px) {
  .map-grid { grid-template-columns: 1fr; }
  .map-full { aspect-ratio: 16/10; }
}

/* --- Image Placeholder — Photographic feel --- */
.img-placeholder {
  overflow: hidden;
  position: relative;
  color: transparent;
  font-size: 0;
  background: #3a4a5c;
  background-image:
    radial-gradient(ellipse at 30% 70%, rgba(255,255,255,0.08) 0%, transparent 60%),
    radial-gradient(ellipse at 80% 20%, rgba(0,0,0,0.15) 0%, transparent 50%),
    linear-gradient(160deg, #2c3e50 0%, #3a4a5c 40%, #34495e 100%);
}

.img-placeholder--dark {
  background: #1e2a3a;
  background-image:
    radial-gradient(ellipse at 40% 80%, rgba(255,255,255,0.05) 0%, transparent 50%),
    linear-gradient(145deg, #1a2332 0%, #2c3e50 100%);
}

.img-placeholder--grenada {
  background: #2A3F5C;
  background-image:
    radial-gradient(ellipse at 60% 30%, rgba(var(--gold-rgb), 0.05) 0%, transparent 50%),
    radial-gradient(ellipse at 20% 80%, rgba(var(--navy-rgb), 0.20) 0%, transparent 50%),
    linear-gradient(160deg, #1E3A5F 0%, #2A3F5C 40%, #1A2744 100%);
}

/* --- Media — Real photography ---------------------------------------
   .media is the drop-in replacement for .img-placeholder. It keeps the
   same box (the sizing class still supplies aspect-ratio / min-height)
   and clips a cover-fitted <img> to it.

   The placeholder gradient is retained underneath as the loading colour,
   so a slow or failed image still reads as an intentional dark panel
   rather than a white gap. --grenada is a deeper navy variant (it used to
   be green; green is retired from the palette).                          */
.media {
  position: relative;
  overflow: hidden;
  background: #2c3e50;
  background-image: linear-gradient(160deg, #2c3e50 0%, #3a4a5c 40%, #34495e 100%);
}

.media--grenada {
  background: #1E3A5F;
  background-image: linear-gradient(160deg, #1E3A5F 0%, #2A3F5C 40%, #1A2744 100%);
}

/* The <img> is absolutely filled rather than flow-sized: every slot in
   this design already carries its own aspect-ratio or min-height from
   its sizing class, and absolute positioning makes the fit independent
   of whether that box resolves a percentage height. It also lets the
   existing overlay/label siblings stack above the photo for free. */
.media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  z-index: 0;
}

/* For slots where .media itself must be the absolutely-filled layer
   (hero backgrounds, quote bands, full-bleed panels). */
.media--fill { position: absolute; inset: 0; }

/* Focal-point nudges, for shots whose subject sits off-centre. */
.media--top    > img { object-position: center 25%; }
.media--bottom > img { object-position: center 75%; }

/* --- Ken Burns -------------------------------------------------------
   Slow, continuous scale + pan on stills, so full-bleed photography
   carries some of the motion the ambient video slots were meant to.
   Applied to the <img> inside .media.

   Kept deliberately subtle: 8% travel over 20-28s, alternating so it
   never snaps back. Disabled entirely under prefers-reduced-motion.    */
@keyframes kb-in    { from { transform: scale(1.00) translate3d(0, 0, 0); }
                      to   { transform: scale(1.08) translate3d(0, -1.5%, 0); } }
@keyframes kb-out   { from { transform: scale(1.08) translate3d(0, -1.5%, 0); }
                      to   { transform: scale(1.00) translate3d(0, 0, 0); } }
@keyframes kb-left  { from { transform: scale(1.09) translate3d(2.5%, 0, 0); }
                      to   { transform: scale(1.09) translate3d(-2.5%, 0, 0); } }
@keyframes kb-right { from { transform: scale(1.09) translate3d(-2.5%, 0, 0); }
                      to   { transform: scale(1.09) translate3d(2.5%, 0, 0); } }

.kb > img {
  animation: kb-in 24s ease-in-out infinite alternate;
  will-change: transform;
  transform-origin: center;
}

.kb--out > img   { animation-name: kb-out; }
.kb--left > img  { animation-name: kb-left; animation-duration: 28s; }
.kb--right > img { animation-name: kb-right; animation-duration: 28s; }
.kb--slow > img  { animation-duration: 34s; }

/* Ken Burns on a hero must not fight the scroll-reveal transform —
   heroes are above the fold and never carry [data-animate]. Where a
   revealed element does use .kb, the animation only starts once the
   reveal has finished. */
[data-animate].kb > img { animation-play-state: paused; }
[data-animate].is-visible.kb > img { animation-play-state: running; }

@media (prefers-reduced-motion: reduce) {
  .kb > img { animation: none !important; transform: none !important; }
}

/* --- Photography pending ---------------------------------------------
   Used only where the client has supplied no honest image for the slot
   (Grenada rooms + restaurant interiors). Deliberately legible rather
   than a silent grey box, so the gap is obvious in client review.      */
.photo-pending {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-6);
  background: #1E3A5F;
  background-image:
    repeating-linear-gradient(135deg,
      rgba(255,255,255,0.02) 0px, rgba(255,255,255,0.02) 12px,
      transparent 12px, transparent 24px),
    linear-gradient(160deg, #1E3A5F 0%, #2A3F5C 40%, #1A2744 100%);
}

.photo-pending::after {
  content: attr(data-pending);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.35);
  line-height: var(--leading-relaxed);
  max-width: 24ch;
}

.photo-pending--marshfield {
  background-color: #2c3e50;
  background-image:
    repeating-linear-gradient(135deg,
      rgba(255,255,255,0.02) 0px, rgba(255,255,255,0.02) 12px,
      transparent 12px, transparent 24px),
    linear-gradient(160deg, #2c3e50 0%, #3a4a5c 40%, #34495e 100%);
}

/* --- Annotations — Hidden by default, visible in dev mode --- */
.annotation {
  position: relative;
  border: none;
  padding: 0;
}

.annotation::before {
  display: none;
}

/* --- Card --- */
.card {
  background: transparent;
  overflow: hidden;
}

.card-img {
  aspect-ratio: 16/10;
  overflow: hidden;
}

.card-body {
  padding: var(--space-5) 0;
}

.card-body h5 { margin-bottom: var(--space-2); }
.card-body p { font-size: var(--text-sm); color: var(--mid-gray); }

/* --- Hero Sections --- */
.page-hero {
  position: relative;
  min-height: 60vh;
  display: flex;
  align-items: flex-end;
  padding: var(--space-32) 0 var(--space-16);
  overflow: hidden;
}

.page-hero--full { min-height: 100vh; align-items: center; }

.page-hero .hero-bg { position: absolute; inset: 0; z-index: 0; }
.page-hero .hero-overlay {
  position: absolute; inset: 0;
  /* Deepened for real photography: the hero eyebrow/overline sits high in
     this box, where the old ramp was still only ~0.4 navy and bright sky
     showed straight through. Measured requirement is ~0.75 alpha at the
     overline's height to hold small accent text at 4.5:1. */
  background: linear-gradient(to top,
    rgba(var(--navy-rgb), 0.92) 0%,
    rgba(var(--navy-rgb), 0.78) 45%,
    rgba(var(--navy-rgb), 0.42) 78%,
    rgba(var(--navy-rgb), 0.15) 100%);
  z-index: 1;
}
.page-hero .container { position: relative; z-index: 2; }
.page-hero .overline { color: rgba(255,255,255,0.3); margin-bottom: var(--space-5); }
.page-hero h1 { color: var(--white); margin-bottom: var(--space-5); font-family: var(--font-serif); }
.page-hero p { color: rgba(255,255,255,0.45); font-size: var(--text-base); max-width: 50ch; line-height: var(--leading-relaxed); }

/* --- Booking Bar --- */
.booking-bar {
  background: var(--white);
  box-shadow: 0 8px 40px rgba(var(--navy-rgb), 0.08);
  padding: var(--space-5) var(--space-8);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.booking-bar .field { flex: 1; padding: var(--space-2) 0; }

.booking-bar .field-label {
  display: block;
  font-size: var(--text-xs); /* was 10px */
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--mid-gray);
  margin-bottom: 2px;
}

.booking-bar .field-value {
  font-size: var(--text-sm);
  color: var(--navy);
  font-weight: 400;
}

.booking-bar .divider {
  width: 1px;
  height: 32px;
  background: rgba(0,0,0,0.06);
}

/* --- Embed Placeholder --- */
.embed-placeholder {
  border: none;
  padding: var(--space-8) var(--space-6);
  text-align: center;
  background: var(--off-white);
}

.embed-placeholder .embed-icon {
  display: none;
}

.embed-placeholder h5 { margin-bottom: var(--space-2); font-size: var(--text-sm); font-family: var(--font-display); }
.embed-placeholder p { font-size: var(--text-xs); color: var(--mid-gray); margin: 0 auto; }

/* --- Contact Info Block --- */
.contact-block {
  padding: var(--space-6);
}

.contact-block .overline {
  margin-bottom: var(--space-4);
}

.contact-block h4 { margin-bottom: var(--space-4); }

.contact-detail {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

.contact-detail .icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 3px;
}

/* ============================================================
   TESTIMONIALS — unified system (replaces cinematic/carousel/inline)
   Two treatments:
     .review-wall     — three reviews at once + aggregate rating (the anchor)
     .immersive-quote — one quote set into full-bleed photography (the break)
   ============================================================ */

/* --- Review Wall (C) --- */
.review-wall { background: var(--navy); padding: var(--section-pad) 0; }
.review-wall--light { background: var(--off-white); }

.review-wall .rw-head { text-align: center; margin-bottom: var(--space-16); }
.review-wall .rw-head h3 {
  color: var(--white); font-family: var(--font-serif);
  font-size: var(--text-4xl); font-weight: 400; margin-bottom: var(--space-3);
}
.review-wall--light .rw-head h3 { color: var(--navy); }
.review-wall .rw-agg {
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider); text-transform: uppercase;
  color: var(--gold-light);
}
.review-wall--light .rw-agg { color: var(--gold-deep); }
.review-wall .rw-agg i { color: var(--gold); }

.review-wall .rw-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5); max-width: var(--content-width); margin: 0 auto;
}
.review-wall .rw-card {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.09);
  border-top: 2px solid var(--gold);
  padding: var(--space-8) var(--space-6);
  display: flex; flex-direction: column;
}
.review-wall--light .rw-card {
  background: var(--white); border: 1px solid var(--light-gray);
  border-top: 2px solid var(--gold);
}
/* Gentle stagger for editorial rhythm; removed when the grid collapses. */
.review-wall .rw-card:nth-child(2) { transform: translateY(24px); }

.review-wall .rw-stars {
  color: var(--gold); font-size: 11px;
  letter-spacing: 1px; margin-bottom: var(--space-4);
  opacity: 0.85;
}
.review-wall .rw-quote {
  font-family: var(--font-serif); font-size: var(--text-xl);
  line-height: var(--leading-normal); color: var(--white);
  margin-bottom: var(--space-6); flex: 1;
}
.review-wall--light .rw-quote { color: var(--navy); }
.review-wall .rw-who {
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.review-wall--light .rw-who { color: var(--mid-gray); }
.review-wall .rw-src {
  display: inline-flex; align-items: center; gap: 7px; margin-top: var(--space-3);
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--gold-light);
}
.review-wall--light .rw-src { color: var(--gold-deep); }

@media (max-width: 900px) {
  .review-wall .rw-grid { grid-template-columns: 1fr; max-width: 540px; }
  .review-wall .rw-card:nth-child(2) { transform: none; }
}

/* --- Immersive Quote (B) --- */
.immersive-quote {
  position: relative; min-height: 72vh;
  display: flex; align-items: flex-end; overflow: hidden;
  background: var(--navy);
}
.immersive-quote .iq-bg { position: absolute; inset: 0; z-index: 0; }
.immersive-quote .iq-bg img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.immersive-quote .iq-scrim {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(105deg,
    rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.5) 42%,
    rgba(0,0,0,0.12) 72%, transparent 100%);
}
.immersive-quote .container {
  position: relative; z-index: 2;
  padding-top: var(--space-24); padding-bottom: var(--space-24);
}
.immersive-quote .iq-mark {
  font-family: var(--font-serif); font-size: 120px; line-height: 0.5;
  color: var(--gold); display: block; margin-bottom: var(--space-4);
}
.immersive-quote .iq-stars {
  color: var(--gold); font-size: 11px;
  letter-spacing: 2px; margin-bottom: var(--space-5);
  opacity: 0.9;
}
.immersive-quote blockquote {
  font-family: var(--font-serif); font-size: var(--text-4xl);
  line-height: var(--leading-tight); color: var(--white);
  max-width: 20ch; margin-bottom: var(--space-6); letter-spacing: -0.01em;
}
.immersive-quote .iq-who {
  font-family: var(--font-display); color: rgba(255,255,255,0.92);
  font-size: var(--text-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.immersive-quote .iq-src {
  color: var(--gold-light); margin-left: var(--space-3);
  display: inline-flex; align-items: center; gap: 6px;
}
@media (max-width: 768px) {
  .immersive-quote { min-height: 62vh; }
  .immersive-quote blockquote { font-size: var(--text-2xl); }
  .immersive-quote .iq-mark { font-size: 88px; }
  /* Vertical scrim reads better than diagonal on a narrow column. */
  .immersive-quote .iq-scrim {
    background: linear-gradient(to top,
      rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.55) 45%, rgba(0,0,0,0.15) 100%);
  }
}

/* --- Journal Promo Block --- */
.journal-promo {
  padding: var(--section-pad) 0;
  background: var(--off-white);
}

.journal-promo-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-10);
}

.journal-promo-header h3 {
  font-weight: 400;
}

.journal-promo-header a {
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--mid-gray);
  transition: color var(--duration-fast);
}

.journal-promo-header a:hover { color: var(--navy); }
.journal-promo-header a::after { content: ' \2192'; }

.journal-promo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

.jp-card {
  display: block;
  position: relative;
  overflow: hidden;
}

.jp-card .jp-img {
  aspect-ratio: 3/4;
  position: relative;
}

.jp-card .jp-img::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Deepened for real photography — the old 0.6 -> transparent ramp was
     tuned against the flat dark gradient placeholders and washes out over
     bright sky. Three stops so the falloff is gradual, not a black bar. */
  background: var(--caption-scrim);
}

.jp-card:hover .jp-img::after {
  background: linear-gradient(to top,
    rgba(0,0,0,0.88) 0%,
    rgba(0,0,0,0.62) 30%,
    rgba(0,0,0,0.28) 70%,
    rgba(0,0,0,0.10) 100%);
}

.jp-card .jp-content {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: var(--space-5);
  z-index: 2;
}

.jp-card .jp-cat {
  font-size: var(--text-xs); /* was 9px */
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: rgba(255,255,255,0.35);
  margin-bottom: var(--space-2);
  display: block;
}

.jp-card .jp-title {
  font-size: var(--text-base);
  font-weight: 400;
  color: var(--white);
  line-height: var(--leading-snug);
}

@media (max-width: 768px) {
  .journal-promo-grid {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
  .jp-card .jp-img { aspect-ratio: 16/9; }
}

/* ========================================
   LAYOUT BREAKING — Editorial Composition
   Overrides the rigid grid with asymmetry,
   overlap, varied rhythm, and visual tension.
   ======================================== */

/* --- Varied Section Rhythm ---
   Instead of uniform padding, alternate between
   tight and generous spacing to create visual pulse */

.section:nth-child(odd) { padding: var(--space-20) 0; }
.section:nth-child(even) { padding: var(--section-pad) 0; }

/* --- Asymmetric Two-Column Layouts ---
   Override even 1:1 splits with editorial proportions */

.grid-2 {
  grid-template-columns: 1fr 1fr;
}

/* Service blocks, dining venues, feature cards — offset the split */
.service-block,
.dining-venue,
.feature-card {
  grid-template-columns: 1.15fr 0.85fr;
}

.service-block:nth-child(even),
.dining-venue:nth-child(even),
.feature-card:nth-child(even) {
  grid-template-columns: 0.85fr 1.15fr;
}

/* --- Offset Card Grids ---
   3-column grids get vertical stagger instead of flat alignment */

.offerings-grid,
.event-types,
.poi-grid,
.activities-grid {
  align-items: start;
}

.offerings-grid > *:nth-child(2),
.event-types > *:nth-child(2),
.poi-grid > *:nth-child(2),
.activities-grid > *:nth-child(2) {
  transform: translateY(32px);
}

.offerings-grid > *:nth-child(3),
.event-types > *:nth-child(3),
.poi-grid > *:nth-child(3),
.activities-grid > *:nth-child(3) {
  transform: translateY(12px);
}

.offerings-grid > *:nth-child(5),
.poi-grid > *:nth-child(5) {
  transform: translateY(24px);
}

/* --- Staggered Highlight Items --- */
.highlight-item:nth-child(even) {
  padding-left: var(--space-6);
}

/* --- Pull Content Out of Container ---
   Some elements break the content-width boundary */

.quote-band,
.testimonial-cinematic {
  margin-left: calc(-50vw + 50%);
  margin-right: calc(-50vw + 50%);
  width: 100vw;
  max-width: 100vw;
}

/* --- Overlapping Sections ---
   Pull elements upward to overlap previous sections */

.booking-bar-section {
  position: relative;
  z-index: 10;
  margin-top: -32px;
}

.booking-bar-section .booking-bar {
  box-shadow: 0 4px 32px rgba(var(--navy-rgb), 0.1);
}

/* --- Feature Strip Asymmetry ---
   Alternate image sizes to break the 50/50 monotony */

.feature-card:nth-child(1) .feature-img { min-height: 65vh; }
.feature-card:nth-child(2) .feature-img { min-height: 55vh; }
.feature-card:nth-child(3) .feature-img { min-height: 70vh; }

.feature-card:nth-child(odd) .feature-text {
  padding-left: clamp(3rem, 6vw, 6rem);
  padding-right: clamp(2rem, 4vw, 4rem);
}

.feature-card:nth-child(even) .feature-text {
  padding-left: clamp(2rem, 4vw, 4rem);
  padding-right: clamp(3rem, 6vw, 6rem);
}

/* --- Image Mosaic — Break the Even Grid ---
   Variation comes from the .span-2 / .span-row spans, NOT from per-item
   heights.

   There used to be a set of `.image-mosaic > *:nth-child(n) { min-height }`
   rules here (38vw / 30vw / 26vw / 34vw). The mosaic's rows are a fixed
   track (`grid-auto-rows: 33vw`, 50vw at <=768, 45vw at <=480, declared in
   each homepage's own style block), so any min-height above that track
   pushed the item out of its row and physically on top of the row below —
   357x68px of overlap on marshfield/index at 1440, 718x68px on grenada.

   They are removed rather than converted to `minmax(33vw, auto)` because
   the row height is per-breakpoint and lives in a file this stylesheet
   cannot see; matching it here would silently desync. Keep item heights
   equal to the track and let the spans do the composition. */

.image-mosaic {
  grid-auto-rows: auto;
}

/* --- Gallery Row — Uneven Widths --- */
.gallery-row {
  grid-template-columns: 1.2fr 0.8fr 1fr 0.9fr 1.1fr;
}

/* --- Footer — Wider Left Column --- */
.footer-grid {
  grid-template-columns: 1.1fr 0.9fr;
}

/* --- Room Cards — Alternate Heights --- */
.room-card:nth-child(even) .room-img {
  min-height: 360px;
}

/* --- Contact Cards — Slight Offset --- */
.contact-card:nth-child(2) {
  margin-top: var(--space-8);
}

/* --- Journal Promo — Varied Card Heights --- */
.journal-promo-grid .jp-card:nth-child(2) .jp-img {
  aspect-ratio: 2/3;
}

/* --- Testimonial Carousel ---
   The portrait column was removed when the guest-photo wells came out;
   this rule used to be `grid-template-columns: 220px 1fr` and was the
   real cause of the collapsed 205px quote — the single remaining child
   landed in the fixed 220px track. Single column now, deliberately.
   Restore the two-column split here if guest photography ever arrives. */
.tc-slide {
  grid-template-columns: 1fr;
}

.tc-slide .tc-photo {
  margin-top: var(--space-6);
}

/* --- Diagonal Section Divider ---
   Subtle angle between some sections */

.property-highlights::before,
.journal-promo::before {
  content: '';
  display: block;
  height: 40px;
  margin-top: -40px;
  background: inherit;
  clip-path: polygon(0 100%, 100% 0, 100% 100%);
}

/* --- Floating Overline Labels ---
   Move overlines to the left margin on wide screens */

@media (min-width: 1200px) {
  .feature-card .feature-text .overline {
    position: relative;
    left: -1em;
  }
}

/* --- Map Full — Asymmetric Aspect --- */
.map-full {
  aspect-ratio: 2.5/1;
}

/* --- Hero Content Offset ---
   Pull hero text slightly left of center for editorial feel */

.page-hero .container,
.m-hero .container,
.g-hero .container {
  max-width: 1000px;
  margin-left: clamp(var(--gutter), 8vw, 10rem);
  margin-right: auto;
}

/* --- Mobile: Flatten the asymmetry --- */
@media (max-width: 1024px) {
  .service-block,
  .dining-venue,
  .feature-card,
  .feature-card:nth-child(even) {
    grid-template-columns: 1fr;
  }

  .feature-card:nth-child(1) .feature-img,
  .feature-card:nth-child(2) .feature-img,
  .feature-card:nth-child(3) .feature-img {
    min-height: 50vw;
  }

  .gallery-row {
    grid-template-columns: repeat(3, 1fr);
  }

  .page-hero .container,
  .m-hero .container,
  .g-hero .container {
    margin-left: auto;
  }

  .contact-card:nth-child(2) {
    margin-top: 0;
  }

  .tc-slide {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .offerings-grid > *:nth-child(2),
  .event-types > *:nth-child(2),
  .poi-grid > *:nth-child(2),
  .activities-grid > *:nth-child(2),
  .offerings-grid > *:nth-child(3),
  .event-types > *:nth-child(3),
  .poi-grid > *:nth-child(3),
  .activities-grid > *:nth-child(3),
  .offerings-grid > *:nth-child(5),
  .poi-grid > *:nth-child(5) {
    transform: none;
  }

  .highlight-item:nth-child(even) {
    padding-left: 0;
  }

  .booking-bar-section {
    margin-top: 0;
  }

  /* (the per-item min-height override that used to live here is gone with
     the rest of them — the mosaic's own 50vw/45vw tracks size the rows) */

  .gallery-row {
    grid-template-columns: repeat(3, 1fr);
  }

  .map-full { aspect-ratio: 16/10; }

  .property-highlights::before,
  .journal-promo::before {
    display: none;
  }

  .footer-grid {
    grid-template-columns: 1fr;
  }

  .tc-slide {
    grid-template-columns: 1fr;
  }

  .tc-slide .tc-photo {
    margin-top: 0;
  }

  .journal-promo-grid .jp-card:nth-child(2) .jp-img {
    aspect-ratio: 16/9;
  }
}

/* --- Scroll Animations --- */
[data-animate] {
  opacity: 0;
  transition-property: opacity, transform;
  transition-duration: 700ms;
  transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}

[data-animate].is-visible {
  opacity: 1;
  transform: translate(0, 0) scale(1) !important;
}

[data-animate="fade-up"]    { transform: translateY(30px); }
[data-animate="fade-down"]  { transform: translateY(-30px); }
[data-animate="fade-left"]  { transform: translateX(40px); }
[data-animate="fade-right"] { transform: translateX(-40px); }
[data-animate="fade-in"]    { transform: none; }
[data-animate="scale-up"]   { transform: scale(0.95); }
[data-animate="scale-in"]   { transform: scale(0.9); }

[data-animate="fade-up-sm"]    { transform: translateY(16px); transition-duration: 500ms; }
[data-animate="fade-left-sm"]  { transform: translateX(20px); transition-duration: 500ms; }
[data-animate="fade-right-sm"] { transform: translateX(-20px); transition-duration: 500ms; }

[data-delay="1"] { transition-delay: 100ms; }
[data-delay="2"] { transition-delay: 200ms; }
[data-delay="3"] { transition-delay: 300ms; }
[data-delay="4"] { transition-delay: 400ms; }
[data-delay="5"] { transition-delay: 500ms; }
[data-delay="6"] { transition-delay: 600ms; }

[data-animate-duration="slow"] { transition-duration: 1000ms; }
[data-animate-duration="fast"] { transition-duration: 400ms; }

@media (prefers-reduced-motion: reduce) {
  [data-animate] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* --- Responsive --- */
@media (max-width: 1024px) {
  :root {
    --section-pad: 5rem;
    --gutter: 1.5rem;
  }

  h1 { font-size: var(--text-4xl); }
  h2 { font-size: var(--text-3xl); }
  h3 { font-size: var(--text-2xl); }

  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  :root {
    --section-pad: 3.5rem;
    --gutter: 1.25rem;
  }

  h1 { font-size: var(--text-3xl); }  /* 32px — legible mobile h1 */
  h2 { font-size: var(--text-2xl); }  /* 24px */
  h3 { font-size: var(--text-xl); }   /* 20px */

  body {
    -webkit-text-size-adjust: 100%;
    font-size: var(--text-base); /* 16px floor on mobile */
  }

  .grid-2,
  .grid-3,
  .grid-4 {
    grid-template-columns: 1fr;
  }

  .footer-grid {
    grid-template-columns: 1fr;
    gap: var(--space-10);
  }

  .footer-newsletter {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }

  .footer-newsletter .nl-form {
    flex-direction: column;
  }

  .footer-newsletter .nl-input {
    width: 100%;
    border-right: 1px solid rgba(255,255,255,0.08);
  }

  .footer-legal {
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
  }

  .site-nav { display: none; }

  .site-header,
  .site-header--solid,
  .site-header--transparent {
    padding: var(--space-3) 0;
  }

  .site-header .container {
    padding: 0 var(--space-4);
  }

  .site-logo {
    font-size: 1.125rem;
  }

  .btn {
    padding: 0.875rem 1.5rem;
    font-size: var(--text-xs); /* 12px */
    min-height: 48px;
    border-radius: 100px;
  }

  .btn-sm {
    padding: 0.75rem 1.25rem;
    min-height: 44px;
    font-size: var(--text-xs);
  }

  .btn-lg {
    padding: 1rem 1.75rem;
    min-height: 52px;
    font-size: var(--text-sm); /* 14px on mobile for primary CTAs */
  }

  .booking-bar {
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-5);
    gap: 0;
  }

  .booking-bar .field {
    padding: var(--space-4) 0;
    border-bottom: 1px solid rgba(0,0,0,0.04);
  }

  .booking-bar .field:last-of-type { border-bottom: none; }
  .booking-bar .divider { display: none; }
  .booking-bar .btn { margin-top: var(--space-4); width: 100%; }

  .page-hero {
    min-height: 50vh;
    padding: var(--space-24) 0 var(--space-10);
  }

  .page-hero h1 { font-size: var(--text-3xl); line-height: 1.15; }
  .page-hero p { font-size: var(--text-base); }

  .card:hover { transform: none; }

  .site-footer { padding: var(--space-12) 0 var(--space-8); }
  .footer-property h4 { font-size: var(--text-base); }
  .footer-bottom { flex-direction: column; gap: var(--space-2); text-align: center; }

  a { -webkit-tap-highlight-color: rgba(var(--navy-rgb), 0.06); }
  .annotation { border-width: 1px; padding: var(--space-3); }
  .annotation::before { font-size: 8px; top: -9px; }
  .embed-placeholder { padding: var(--space-6) var(--space-4); }
  .contact-block { padding: var(--space-5); }

  /* Mobile property nav scroll */
  .property-nav {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .property-nav::-webkit-scrollbar { display: none; }
  .property-nav .container {
    flex-wrap: nowrap;
    min-width: max-content;
    padding-right: 40px;
  }
  .property-nav a {
    white-space: nowrap;
    font-size: var(--text-xs); /* was 11px */
    letter-spacing: var(--tracking-wide); /* keeps the track from growing */
    padding: 14px 8px;
  }
}

@media (max-width: 480px) {
  :root {
    --gutter: 1rem;
    --section-pad: 2.5rem;
  }

  h1 { font-size: var(--text-2xl); }  /* 24px minimum */
  h2 { font-size: var(--text-xl); }   /* 20px minimum */

  .container { padding: 0 var(--space-4); }

  .page-hero {
    min-height: 45vh;
    padding: var(--space-20) 0 var(--space-8);
  }

  .page-hero h1 { font-size: var(--text-2xl); }
  .page-hero p { font-size: var(--text-base); } /* 16px, not smaller */

  /* Quote wraps to ~260px at 320px wide. */
  .tc-track { min-height: 290px; }
}

@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .site-footer {
    padding-bottom: calc(var(--space-10) + env(safe-area-inset-bottom));
  }
}

/* ==========================================================================
   ACCESSIBILITY LAYER
   Added in the a11y/responsive pass. Three groups:
     A. 12px legibility floor
     B. 44x44 minimum tap targets (WCAG 2.5.5)
     C. Visible keyboard focus, motion safety, scroll affordances

   `!important` is used ONLY where the offending declaration lives in a
   page-level <style> block inside _src/*.html. Those blocks are emitted
   after this stylesheet, so specificity alone cannot win. Everything that
   originates in this file is corrected without it.
   ========================================================================== */

/* --- A. Legibility floor: nothing renders below 12px ---------------------
   Uppercase micro-labels at 9-10px were the site's most common defect.
   Tracking is pulled back from --tracking-wider to --tracking-wide on the
   worst offenders so the wider glyphs don't lengthen the label enough to
   crowd its neighbour or force a wrap. */
.overline,
.jp-card .jp-cat,
.post-category,
.post-location,
.post-date,
.rel-cat,
.jf-card .jf-meta span,
.testimonial-location,
.post-hero .meta-cat,
.post-hero .meta-loc,
.post-hero .meta-date,
.post-tags .tag-label,
.booking-bar .field-label,
.filter-btn {
  font-size: var(--text-xs) !important; /* 12px */
}

.jp-card .jp-cat,
.post-category,
.post-location,
.rel-cat,
.jf-card .jf-meta span,
.post-hero .meta-cat,
.post-hero .meta-loc,
.post-hero .meta-date {
  letter-spacing: var(--tracking-wide) !important;
}

/* --- B. Tap targets ------------------------------------------------------ */

/* Buttons. .btn was 43px tall and .btn-sm 36px — both just under the bar. */
.btn { min-height: 44px; }
.btn-sm { min-height: 44px; }

/* Header. The logo (78x24) and nav links (~77x18) were the smallest
   targets in the chrome. Growing them to 44px would push the header from
   72px to 92px and break the `top: 72px` sticky offsets that the property
   nav and journal filter bar are pinned to, so the header's own vertical
   padding is reduced by exactly the amount the children gain. Net header
   height is unchanged: 14 + 44 + 14 = 72, and solid 6 + 44 + 6 = 56. */
.site-header { padding: 14px 0; }
.site-header--solid { padding: 6px 0; }

/* Below 768 the nav is replaced by the 44px hamburger, which already sets
   the row height — restore the tighter mobile padding this block would
   otherwise override (68px header, unchanged from before this pass). */
@media (max-width: 768px) {
  .site-header,
  .site-header--solid,
  .site-header--transparent { padding: var(--space-3) 0; }
}

.site-logo,
.site-nav a,
.nav-dropdown-trigger {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.site-logo { display: flex; }
.nav-book-btn { min-height: 44px; }

/* Property sub-nav: short labels ("FAQ", "Stay") measured 32px wide. */
.property-nav a {
  min-width: 44px;
  text-align: center;
}

/* Journal category filters — 24x32 and 144x32. `button.` outranks the
   page-level `.filter-btn` rule without needing !important. */
button.filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
}

/* Footer: social icons were 12x21, legal links 67x15. */
.footer-social {
  gap: var(--space-1);
  margin-left: calc(var(--space-2) * -1); /* keep the row optically aligned */
}

.footer-social a,
.footer-legal a,
.journal-promo-header a,
.social-cta > a,
.contact-line a,
.contact-sub a,
.cross-note-inner a,
.post-back a,
.detail-value a,
.post-tags a[href] {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.footer-social a {
  justify-content: center;
  min-width: 44px;
}

.pft-links a { min-height: 44px; }

/* Newsletter field + submit were 40px and 36px tall. */
.footer-newsletter .nl-input,
.footer-newsletter .nl-btn {
  min-height: 44px;
}

/* Inactive carousel slides are only opacity:0 — they still sit in the tab
   order and the accessibility tree, so a screen reader reads every quote
   as if all four were on screen. They also sit 40px off to the right,
   which is what put .tc-body past the viewport edge at 320/390 (clipped
   by .testimonial-carousel, so never a document overflow, but noise).
   visibility is delayed by the fade duration so the transition still plays. */
.tc-slide {
  visibility: hidden;
  transition: opacity 600ms cubic-bezier(0.16,1,0.3,1),
              transform 600ms cubic-bezier(0.16,1,0.3,1),
              visibility 0s linear 600ms;
}

.tc-slide.tc-active {
  visibility: visible;
  transition: opacity 600ms cubic-bezier(0.16,1,0.3,1),
              transform 600ms cubic-bezier(0.16,1,0.3,1),
              visibility 0s linear 0s;
}

/* Narrow nav labels ("Shop", "Book") measured 37px wide. */
.site-nav a { min-width: 44px; justify-content: center; }

/* Carousel dots are a 1px rule by design. Keep the rule, but hang it in
   the middle of a 44px-tall transparent hit area instead of being the
   hit area. */
/* Hit areas now abut, so the visual gap between the rules comes from the
   44px box rather than the flex gap — keeps the original dot pitch. */
.tc-dots,
.testimonial-dots { gap: 0; }

/* The 44px dot boxes make the control row wider; stop the prev/next
   buttons being squeezed below 44px on a 320px screen. */
.tc-nav-btn { flex-shrink: 0; }

@media (max-width: 480px) {
  .tc-controls { gap: var(--space-2); }
}

.tc-dots button,
.testimonial-dots button {
  height: 44px !important;
  min-width: 44px;
  background: none !important;
  border: none;
  padding: 0;
  position: relative;
}

.tc-dots button::before,
.testimonial-dots button::before {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 24px;               /* the visible rule keeps its original length */
  top: 50%;
  height: 1px;
  background: rgba(0,0,0,0.1);
  transition: background var(--duration-fast);
}

.tc-dots button.tc-dot-active::before,
.testimonial-dots button.active::before {
  background: var(--navy);
  width: 40px;
}

/* --- C1. Visible keyboard focus -----------------------------------------
   Two concentric rings so one of them always has contrast: gold hugs the
   element (reads on the navy/black chrome and dark hero art), navy sits
   just outside it (reads on the white and off-white page surfaces).
   :focus-visible only, so mouse users see nothing. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--gold);
}

/* On the dark footer / solid header the navy ring disappears into the
   background — invert the pair so the gold is the outer ring there. */
.site-header a:focus-visible,
.site-header button:focus-visible,
.site-footer a:focus-visible,
.site-footer button:focus-visible,
.site-footer input:focus-visible,
.pre-footer-tagline a:focus-visible,
.page-hero a:focus-visible,
.page-hero button:focus-visible {
  outline-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.85);
}

/* Elements that explicitly killed their outline still need a focus ring. */
.footer-newsletter .nl-input:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* --- C2. Skip link (element injected by roht.js) -------------------------
   Off-screen until it takes focus, then it parks under the fixed header. */
.skip-link {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translate(-50%, -120%);
  z-index: 10100;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-6);
  background: var(--gold-deep); /* white on --gold-deep = 6.5:1 */
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  transition: transform var(--duration-fast) var(--ease-out);
}

.skip-link:focus {
  transform: translate(-50%, 0);
}

[data-skip-target]:focus { outline: none; }

/* --- C3. Horizontal-scroll affordance on the property nav ----------------
   The nav is intentionally wider than a phone screen and scrolls. Without
   a cue that reads as "there is more", it just looks clipped. Classic
   local/scroll background-attachment pair: the white masks ride with the
   content and uncover the shadow only at the edge that still has overflow. */
@media (max-width: 768px) {
  .property-nav {
    background-color: var(--white);
    background-image:
      linear-gradient(to right, var(--white) 40%, rgba(255,255,255,0)),
      linear-gradient(to left,  var(--white) 40%, rgba(255,255,255,0)),
      linear-gradient(to right, rgba(var(--navy-rgb),0.16), rgba(var(--navy-rgb),0)),
      linear-gradient(to left,  rgba(var(--navy-rgb),0.16), rgba(var(--navy-rgb),0));
    background-position: left center, right center, left center, right center;
    background-size: 48px 100%, 48px 100%, 26px 100%, 26px 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
    overscroll-behavior-x: contain;
  }
}

/* --- C4. Motion safety ---------------------------------------------------
   .kb and [data-animate] are already handled above; this is the blanket
   catch for the transitions declared in roht.js's injected stylesheet and
   in the per-page <style> blocks. End states are all class-driven, so
   collapsing the duration leaves everything visible, never mid-animation. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  html { scroll-behavior: auto; }
}

/* --- Photo scrims --------------------------------------------------------
   Real photography replaced the flat synthetic gradients these overlays
   were tuned against, and captions over bright sky / white clapboard
   stopped being legible. Each scrim goes darker at the baseline AND gains
   intermediate stops so the extra density reads as a gradient rather than
   a black band. The declarations these override live in the per-page
   <style> blocks in _src/, which are emitted after this file, hence
   !important. */
.mosaic-item .mosaic-label {
  /* Measured against the brightest plates in the set (clam-shack-exterior,
     boathouse-deck-blue-sky): the caption band needs ~0.85 alpha to hold
     the 18px h4 at 4.5:1, so the density is held high across the text and
     then ramped out over the top ~45% of a taller box rather than being
     cut off as a bar. */
  background: var(--caption-scrim) !important;
  padding-top: var(--space-20) !important;
}

/* The sub-caption was rgba(255,255,255,0.6) — over photography that lands
   around 2.7:1. Near-solid white keeps the hierarchy (it is still smaller
   and lighter than the h4) while clearing AA. */
.mosaic-label p {
  color: rgba(255,255,255,0.88) !important;
}

.post-card .post-img::after {
  background: var(--caption-scrim) !important;
}

.post-card:hover .post-img::after {
  background: var(--caption-scrim-hover) !important;
}

.jf-card .jf-overlay {
  background: var(--caption-scrim) !important;
}

/* --- Containing-block guard for .media ----------------------------------
   .media > img is position:absolute, so .media must stay a containing
   block. our-story.html knocks .narrative-img to `position: static` at
   <=768px, which silently hands the img to some ancestor further up.
   The doubled class (0,2,0) outranks any single-class override in a later
   stylesheet without needing !important. */
.media.media { position: relative; }
.media.media--fill { position: absolute; }

/* --- Gold accent routing by surface -------------------------------------
   Plain --gold is a mid-tone: 3.4:1 on white, 4.2:1 on navy. That clears
   the 3:1 non-text threshold (icons, rules, borders) but not the 4.5:1
   small text needs, and almost every gold accent in the page-level <style>
   blocks is a 12px uppercase overline, eyebrow or meta label. Route each to
   the ramp that clears AA on the surface it actually sits on: --gold-deep
   (6.5:1) on light, --gold-light (6.3:1) on dark. These rules target
   declarations in _src page styles that load after this file, hence
   !important. */

/* Light surfaces (white / off-white cards and text columns) -> 6.5:1 */
.card-body .overline,
.dining-text .overline,
.room-info .overline,
.info-block .overline,
.feature-text .overline,
.activity-card .overline,
.poi-card .overline,
.room-cta,
.post-location--grenada,
.faq-answer-inner a,
.info-block p a,
.sitemap-group--grenada h3 {
  color: var(--gold-deep) !important;
}

/* Dark surfaces (hero photography under the navy scrim, navy bands) -> 6.3:1 */
.g-hero .overline,
.stay-hero .overline,
.restaurant-hero .overline,
.activities-hero .overline,
.island-hero .overline,
.gallery-hero .overline,
.travel-hero .overline,
.res-hero .overline,
.faq-hero .overline,
.post-hero .meta-loc,
.scroll-hint,
.testimonial-location--grenada,
.location-band .btn-outline,
.split-side--grenada .btn-outline,
.g-hero .btn-outline,
.property-card-large--grenada .btn-outline {
  color: var(--gold-light) !important;
}
