/* One Caribbean Estates — private client area.
 *
 * Built on the tokens in styles.css. Two deliberate departures from the rest
 * of the site, both answering the brief for a softer, more considered feel:
 *
 *   --r-soft   a 2px radius on photographs instead of a hard corner. Barely
 *              visible, which is the point — at 8px or more a luxury page
 *              starts to read as a consumer app.
 *   --lift     one shared hover motion. Everything that can be picked up
 *              rises by the same 3px over the same duration, so the page
 *              feels like one object rather than a collection of effects.
 */

/* The full palette, not just this file's own additions.
 *
 * account.css is loaded beside two different stylesheets: styles.css on the
 * site pages, and property.css on the 788 server-rendered listing pages.
 * property.css defines only five tokens — ink, bone, gold, line, muted — so
 * every rule here that reached for --bg, --ink-2 or --gold-deep resolved to
 * nothing on a property page. `background: var(--bg)` with no --bg is not
 * white, it is invalid, which is why the sign-in dialog rendered as a
 * transparent panel with the page showing through it.
 *
 * Declaring the whole set here makes this file self-sufficient wherever it is
 * included. The values are identical to styles.css, so on pages that already
 * define them this changes nothing. */
:root {
  /* The site is light by design and has no dark palette. Saying so is not
     decoration: without it a phone in dark mode renders every native
     control - the Location, Budget, Bedrooms and Sort dropdowns - in the
     OS's dark styling on a cream page, and Chrome on Android may apply
     its Auto Dark Theme and algorithmically invert the whole thing.
     Declaring the scheme opts out of both. */
  color-scheme: only light;

  --ink: #191713;
  --ink-2: #2c2823;
  --bg: #ffffff;
  --bone: #f6f3ee;
  --bone-2: #efe9e0;
  --stone: #e6ded2;
  --line: #e8e1d5;
  --gold: #c9a875;
  --gold-l: #c9a875;
  --gold-deep: #a8875a;
  --muted: #857c6f;
  --muted-2: #a49a8b;
  --dark: #14130f;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  --r-soft: 2px;
  --lift: -3px;
  --dur: 0.55s;
}

/* The `hidden` attribute is a user-agent rule (display:none) and loses to any
   class that sets display. Without this, hiding the gate while signed in has
   no effect and the sign-in form sits above the account it already knows. */
[hidden] { display: none !important; }

/* ── the sign-in gate ─────────────────────────────────────────────────── */
.gate {
  min-height: calc(100vh - 96px);
  display: flex;
  align-items: center;
  background:
    radial-gradient(120% 90% at 12% 0%, rgba(201, 168, 117, 0.10), transparent 60%),
    var(--bone);
  padding: 5rem 0;
}
.gate-inner {
  width: var(--wrap);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: center;
}
.gate-copy h1 {
  font-family: "Cormorant Garamond", serif;
  font-weight: 300;
  font-size: clamp(2.6rem, 5vw, 4.1rem);
  line-height: 1.04;
  letter-spacing: -0.01em;
  margin: 0.6rem 0 0;
}
.gate-copy h1 em { font-style: italic; color: var(--gold-deep); }
.gate-lede {
  color: var(--muted);
  max-width: 34ch;
  margin: 1.5rem 0 0;
  line-height: 1.75;
}
.gate-points {
  list-style: none;
  margin: 2.2rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.gate-points li {
  position: relative;
  padding-left: 1.6rem;
  font-size: 0.9rem;
  color: var(--ink-2);
}
/* A hairline rule rather than a bullet or a tick: quieter, and it echoes the
   dividers used elsewhere on the site. */
.gate-points li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.9rem; height: 1px;
  background: var(--gold);
}

.gate-card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-soft);
  padding: clamp(1.8rem, 3vw, 2.6rem);
  box-shadow: 0 30px 70px -45px rgba(20, 19, 15, 0.45);
}
.tabs {
  display: flex;
  gap: 1.6rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.8rem;
}
.tab {
  background: none; border: 0; cursor: pointer;
  font-family: inherit;
  font-size: 0.64rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--muted-2);
  padding: 0 0 0.9rem;
  position: relative;
  transition: color var(--dur) var(--ease);
}
.tab::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px; background: var(--gold);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.tab.on { color: var(--ink); }
.tab.on::after { transform: scaleX(1); }
.tab:hover { color: var(--ink); }

.gate-card form { display: flex; flex-direction: column; gap: 1.15rem; }
.gate-card label,
#form-msg label {
  display: flex; flex-direction: column; gap: 0.45rem;
  font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--muted);
}
.gate-card input[type="email"],
.gate-card input[type="password"],
.gate-card input[type="text"],
.gate-card input[type="tel"],
#form-msg textarea {
  font-family: inherit; font-size: 0.95rem; font-weight: 300;
  color: var(--ink);
  background: transparent;
  border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0;
  padding: 0.6rem 0;
  letter-spacing: normal; text-transform: none;
  transition: border-color var(--dur) var(--ease);
}
.gate-card input:focus, #form-msg textarea:focus {
  outline: none; border-bottom-color: var(--gold);
}
.gate-card .hint, .opt {
  font-size: 0.66rem; letter-spacing: 0.02em; text-transform: none;
  color: var(--muted-2);
}
.check {
  flex-direction: row !important; align-items: flex-start; gap: 0.7rem !important;
  text-transform: none !important; letter-spacing: normal !important;
  font-size: 0.82rem !important; color: var(--muted) !important;
  line-height: 1.5;
}
.check input { margin-top: 0.25rem; accent-color: var(--gold-deep); }
/* Honeypot: reachable by a screen reader, invisible and unreachable by tab. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.submit {
  margin-top: 0.5rem;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.8rem;
  background: var(--ink); color: var(--bone);
  border: 0; border-radius: var(--r-soft);
  font-family: inherit;
  font-size: 0.64rem; letter-spacing: 0.24em; text-transform: uppercase;
  padding: 1.05rem 2rem;
  cursor: pointer;
  transition: background var(--dur) var(--ease), letter-spacing var(--dur) var(--ease);
}
.submit .ar { transition: transform var(--dur) var(--ease); }
/* Hover inverts rather than tints. Cream on mid-gold is two middle tones
   against each other — the text washed out and the button read as fading,
   which is exactly how it was described. Dark on gold is unmistakable, and
   the shift from dark-with-light to light-with-dark reads as a deliberate
   state change rather than a colour wobble. */
.submit:hover { background: var(--gold); color: var(--ink); letter-spacing: 0.28em; }
.submit:hover .ar { transform: translateX(4px); }
/* The ring was also gold, so on a gold hover it vanished into the button and
   left one shapeless block. Ink reads against both states. */
.submit:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.submit:active { background: var(--gold-deep); color: var(--ink); }

.note { font-size: 0.82rem; margin: 0; }
.note.bad { color: #9e3b2c; }
.note.good { color: #3f6b4f; }

/* ── signed in ────────────────────────────────────────────────────────── */
.acct-hero { padding: 4.5rem 0 2.2rem; background: var(--bone); }
.acct-hero h1, .acct-hero h2 {
  font-family: "Cormorant Garamond", serif;
  font-weight: 300; font-size: clamp(2.1rem, 4vw, 3.1rem);
  margin: 0.4rem 0 0;
}
.acct-sub {
  margin: 0.7rem 0 0; color: var(--muted); font-size: 0.88rem;
  display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap;
}
.lnk {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 0.78rem; color: var(--gold-deep);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}
.lnk:hover { border-bottom-color: var(--gold-deep); }

.acct-grid {
  display: grid; grid-template-columns: 1.6fr 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  padding: 3rem 0 6rem;
  align-items: start;
}
.col-head {
  display: flex; align-items: baseline; gap: 1rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.8rem; margin-bottom: 1.6rem;
}
.col-head h2 {
  font-family: "Cormorant Garamond", serif;
  font-weight: 400; font-size: 1.5rem; margin: 0;
}
.count { font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-2); }

.fav-list { display: flex; flex-direction: column; gap: 1.4rem; }
.fav {
  display: grid; grid-template-columns: 190px 1fr; gap: 1.4rem;
  align-items: center;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--line);
}
.fav:last-child { border-bottom: 0; }
.fav-media {
  display: block; overflow: hidden; border-radius: var(--r-soft);
  aspect-ratio: 3 / 2; background: var(--bone-2);
}
.fav-media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* The image moves, the frame does not — the restrained version of a
     hover zoom, and the reason the corner radius sits on the parent. */
  transform: scale(1.001);
  transition: transform 1.1s var(--ease);
}
.fav:hover .fav-media img { transform: scale(1.045); }
.fav-name {
  font-family: "Cormorant Garamond", serif;
  font-size: 1.28rem; color: var(--ink); text-decoration: none;
  line-height: 1.25;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-size: 0% 1px; background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--dur) var(--ease);
}
.fav:hover .fav-name { background-size: 100% 1px; }
.fav-loc {
  font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted-2); margin-top: 0.45rem;
}
.fav-price { margin-top: 0.6rem; font-size: 1rem; }
.fav-price .per { color: var(--muted-2); font-size: 0.8rem; }
.fav-acts { margin-top: 0.9rem; display: flex; gap: 1.3rem; }
.fav-noimg { display: block; width: 100%; height: 100%; background: var(--bone-2); }

.msg-list {
  display: flex; flex-direction: column; gap: 0.9rem;
  max-height: 340px; overflow-y: auto; margin-bottom: 1.4rem;
}
.msg { border-radius: var(--r-soft); padding: 0.85rem 1rem; font-size: 0.88rem; line-height: 1.6; }
.msg.out { background: var(--bone); margin-left: 2rem; }
.msg.in  { background: var(--dark); color: var(--bone); margin-right: 2rem; }
.msg p { margin: 0; }
.msg time { display: block; margin-top: 0.4rem; font-size: 0.66rem; color: var(--muted-2); }
#form-msg { display: flex; flex-direction: column; gap: 0.9rem; }
#form-msg textarea { border: 1px solid var(--line); border-radius: var(--r-soft); padding: 0.8rem; resize: vertical; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

.empty { color: var(--muted-2); font-size: 0.9rem; }

/* ── the heart, used on every listing card ────────────────────────────── */
.fav-btn {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(6px);
  border: 0; border-radius: 50%;
  cursor: pointer;
  opacity: 0; transform: translateY(-4px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
/* Appears on approach, but never hides once saved — a shortlist you cannot
   see is a shortlist you forget. Always visible on touch, where there is no
   hover to reveal it. */
.p-card:hover .fav-btn, .card:hover .fav-btn,
.fav-btn:focus-visible, .fav-btn.on { opacity: 1; transform: none; }
@media (hover: none) { .fav-btn { opacity: 1; transform: none; } }
.fav-btn svg { width: 17px; height: 17px; display: block; }
.fav-btn path { fill: none; stroke: var(--ink); stroke-width: 1.6; transition: fill var(--dur) var(--ease), stroke var(--dur) var(--ease); }
.fav-btn.on path { fill: var(--gold-deep); stroke: var(--gold-deep); }
.fav-btn:hover { background: #fff; }
.fav-btn.pulse { animation: heartbeat 0.5s var(--ease); }
@keyframes heartbeat {
  0% { transform: scale(1); } 40% { transform: scale(1.22); } 100% { transform: scale(1); }
}

.hdr-acct {
  font-size: 0.64rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink); text-decoration: none; margin-right: 1.4rem;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.hdr-acct:hover { border-bottom-color: var(--gold); }
.hdr:not(.solid) .hdr-acct { color: rgba(246, 243, 238, 0.9); }

@media (prefers-reduced-motion: reduce) {
  .fav-media img, .fav-btn, .submit, .tab::after, .fav-name { transition: none; }
  .fav-btn.pulse { animation: none; }
}

@media (max-width: 900px) {
  .gate-inner, .acct-grid { grid-template-columns: 1fr; }
  .fav { grid-template-columns: 130px 1fr; gap: 1rem; }
}

/* ── portfolio: map beside the listings ───────────────────────────────
   The Zillow arrangement, which works because the map is the stable thing
   and the list is what moves. Only applied from 1000px up: on a phone a
   split view gives you two cramped panes instead of one usable one, so the
   map stays a full-width panel above the results. */
.split { display: block; }
.split-map { display: none; }

@media (min-width: 1000px) {
  .split.is-open {
    display: grid;
    /* Went 44% -> 56% to make the map landscape, and that was the wrong
       trade: it bought map at the cost of the listings, which fell to two
       columns of 243px. The map is the aid, the properties are the point.
       Back to a narrow column, but taller than either previous version - so
       the map keeps its area while giving the width to the cards. Barbados
       is about as tall as it is wide, so a vertical frame holds the whole
       island as comfortably as a horizontal one did. */
    grid-template-columns: minmax(360px, 38%) 1fr;
    gap: 1.75rem;
    align-items: start;
  }
  .split.is-open .split-map {
    display: block;
    position: sticky;
    /* Clears the site header, which is fixed. */
    top: 84px;
    /* Was calc(100vh - 108px), which on a laptop ran the map past the bottom
       of the window — you could not see its lower edge or reach the zoom
       controls without the page scrolling under you. Short enough that the
       whole map is always on screen, with the page visible around it. */
    height: min(calc(100vh - 140px), 700px);
  }
  .split.is-open .split-map #map {
    height: 100%; width: 100%;
    border-radius: var(--r-soft, 2px);
    overflow: hidden;
  }
  /* Two columns of cards in the narrower half, not three. */
  .split.is-open .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* The results scroll inside their own frame rather than lengthening the
     page. With 362 listings the footer sat thousands of pixels down and
     everything below the grid — the subscribe block, the location links, the
     footer itself — was effectively unreachable.

     Same height as the map beside it, so the two read as one panel. The page
     itself is then short enough to scroll past in a flick.

     Deliberately desktop-only: a scrolling area inside a scrolling page is
     workable with a mouse and horrible on a touchscreen, where it steals the
     gesture that was meant to move the page. Below 1000px the list stays as
     it was. */
  .split.is-open .split-list {
    height: min(calc(100vh - 140px), 700px);
    overflow-y: auto;
    /* Stops a flick inside the list continuing into the page once it hits
       the end, which is what makes nested scrolling feel broken. */
    overscroll-behavior: contain;
    /* Room for the scrollbar so the last column is not clipped by it. */
    padding-right: 6px;
  }
  /* A quiet scrollbar; the default steel-grey one is louder than anything
     else on the page. */
  .split.is-open .split-list::-webkit-scrollbar { width: 8px; }
  .split.is-open .split-list::-webkit-scrollbar-track { background: transparent; }
  .split.is-open .split-list::-webkit-scrollbar-thumb {
    background: rgba(28,28,26,.16); border-radius: 4px;
  }
  .split.is-open .split-list:hover::-webkit-scrollbar-thumb {
    background: rgba(28,28,26,.28);
  }
  .split.is-open .split-list { scrollbar-width: thin; }

  /* Tells the reader the list continues below the fold, which a hard edge
     does not. */
  .split.is-open {
    position: relative;
  }
  .split.is-open::after {
    content: "";
    position: absolute;
    left: calc(38% + 1.75rem); right: 0; bottom: 0;
    height: 52px;
    background: linear-gradient(180deg, rgba(250,248,245,0), rgba(250,248,245,.95));
    pointer-events: none;
  }
}

/* Below 1000px the map is a panel above the list rather than a column. */
@media (max-width: 999px) {
  .split.is-open .split-map { display: block; }
  .split.is-open .split-map #map { height: 62vh; border-radius: var(--r-soft, 2px); }
  .split.is-open .split-list { margin-top: 1.5rem; }
}

/* Hovering a card lifts its pin, and hovering a pin lifts its card. The link
   between the two panes is the whole reason for showing them together. */
.p-card.is-hot {
  outline: 1px solid var(--gold);
  outline-offset: 3px;
}
.price-pin.is-hot span,
.leaflet-marker-icon.is-hot span {
  background: var(--gold-deep) !important;
  color: #fff !important;
  transform: scale(1.12);
  z-index: 500;
}
.price-pin span { transition: transform .35s var(--ease), background .35s var(--ease); }

/* ── property page: hero, filmstrip, features, save ───────────────────── */

/* The save control lives on the photograph. Beside the title it consumed a
   whole row and competed with the property's own name; here it costs nothing
   and sits where the eye already is. */
.stage { position: relative; }
.save {
  position: absolute; top: 16px; right: 16px; z-index: 3;
  display: inline-flex; align-items: center; gap: 0.5rem;
  background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(8px);
  border: 0; border-radius: 2px; padding: 0.6rem 0.85rem;
  font: inherit; font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink); cursor: pointer; white-space: nowrap;
  box-shadow: 0 6px 20px -8px rgba(20, 19, 15, 0.5);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.save svg { width: 16px; height: 16px; flex: none; }
.save path { fill: none; stroke: currentColor; stroke-width: 1.6;
             transition: fill var(--dur) var(--ease); }
/* The label collapses to nothing until hover, so at rest this is a quiet
   circle on the corner of the photograph rather than a button shouting at it. */
.save-t {
  max-width: 0; overflow: hidden; opacity: 0;
  transition: max-width var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.save:hover .save-t, .save:focus-visible .save-t, .save.on .save-t {
  max-width: 5rem; opacity: 1;
}
.save:hover { background: #fff; }
.save.on { color: var(--gold-deep); }
.save.on path { fill: var(--gold-deep); }
.save.on .save-t::after { content: "d"; }
.save.pulse { animation: heartbeat 0.5s var(--ease); }

.hero-btn { padding: 0; border: 0; background: none; cursor: zoom-in;
            display: block; width: 100%; }
/* A fixed frame, not the photograph's own proportions. height:auto meant a
   portrait shot rendered as a full-page column while a wide one stayed a
   letterbox, so the page changed shape listing to listing. 3:2 is the classic
   photographic ratio and holds every image to the same cinematic crop; the
   viewport cap stops it dominating a laptop screen. The uncropped original is
   one click away in the carousel. */
.hero-btn .hero {
  width: 100%; display: block; border-radius: var(--r-soft);
  aspect-ratio: 3 / 2; object-fit: cover; max-height: 68vh;
  margin: 0;
}

/* Filmstrip: one row, scrolled sideways, snapping. A grid of thumbnails makes
   a page of 40 photographs enormous; a strip keeps the whole listing on one
   screen and reads the way a gallery should. */
.strip {
  display: flex; gap: 10px; overflow-x: auto; padding: 12px 0 16px;
  scroll-snap-type: x mandatory; scrollbar-width: thin;
}
.strip::-webkit-scrollbar { height: 6px; }
.strip::-webkit-scrollbar-thumb { background: var(--stone); border-radius: 2px; }
.shot {
  flex: 0 0 clamp(150px, 21vw, 220px); aspect-ratio: 3/2;
  padding: 0; border: 0; background: var(--bone-2); cursor: zoom-in;
  overflow: hidden; border-radius: var(--r-soft); scroll-snap-align: start;
  position: relative;
}
.shot img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 0.9s var(--ease), opacity var(--dur) var(--ease);
  opacity: 0.86;
}
.shot:hover img, .shot:focus-visible img { transform: scale(1.06); opacity: 1; }

/* Key features as tiles. A dash in front of a phrase is a bullet wearing a
   different hat; a number set large is a fact you can read at a glance. */
/* Bordered tiles rather than a 1px gap over a coloured background: that trick
   paints every unused grid track, so seven features in a four-column grid left
   a filled empty cell sitting there looking like a mistake. */
/* THE SPEC BAR
   Bedrooms, bathrooms and the two areas — the facts every listing has and
   every buyer checks first. Twelve bordered tiles in one grid ran to three
   rows and most of a screen before a word about the house; these four read
   across a single line, divided by hairlines rather than boxed. */
.spec {
  list-style: none; margin: 0 0 2rem; padding: 1.1rem 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 0 2.6rem;
}
.spec-i { display: flex; flex-direction: column; gap: 0.25rem; }
.spec-v {
  font-family: "Cormorant Garamond", serif; font-size: 1.6rem;
  line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* The unit sits with its figure — "9,250 sq ft" reads as one measurement,
   where a separate caption saying "sq ft floor area" wrapped to three lines
   and read as two facts. */
.spec-v .fu {
  font-family: "Inter", sans-serif; font-size: 0.58rem; font-weight: 400;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted-2);
  margin-left: 0.35em;
}
.spec-l {
  font-size: 0.63rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted); line-height: 1.4;
}
@media (max-width: 560px) { .spec { gap: 0 1.6rem; } }

/* THE HIGHLIGHTS
   What distinguishes this property from the one next door, which is a
   different question from how many bathrooms it has — so it sits below the
   description rather than competing with it, and reads as a list rather than
   a wall of boxes. */
.hl {
  list-style: none; margin: 0 0 2.6rem; padding: 0;
  columns: 2; column-gap: 2.6rem;
}
.hl li {
  break-inside: avoid; position: relative;
  padding: 0.34rem 0 0.34rem 1.05rem;
  font-size: 0.9rem; line-height: 1.5; color: var(--ink-2);
}
.hl li::before {
  content: ""; position: absolute; left: 0; top: 0.92em;
  width: 0.42rem; height: 1px; background: var(--gold, #b8935a);
}
@media (max-width: 720px) { .hl { columns: 1; } }

/* THE FILM
   A still from the property's own gallery with a play control over it. It
   becomes the player on click; until then it is one WebP the page was
   loading anyway. */
.film {
  position: relative; margin: 0 0 2.8rem; overflow: hidden;
  border-radius: var(--r-soft); background: var(--bone-2);
  aspect-ratio: 16 / 9;
}
.film img, .film iframe {
  width: 100%; height: 100%; display: block; border: 0; object-fit: cover;
}
.film-play {
  position: absolute; inset: 0; width: 100%; border: 0; cursor: pointer;
  background: linear-gradient(rgba(20,19,15,0.05), rgba(20,19,15,0.42));
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 0.9rem; color: #f6f3ee;
  transition: background 0.9s cubic-bezier(.16,.72,.26,1);
}
.film-play svg { width: 4.6rem; height: auto; display: block; }
/* Not YouTube red. The page has one accent and this is not an exception to
   it — the mark reads as a play control from its shape alone. */
.film-play .pl-bg { fill: rgba(20,19,15,0.55); transition: fill 0.9s cubic-bezier(.16,.72,.26,1); }
.film-play .pl-ar { fill: #f6f3ee; }
.film-play span {
  font-size: 0.62rem; letter-spacing: 0.24em; text-transform: uppercase;
}
.film-play:hover { background: linear-gradient(rgba(20,19,15,0.02), rgba(20,19,15,0.3)); }
.film-play:hover .pl-bg { fill: var(--gold-deep, #a8875a); }
.film-play:focus-visible { outline: 2px solid var(--gold); outline-offset: -4px; }
@media (prefers-reduced-motion: reduce) {
  .film-play, .film-play .pl-bg { transition: none; }
}

/* Carousel */
.lb {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(12, 11, 9, 0.94);
  display: flex; align-items: center; justify-content: center;
}
.lb img { max-width: 92vw; max-height: 86vh; object-fit: contain; display: block; }
.lb-x, .lb-p, .lb-n {
  position: absolute; background: rgba(255,255,255,0.1); border: 0; color: #fff;
  cursor: pointer; width: 46px; height: 46px; border-radius: 50%;
  font-size: 1.5rem; line-height: 1; display: grid; place-items: center;
  transition: background var(--dur) var(--ease);
}
.lb-x:hover, .lb-p:hover, .lb-n:hover { background: rgba(255,255,255,0.22); }
.lb-x { top: 22px; right: 22px; }
.lb-p { left: 22px; }
.lb-n { right: 22px; }
.lb-c {
  position: absolute; bottom: 22px; left: 0; right: 0; text-align: center;
  color: rgba(255,255,255,0.62); font-size: 0.7rem; letter-spacing: 0.2em; margin: 0;
}
@media (max-width: 700px) {
  .lb-p, .lb-n { display: none; }              /* swipe instead */
}

/* The sign-in invitation */
.joinbox {
  position: fixed; inset: 0; z-index: 2100;
  background: rgba(12, 11, 9, 0.55); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 1.5rem;
}
.joinbox-card {
  position: relative; background: var(--bg); border-radius: var(--r-soft);
  padding: clamp(2rem, 4vw, 3rem); max-width: 30rem; width: 100%;
  box-shadow: 0 40px 90px -50px rgba(20, 19, 15, 0.7);
  animation: joinrise 0.5s var(--ease);
}
@keyframes joinrise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; } }
.joinbox-card h2 {
  font-family: "Cormorant Garamond", serif; font-weight: 300;
  font-size: 2.1rem; margin: 0.4rem 0 0.8rem;
}
/* Was --muted, a light grey that measured 133,124,111 on white — about
   3.5:1, below the readable threshold and visibly faint at this size.
   --ink-2 is the body colour used elsewhere on the site. */
.joinbox-lede { color: var(--ink-2); line-height: 1.75; margin: 0 0 2rem; font-size: 1rem; }
.joinbox-card .submit { display: inline-flex; text-decoration: none; }
.joinbox-alt { margin: 1.2rem 0 0; font-size: 0.85rem; color: var(--muted); }
.joinbox-alt a { color: var(--gold-deep); }
.joinbox-x {
  position: absolute; top: 14px; right: 16px; background: none; border: 0;
  font-size: 1.5rem; line-height: 1; color: var(--muted-2); cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .joinbox-card { animation: none; }
  .shot img { transition: none; }
}

/* ── property page: two columns, and the share panel ──────────────────── */
.detail { display: block; }

@media (min-width: 960px) {
  .detail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: clamp(2rem, 5vw, 4.5rem);
    align-items: start;
    margin-top: 2.6rem;
  }
  .detail-side { position: sticky; top: 92px; }
  /* Body copy is capped for readability, not stretched to fill the column —
     the whole point of the second column is that prose should not be 140
     characters wide. */
  .detail-main .desc p { max-width: 68ch; }
}

.panel-card {
  border: 1px solid var(--line);
  border-radius: var(--r-soft);
  padding: 1.6rem 1.5rem;
  background: var(--bg, #fff);
  display: flex; flex-direction: column; gap: 1rem;
}
.panel-price {
  font-family: "Cormorant Garamond", serif;
  font-size: 1.85rem; line-height: 1; margin: 0; color: var(--ink);
}
.panel-card .cta {
  display: block; text-align: center; margin: 0;
  background: var(--ink); color: var(--bone); text-decoration: none;
  border-radius: var(--r-soft); padding: 1rem 1.2rem;
  font-size: 0.64rem; letter-spacing: 0.22em; text-transform: uppercase;
  transition: background var(--dur) var(--ease), letter-spacing var(--dur) var(--ease);
}
.panel-card .cta:hover { background: var(--gold-deep); letter-spacing: 0.26em; }

.panel-save {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  background: none; border: 1px solid var(--line); border-radius: var(--r-soft);
  padding: 0.85rem 1rem; cursor: pointer; font: inherit;
  font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.panel-save svg { width: 15px; height: 15px; }
.panel-save path { fill: none; stroke: currentColor; stroke-width: 1.6;
                   transition: fill var(--dur) var(--ease); }
.panel-save:hover { border-color: var(--gold); }
.panel-save.on { color: var(--gold-deep); border-color: var(--gold-deep); }
.panel-save.on path { fill: var(--gold-deep); }
/* "Save to favourites" + "ed" read "Save to favouritesed" once saved.
   The label is swapped instead (9 Oct 2026). */
.panel-save.on .save-t { font-size: 0; }
.panel-save.on .save-t::after { content: "Saved"; font-size: 0.62rem; }
.panel-save.pulse { animation: heartbeat 0.5s var(--ease); }

.share { border-top: 1px solid var(--line); padding-top: 1.1rem; }
.share-h {
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--muted-2); margin: 0 0 0.75rem;
}
.share-row { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.share-btn {
  font: inherit; font-size: 0.74rem; color: var(--ink-2); text-decoration: none;
  background: none; border: 1px solid var(--line); border-radius: 2px;
  padding: 0.38rem 0.8rem; cursor: pointer; white-space: nowrap;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.share-btn:hover { border-color: var(--gold); color: var(--ink); }
.share-said { font-size: 0.74rem; color: var(--gold-deep); margin: 0.7rem 0 0; }

/* The map closes the page, full width beneath both columns. */
/* Height is declared here AND in assets/property.css. Both files load on
   a property page, this one second, so this is the rule that wins - the
   other looked authoritative and was doing nothing. Kept identical in
   both so the map is the same size whichever order they arrive in. */
#pmap { height: clamp(300px, 42vh, 460px); border-radius: var(--r-soft); margin-bottom: 2.5rem; }

/* The collapsing label is for the heart on the photograph. The panel button
   has room, so it keeps its words. */
.panel-save .save-t { max-width: none; opacity: 1; }

/* ── the description, collapsed ───────────────────────────────────────────
   Lost when this section was rewritten, which is why every listing was
   printing its full 2,700 characters. Collapsed, not truncated: the whole
   text stays in the document for a crawler and for anyone who opens it, and
   only its height is limited. */
/* THE DESCRIPTION'S OWN CONTENTS
   Nothing here was styled. The imported copy carries sections — "Staff List",
   "In the Area", "What Our Guests Say" — and lists of what is nearby, and
   they were rendering as plain bold lines and loose unbulleted rows: the
   structure was right and invisible, which is the same as not having it.
   Matches the section headings and lists elsewhere on the page. */
.desc h3, .desc h4 {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-weight: 400; font-size: 1.32rem; line-height: 1.2;
  color: var(--ink); margin: 2.1rem 0 0.75rem;
}
.desc h3:first-child, .desc h4:first-child { margin-top: 0; }
.desc ul, .desc ol {
  margin: 0 0 1.35rem; padding: 0; list-style: none;
}
.desc ol { counter-reset: d; }
.desc li {
  position: relative; padding: 0.24rem 0 0.24rem 1.05rem;
  line-height: 1.55;
}
.desc ul li::before {
  content: ""; position: absolute; left: 0; top: 0.86em;
  width: 0.42rem; height: 1px; background: var(--gold, #b8935a);
}
.desc ol li { counter-increment: d; }
.desc ol li::before {
  content: counter(d) "."; position: absolute; left: 0; top: 0.24rem;
  color: var(--muted); font-size: 0.82rem;
}
.desc p { margin: 0 0 1.1rem; }
.desc p:last-child { margin-bottom: 0; }

.desc.is-long { max-height: 17rem; overflow: hidden; position: relative; }
.desc.is-long::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 7rem;
  background: linear-gradient(rgba(255,255,255,0), var(--bg, #fff));
  pointer-events: none;
}
.desc.is-long.is-open { max-height: none; }
.desc.is-long.is-open::after { display: none; }
.more {
  background: none; border: 0; padding: 0; margin: 1rem 0 2.2rem; cursor: pointer;
  font: inherit; font-size: 0.64rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-deep); border-bottom: 1px solid transparent;
  transition: border-color 0.55s cubic-bezier(.16,.72,.26,1);
}
.more:hover { border-bottom-color: var(--gold-deep); }

/* ── hero paging ──────────────────────────────────────────────────────── */
.stage-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,0.86); backdrop-filter: blur(6px);
  color: var(--ink); font-size: 1.4rem; line-height: 1;
  opacity: 0; transition: opacity 0.5s cubic-bezier(.16,.72,.26,1),
                          background 0.5s cubic-bezier(.16,.72,.26,1);
}
.stage:hover .stage-nav, .stage-nav:focus-visible { opacity: 1; }
@media (hover: none) { .stage-nav { opacity: 1; } }
.stage-nav:hover { background: #fff; }
.stage-nav.prev { left: 16px; }
.stage-nav.next { right: 16px; }
.stage-count {
  position: absolute; bottom: 14px; left: 0; right: 0; text-align: center;
  margin: 0; z-index: 3; pointer-events: none;
  color: rgba(255,255,255,0.9); font-size: 0.66rem; letter-spacing: 0.22em;
  text-shadow: 0 1px 6px rgba(0,0,0,0.55);
}
/* The thumbnail of whatever the hero is showing. */
.shot.is-on { box-shadow: inset 0 0 0 2px var(--gold); }
.shot.is-on img { opacity: 1; }

/* ── related properties ───────────────────────────────────────────────── */
.rel-wrap { margin: 3.5rem 0 0; }
.rel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap; margin-bottom: 1.6rem;
}
.rel-head .sec { margin: 0; }
.rel-all {
  font-size: 0.64rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-deep); text-decoration: none; white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color 0.95s cubic-bezier(.16,.72,.26,1);
}
.rel-all:hover { border-bottom-color: var(--gold-deep); }
.rel-all .ar { transition: transform 0.95s cubic-bezier(.16,.72,.26,1); display: inline-block; }
.rel-all:hover .ar { transform: translateX(4px); }

.rel-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1.4rem;
}
.rel { text-decoration: none; color: inherit; display: block; }
.rel-ph {
  display: block; aspect-ratio: 3/2; overflow: hidden;
  border-radius: var(--r-soft); background: var(--bone-2);
  box-shadow: inset 0 0 0 1px rgba(25,23,19,.07);
}
.rel-ph img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: translateZ(0) scale(1); filter: saturate(.93) brightness(.975);
  will-change: transform; backface-visibility: hidden;
  transition: transform 1.15s cubic-bezier(.16,.72,.26,1),
              filter 1s cubic-bezier(.16,.72,.26,1);
}
/* Same behaviour as the collection cards — one hover language across the
   site, not a second one invented for the foot of a page. */
.rel:hover .rel-ph img, .rel:focus-visible .rel-ph img {
  transform: translateZ(0) scale(1.058); filter: saturate(1) brightness(1);
  transition: transform 1.9s cubic-bezier(.16,.72,.26,1),
              filter 1.5s cubic-bezier(.16,.72,.26,1);
}
.rel-noimg { display: block; width: 100%; height: 100%; background: var(--bone-2); }
.rel-loc {
  display: block; margin-top: 0.75rem;
  font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gold-deep);
}
.rel-name {
  display: block; margin: 0.3rem 0 0.35rem;
  font-family: "Cormorant Garamond", serif; font-size: 1.2rem; line-height: 1.2;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-size: 0 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size 0.95s cubic-bezier(.16,.72,.26,1);
}
.rel:hover .rel-name { background-size: 100% 1px; }
.rel-price { display: block; font-family: "Cormorant Garamond", serif; font-size: 1.05rem; }

/* ── footer ───────────────────────────────────────────────────────────
   Dark, because a page of white galleries wants a floor to land on and the
   site already used a dark footer on half its pages. The two versions are
   reconciled here rather than left to whichever stylesheet loaded last. */
.foot {
  margin-top: 5rem; background: var(--dark, #14130f);
  color: rgba(246, 243, 238, 0.66); border-top: 0;
}
/* 0.9fr, not 1.2: the brand column was reserving ~420px for a line capped at
   38ch, and the leftover went spare while the contact column was one
   character too narrow for info@onecaribbeanestates.com — which then broke
   mid-word into "…estates.co / m". The space moves to where it is needed. */
.foot-in {
  max-width: 1240px; width: 92%; margin: 0 auto;
  padding: 4rem 0 2.8rem;
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 2fr);
  gap: clamp(2rem, 5vw, 5rem);
}
.foot-mark {
  font-family: "Cormorant Garamond", serif; font-size: 1.5rem; margin: 0;
  letter-spacing: 0.02em; color: #f4efe6; text-transform: none;
}
.foot-mark span { color: var(--gold-l, #c9a875); }
/* The tagline is a signature, not body copy, so it takes the display serif in
   italic rather than the UI face. Set slightly larger than the paragraph it
   replaced and given room to breathe — at body size an italic line under a
   serif wordmark reads as an afterthought instead of a sign-off. */
.foot-tagline {
  font-family: "Cormorant Garamond", serif;
  font-style: italic; font-weight: 400;
  font-size: 1.3rem; line-height: 1.4;
  color: rgba(246, 243, 238, 0.8);
  letter-spacing: 0.015em;
  margin: 0.85rem 0 0;
  text-transform: none; text-align: left;
}

/* 38ch, not 32: the brand line is now two sentences rather than one, and at
   32ch it set as a narrow five-line column beside a much wider nav. */
.foot-line {
  color: rgba(246, 243, 238, 0.55); font-size: 0.88rem; line-height: 1.75;
  margin: 0.75rem 0 0; max-width: 38ch;
  text-transform: none; letter-spacing: normal; text-align: left;
}
/* Social row. Marks rather than a fourth column of words: the nav is already
   three columns of text, and a row of icons reads as reference information
   instead of a fifth thing to read. Inline SVG keeps the site dependency-free
   and gives the service worker nothing extra to hold in step. */
/* Scoped to .foot-brand to outrank `.foot-h { margin: 0 0 0.35rem }`, which is
   defined further down and whose shorthand would otherwise zero this out. */
.foot-brand .foot-follow-h { margin-top: 2rem; margin-bottom: 0.7rem; }
.foot-social {
  display: flex; gap: 1.15rem; align-items: center;
  list-style: none; margin: 0; padding: 0;
}
.foot-social a {
  display: block; color: rgba(246, 243, 238, 0.5);
  transition: color 0.45s cubic-bezier(.16,.72,.26,1);
}
.foot-social a:hover, .foot-social a:focus-visible { color: var(--gold-l, #c9a875); }
.foot-social svg { width: 18px; height: 18px; display: block; fill: currentColor; }

.foot-nav { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 2rem; }
.foot-nav div { display: flex; flex-direction: column; gap: 0.65rem; }
.foot-h {
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-l, #c9a875); margin: 0 0 0.35rem;
}
/* property.css styles every `nav a` as an uppercase, wide-tracked header
   link, and index.html's old .foot rule shouted everything inside it. Both
   are reset explicitly here rather than by accident. */
/* Four columns of links, the last holding Property owners above Get in
   touch. The contact details read wrong broken across lines, so that column
   takes a little more width on a wide screen and a full row on a phone. */
@media (min-width: 1000px) {
  .foot-in { grid-template-columns: minmax(0, 0.7fr) minmax(0, 2.3fr); }
  .foot-nav { grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, 1.3fr);
              row-gap: 1.4rem; }
  .foot-nav > div:not(.foot-owners):not(.foot-contact) { grid-row: span 2; }
  .foot-owners, .foot-contact { grid-column: 4; }
}
@media (max-width: 999px) {
  .foot-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-contact { grid-column: 1 / -1; }
}
.foot-contact a { white-space: nowrap; overflow-wrap: normal; }
.foot-nav a {
  color: rgba(246, 243, 238, 0.78); text-decoration: none; font-size: 0.88rem;
  text-transform: none; letter-spacing: normal; margin-left: 0;
  width: fit-content; max-width: 100%; overflow-wrap: anywhere;
  border-bottom: 1px solid transparent;
  transition: border-color 0.95s cubic-bezier(.16,.72,.26,1), color 0.95s cubic-bezier(.16,.72,.26,1);
}
.foot-nav a:hover { color: #fff; border-bottom-color: var(--gold-l, #c9a875); }

/* Privacy, Terms and Cookies moved out of the "The house" column and down to
   the base row. They were three of the twelve links making that column twice
   the height of its neighbours, and the bottom of a footer is where people
   look for them anyway. Sits opposite the copyright line, wrapping above it
   on a narrow screen. */
.foot-legal { display: inline-flex; flex-wrap: wrap; gap: 1.1rem; }
.foot-legal a {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid transparent; padding-bottom: 2px;
  transition: color .25s, border-color .25s;
}
.foot-legal a:hover { color: #fff; border-bottom-color: var(--gold-l, #c9a875); }
@media (max-width: 620px) { .foot-legal { order: 2; width: 100%; } }

.foot-base {
  max-width: 1240px; width: 92%; margin: 0 auto;
  border-top: 1px solid rgba(246, 243, 238, 0.12); padding: 1.4rem 0 3rem;
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(246, 243, 238, 0.42);
}
@media (max-width: 760px) {
  .foot-in { grid-template-columns: 1fr; }
}

/* ── subscription ─────────────────────────────────────────────────────── */
.subs { background: var(--bone); border-top: 1px solid var(--line); }
.subs-in {
  max-width: 1240px; width: 92%; margin: 0 auto; padding: 4.5rem 0 5rem;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(2.5rem, 6vw, 6rem); align-items: start;
}
.subs-copy h2 {
  font-family: "Cormorant Garamond", serif; font-weight: 300;
  font-size: clamp(1.8rem, 3.2vw, 2.6rem); line-height: 1.12;
  margin: 0.6rem 0 0; text-transform: none; letter-spacing: normal;
}
.subs-copy h2 em { font-style: italic; color: var(--gold-deep); }
/* Contrast, measured against the --bone background (#f6f3ee) rather than
   judged by eye. The palette's --muted / --muted-2 landed this block at
   3.7:1 and 2.5:1; WCAG AA wants 4.5:1 for body text, and the two worst
   offenders were the 9.6px labels and the consent notice — the smallest
   type on the page carrying the text that most has to be read. These stay
   warm greys, just dark enough to pass. */
.subs-lede {
  color: #6b6354; line-height: 1.75; margin: 1.2rem 0 0; max-width: 34ch;
  font-size: 0.95rem;
}
.subs-form { display: flex; flex-direction: column; gap: 1.5rem; }
.subs-topics { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.7rem; }
.subs-topics legend {
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: #5f5749; font-weight: 500; padding: 0; margin-bottom: 0.7rem;
}
/* Each choice is a row you can click anywhere on, not a small square you must
   hit exactly. */
.subs-topics label {
  display: flex; align-items: center; gap: 0.75rem; cursor: pointer;
  font-size: 0.94rem; color: var(--ink-2); line-height: 1.4;
}
.subs-topics input { accent-color: var(--gold-deep); width: 15px; height: 15px; flex: none; }
.subs-topics label span { transition: color 0.95s cubic-bezier(.16,.72,.26,1); }
.subs-topics label:hover span { color: var(--ink); }

.subs-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
.subs-f { display: flex; flex-direction: column; gap: 0.45rem; }
.subs-f > span {
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: #5f5749; font-weight: 500;
}
/* A bottom rule alone read as a divider, not somewhere to type — against the
   bone background there was nothing to say "field". A white ground inside a
   1px rule is unmistakably an input while staying inside the house style:
   square corners, hairline border, no shadow. */
.subs-f input {
  font-family: inherit; font-size: 0.95rem; font-weight: 400; color: var(--ink);
  background: #fff; border: 1px solid #d9d1c2;
  border-radius: 0; padding: 0.72rem 0.8rem;
  transition: border-color 0.4s cubic-bezier(.16,.72,.26,1);
}
.subs-f input::placeholder { color: #77705f; opacity: 1; }
.subs-f input:hover { border-color: #bfb49e; }
/* Focus is both a colour change and a ring: colour alone is not a sufficient
   focus indicator for anyone who cannot distinguish it. */
.subs-f input:focus {
  outline: 2px solid var(--gold); outline-offset: -2px;
  border-color: var(--gold);
}
.subs-consent {
  font-size: 0.72rem; color: #5f5749; line-height: 1.6; margin: 0; max-width: 46ch;
}
.subs-consent a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.subs-form .submit { align-self: flex-start; margin-top: 0; }
.subs-form .submit:disabled { opacity: 0.55; cursor: default; }

@media (max-width: 820px) {
  .subs-in { grid-template-columns: 1fr; padding: 3.5rem 0 4rem; }
  .subs-fields { grid-template-columns: 1fr; }
}

/* ── collection header ────────────────────────────────────────────────────
   One photograph from the highest-ranked listing, breathing.

   The movement is a single 44-second zoom that eases at both ends and
   alternates direction for ever, so it never snaps back to a start position —
   a reset is the thing that makes a slow zoom look cheap. At 44 seconds the
   image moves about a pixel a second: you register that the page is alive
   without being able to point at what moved.

   The previous version cross-faded four interiors. It read as a slideshow,
   because the eye keeps being asked to begin again on a new room. */
.sub-hero { position: relative; overflow: hidden; }
.sub-hero-media { position: absolute; inset: 0; z-index: 0; }
/* Guarded on .has-media, which is only set once a photograph has actually
   loaded. Unguarded, a page whose media layer never fills — journal has no
   listings to draw from — would lay a dark scrim over a pale band and leave
   dark text on it. */
.sub-hero.has-media .sub-hero-media::after {
  /* Without this the text sits on whatever the photograph happens to be. */
  content: ""; position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(180deg, rgba(10,12,11,.74), rgba(10,12,11,.54) 45%, rgba(10,12,11,.8));
}
.sub-hero-media img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0;
  transform: translateZ(0) scale(1.06);
  transform-origin: 50% 45%;
  will-change: transform, opacity; backface-visibility: hidden;
  transition: opacity 1.6s cubic-bezier(.16,.72,.26,1);
}
.sub-hero-media img.on {
  opacity: 1;
  animation: heroBreathe 44s cubic-bezier(.37,0,.63,1) infinite alternate;
}
@keyframes heroBreathe {
  from { transform: translateZ(0) scale(1.06); }
  to   { transform: translateZ(0) scale(1.20); }
}
/* Everything in the band sits above the photograph and is set for a dark
   ground, which the flat version never had to be. */
.sub-hero > .wrap { position: relative; z-index: 3; }
.sub-hero.has-media .eyebrow { color: var(--gold-l, #c9a875); }
.sub-hero.has-media .sub-h { color: #f6f3ee; text-shadow: 0 2px 30px rgba(0,0,0,.4); }
.sub-hero.has-media .sub-lede { color: rgba(246,243,238,.82); }
.sub-hero.has-media { border-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .sub-hero-media img.on { animation: none; transition: none; }
}

/* .eyebrow lives in styles.css, which a property page does not load, so the
   dialog's own label had no styling there and rendered as body text. */
.joinbox-card .eyebrow {
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-deep); margin: 0;
}
/* Opaque, and lifted off the page rather than floating in it. */
.joinbox-card { background: #fff; }
.joinbox { background: rgba(12, 11, 9, 0.62); }

/* ── enquiry, without an account ──────────────────────────────────────── */
.enq-wrap {
  position: fixed; inset: 0; z-index: 2100;
  background: rgba(12, 11, 9, 0.62); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 1.5rem; overflow-y: auto;
}
.enq-card {
  position: relative; background: #fff; border-radius: var(--r-soft);
  padding: clamp(1.8rem, 4vw, 2.8rem); max-width: 32rem; width: 100%;
  box-shadow: 0 40px 90px -50px rgba(20, 19, 15, 0.7);
}
.enq-card .eyebrow {
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-deep); margin: 0;
}
.enq-card h2 {
  font-family: "Cormorant Garamond", serif; font-weight: 300;
  font-size: 1.7rem; line-height: 1.2; margin: 0.5rem 0 0.7rem;
}
.enq-lede { color: var(--ink-2); font-size: 0.95rem; line-height: 1.7; margin: 0 0 1.6rem; }
.enq-x {
  position: absolute; top: 14px; right: 16px; background: none; border: 0;
  font-size: 1.5rem; line-height: 1; color: var(--muted-2); cursor: pointer;
}
#enqForm { display: flex; flex-direction: column; gap: 1.1rem; }
#enqForm label {
  display: flex; flex-direction: column; gap: 0.4rem;
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--muted);
}
#enqForm input, #enqForm textarea {
  font-family: inherit; font-size: 0.95rem; font-weight: 300; color: var(--ink);
  background: transparent; border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; padding: 0.55rem 0;
  letter-spacing: normal; text-transform: none;
  transition: border-color 0.55s cubic-bezier(.16,.72,.26,1);
}
#enqForm textarea { border: 1px solid var(--line); border-radius: var(--r-soft); padding: 0.7rem; resize: vertical; }
#enqForm input:focus, #enqForm textarea:focus { outline: none; border-bottom-color: var(--gold); }
#enqForm textarea:focus { border-color: var(--gold); }
/* The standalone enquiry page carries a select the listing dialog does not.
   Left to the browser it renders as a system dropdown in the middle of a set
   of hairline-ruled fields, which is the one control on the page that looks
   like a form rather than like the site. */
#enqForm select {
  font-family: inherit; font-size: 0.95rem; font-weight: 300; color: var(--ink);
  background: transparent; border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; padding: 0.55rem 0;
  letter-spacing: normal; text-transform: none;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  /* The chevron, drawn rather than imported: one inline SVG beats a request. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%23a8875a' stroke-width='1.2' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.2rem center;
  background-size: 10px 6px; padding-right: 1.6rem;
}
#enqForm select:focus { outline: none; border-bottom-color: var(--gold); }
/* A form on its own page wants room to breathe; in a dialog it does not. */
.enq-page { display: flex; flex-direction: column; gap: 1.6rem; max-width: 34rem; }
/* Telephone and email in the side panel were rendering as default browser
   links — blue and underlined — against a page with its own palette. */
.detail-side .panel-card a {
  color: var(--ink); text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: border-color 0.55s cubic-bezier(.16,.72,.26,1);
}
.detail-side .panel-card a:hover { border-bottom-color: var(--gold); }
#enqForm .submit { align-self: flex-start; }
#enqForm .submit:disabled { opacity: 0.55; cursor: default; }
/* The panel button is a <button> now rather than a link, so it needs the
   same reset a bare button gets nowhere else on this page. */
.panel-card button.cta { border: 0; cursor: pointer; font-family: inherit; width: 100%; }

/* "WhatsApp us": a chat with the office, quieter than Enquire beneath it. */
.detail-side .panel-card a.panel-wa {
  display: block; text-align: center; border: 1px solid var(--line);
  border-radius: var(--r-soft); padding: 0.85rem 1rem;
  font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase;
}
.detail-side .panel-card a.panel-wa:hover { border-color: var(--gold); }

/* Phone enquiry bar: price, WhatsApp, Enquire. Hidden from 960px, where the
   panel itself is sticky beside the description. */
.mbar { display: none; }
@media (max-width: 959px) {
  .mbar {
    display: flex; align-items: center; gap: 0.6rem;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    padding: 0.7rem 16px calc(0.7rem + env(safe-area-inset-bottom));
    background: var(--bg, #fff); border-top: 1px solid var(--line);
    box-shadow: 0 -6px 18px rgba(20, 19, 16, 0.06);
  }
  .mbar-price {
    flex: 1; min-width: 0; margin: 0; color: var(--ink);
    font-family: "Cormorant Garamond", serif; font-size: 1.2rem; line-height: 1.1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .mbar-per {
    display: block; margin-top: 0.15rem; font-family: Inter, system-ui, sans-serif;
    font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
  }
  .mbar-wa, .mbar-enq {
    flex: none; border-radius: var(--r-soft); padding: 0.8rem 1rem;
    font: inherit; font-size: 0.6rem; letter-spacing: 0.18em;
    text-transform: uppercase; text-decoration: none; cursor: pointer;
  }
  .mbar-wa { color: var(--ink); border: 1px solid var(--line); background: none; }
  /* Icon only once the heart joined the bar: the word did not leave room
     for the price. */
  .mbar-wa { width: 2.75rem; height: 2.75rem; padding: 0; display: grid; place-items: center; }
  .mbar-wa svg { width: 20px; height: 20px; }
  /* WhatsApp's own green, so it reads as WhatsApp at a glance (Monika,
     9 Oct 2026) - the one colour in the bar on purpose. */
  .mbar-wa { color: #25d366; }
  .mbar-wa svg { width: 22px; height: 22px; }
  .mbar-wa path { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
  .mbar-wa path.wa-fill { fill: currentColor; stroke: none; }
  .mbar-fav {
    flex: none; width: 2.6rem; height: 2.6rem; padding: 0; display: grid;
    place-items: center; background: none; border: 0; cursor: pointer; color: var(--ink);
  }
  .mbar-fav svg { width: 20px; height: 20px; }
  .mbar-fav path { fill: none; stroke: currentColor; stroke-width: 1.5; }
  .mbar-fav.on { color: var(--gold-deep, #9a7742); }
  .mbar-fav.on path { fill: currentColor; }
  .mbar-enq { color: var(--bone); background: var(--ink); border: 0; }
  /* Room so the bar never sits over the last line of the footer. */
  body:has(.mbar) { padding-bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
}

/* ── editorial pages (Advisory, About, later Hospitality) ─────────────────
   One small set of classes shared by every prose page, so a fourth page is
   markup rather than another stylesheet. Deliberately few: a section, a
   label, a lede, a column grid and a closing call. Nothing else, because the
   brief for these pages is calm and legible, not feature-rich. */
.pg { max-width: 1240px; width: 92%; margin: 0 auto; }

/* Two columns, because one was leaving half the page empty. Running text has
   to stay near 65 characters to be readable, which on a 1240px page means a
   column of prose and a void beside it. Putting the heading in the left
   margin turns that void into a margin — the same device a printed article
   uses, and the reason it does not read as unfinished. */
.pg-sec {
  padding: clamp(2.1rem, 3.6vw, 3.2rem) 0; border-top: 1px solid var(--line);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: clamp(1.2rem, 4vw, 3.5rem); align-items: start;
}
.pg-sec:first-of-type { border-top: 0; }
.pg-sec > h2, .pg-sec > .pg-h { grid-column: 1; }
.pg-sec > .pg-body, .pg-sec > .pg-lede, .pg-sec > .pg-faq,
.pg-sec > .pg-note, .pg-sec > .pg-cta { grid-column: 2; }
/* Card rows are not running text, so they take the whole measure. */
.pg-sec > .pg-cols { grid-column: 1 / -1; }

@media (max-width: 820px) {
  .pg-sec { grid-template-columns: 1fr; gap: 0.9rem; }
  .pg-sec > h2, .pg-sec > .pg-h,
  .pg-sec > .pg-body, .pg-sec > .pg-lede, .pg-sec > .pg-faq,
  .pg-sec > .pg-note, .pg-sec > .pg-cta, .pg-sec > .pg-cols { grid-column: 1; }
}

.pg-h {
  font-size: 0.64rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-deep); margin: 0 0 1.1rem; font-weight: 500;
}
.pg-sec h2 {
  font-family: "Cormorant Garamond", serif; font-weight: 300;
  font-size: clamp(1.6rem, 2.9vw, 2.1rem); line-height: 1.15;
  margin: 0 0 0.9rem; color: var(--ink);
  text-transform: none; letter-spacing: normal; max-width: 20ch;
}
/* Running text stays near 65 characters; anything wider stops being read and
   starts being scanned. */
.pg-body { max-width: 66ch; }
.pg-body p { margin: 0 0 0.8rem; line-height: 1.68; color: var(--ink-2); font-size: 1rem; }
.pg-body p:last-child { margin-bottom: 0; }
.pg-lede { font-size: 1.1rem; line-height: 1.6; color: var(--ink-2); max-width: 62ch; margin: 0; }

.pg-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(1.5rem, 2.8vw, 2.4rem); margin-top: 1.7rem;
}
.pg-item h3 {
  font-family: "Cormorant Garamond", serif; font-weight: 500; font-size: 1.35rem;
  margin: 0 0 0.7rem; color: var(--ink); letter-spacing: normal; text-transform: none;
}
.pg-item p { margin: 0; line-height: 1.65; color: var(--muted); font-size: 0.95rem; }

/* Definition list, not an accordion: five questions do not need JavaScript,
   and answers that are visible get read. */
.pg-faq { margin-top: 1.2rem; max-width: 68ch; }
.pg-faq dt {
  font-weight: 500; color: var(--ink); font-size: 1rem;
  margin-top: 1.25rem; padding-top: 1.05rem; border-top: 1px solid var(--line-soft, #eee8dd);
}
.pg-faq dt:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.pg-faq dd { margin: 0.4rem 0 0; color: var(--muted); line-height: 1.65; font-size: 0.95rem; }

.pg-note {
  margin-top: 1.6rem; padding: 1rem 1.3rem; background: var(--bone);
  border-left: 2px solid var(--gold); font-size: 0.9rem; color: var(--muted);
  line-height: 1.7; max-width: 62ch;
}
.pg-cta { display: flex; flex-wrap: wrap; gap: 1.4rem; align-items: center; margin-top: 1.6rem; }
.pg-cta .submit { margin: 0; }
.pg-cta a.lnk {
  color: var(--ink-2); font-size: 0.92rem; text-decoration: none;
  border-bottom: 1px solid var(--line); padding-bottom: 2px;
  transition: border-color 0.5s cubic-bezier(.16,.72,.26,1), color 0.5s cubic-bezier(.16,.72,.26,1);
}
.pg-cta a.lnk:hover { color: var(--ink); border-bottom-color: var(--gold); }

/* No sideways scroll, anywhere.
   The hero photograph is scaled to 1.20 by its slow zoom, and a transform
   still counts toward the scrollable area — so every page with a hero was
   about 46px wider than the window and could be dragged sideways. On a phone
   that reads as a broken layout rather than an effect.
   `clip` rather than `hidden`: hidden on html/body creates a scroll container
   and silently kills position:sticky elsewhere on the page. */
html, body { overflow-x: clip; max-width: 100%; }

/* ── cookie consent ───────────────────────────────────────────────────────
   A bar, not a modal that blocks the page. The choice is required before
   anything loads, but holding a visitor hostage behind a full-screen overlay
   is the pattern regulators single out — and it reads as distrust on a page
   selling discretion. Reject sits in the same weight of type as Accept. */
.cc {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1200;
  background: var(--dark, #14130f); color: rgba(246,243,238,0.82);
  border-top: 1px solid rgba(201,168,117,0.28);
  transform: translateY(100%); transition: transform .5s cubic-bezier(.16,.72,.26,1);
}
.cc.in { transform: none; }
.cc-in {
  max-width: 1240px; width: 92%; margin: 0 auto; padding: 1.2rem 0 1.3rem;
  display: grid; grid-template-columns: minmax(0,1fr) auto;
  gap: 1rem 2.5rem; align-items: center;
}
.cc-h {
  font-size: 0.6rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-l, #c9a875); margin: 0 0 0.4rem; font-weight: 500;
}
.cc-copy p { margin: 0; font-size: 0.88rem; line-height: 1.6; max-width: 68ch; }
.cc-copy a { color: var(--gold-l, #c9a875); }
.cc-acts { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.cc-btn {
  font-family: inherit; font-size: 0.62rem; letter-spacing: 0.2em;
  text-transform: uppercase; padding: 0.75rem 1.3rem; cursor: pointer;
  border-radius: 0; transition: .3s; white-space: nowrap;
}
.cc-ghost {
  background: transparent; color: rgba(246,243,238,0.78);
  border: 1px solid rgba(246,243,238,0.28);
}
.cc-ghost:hover { color: #fff; border-color: rgba(246,243,238,0.6); }
.cc-solid {
  background: var(--gold, #c9a875); color: #1a1509; border: 1px solid var(--gold, #c9a875);
}
.cc-solid:hover { filter: brightness(1.06); }
.cc-btn:focus-visible { outline: 2px solid var(--gold-l, #c9a875); outline-offset: 2px; }
.cc-detail {
  grid-column: 1 / -1; border-top: 1px solid rgba(246,243,238,0.14);
  padding-top: 1rem; margin-top: 0.3rem;
  display: flex; flex-direction: column; gap: 0.75rem; max-width: 76ch;
}
.cc-detail label {
  display: grid; grid-template-columns: auto minmax(0,1fr); gap: 0.7rem;
  align-items: start; font-size: 0.86rem; line-height: 1.55; cursor: pointer;
}
.cc-detail input { margin-top: 0.28rem; accent-color: var(--gold, #c9a875); }
.cc-detail strong { color: #f4efe6; font-weight: 500; }
.cc-detail .cc-btn { justify-self: start; margin-top: 0.3rem; }

@media (max-width: 760px) {
  .cc-in { grid-template-columns: 1fr; gap: 0.9rem; }
  .cc-acts { justify-content: flex-start; }
}

/* ── header submenu ────────────────────────────────────────────────
   Advisory and Journal sit under About so the top level carries only
   the three ways to browse the portfolio.

   No JavaScript. :hover opens it for a mouse, :focus-within opens it
   for a keyboard, and below 900px the whole bar is replaced by
   mobile-nav.js - which reads the <a> elements inside and flattens
   them, so the nested links appear there as ordinary menu items. The
   trigger is a <button> rather than a link precisely so it does not
   show up twice in that list. */
.msub{position:relative;display:inline-block}
.msub-t{
  font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;
  cursor:pointer;letter-spacing:inherit;text-transform:inherit;
}
.msub-p{
  position:absolute;top:calc(100% + 14px);left:50%;transform:translateX(-50%);
  display:grid;gap:2px;min-width:11rem;padding:10px 0;
  background:#fff;border:1px solid rgba(28,25,20,.10);
  box-shadow:0 18px 44px -22px rgba(28,25,20,.45);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .16s ease;
  z-index:60;text-align:left;
}
.msub:hover .msub-p,
.msub:focus-within .msub-p{opacity:1;visibility:visible;pointer-events:auto}
/* A gap between trigger and panel would close the menu as the pointer
   crosses it, so the gap is bridged rather than left open. */
.msub::after{content:"";position:absolute;top:100%;left:0;right:0;height:16px}
.msub-p a{display:block;padding:8px 18px;white-space:nowrap;
  font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;
  color:#3a352c;text-decoration:none}
.msub-p a:hover,.msub-p a:focus{background:#f6f3ee;color:#1c1914}
@media (max-width:900px){ .msub{display:none} }

/* The trigger has to look exactly like the links beside it. `.menu a` is
   defined in each page's inline <style>, which comes after this file, so
   matching it needs two classes to win on specificity rather than order. */
.menu .msub-t{white-space:nowrap;
  font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(242,237,228,.86);transition:.3s;
}
.menu .msub:hover .msub-t,
.menu .msub:focus-within .msub-t{color:#fff}
/* Inside the panel the ground is white, so the link colour flips back. */
.menu .msub-p a{color:#3a352c}
.menu .msub-p a:hover,.menu .msub-p a:focus{color:#1c1914}

/* The chevron is a real element, not ::after. .nav-item already owns its
   ::after for the hover underline - absolutely positioned at bottom:-2px -
   so a pseudo-element chevron inherited that placement and rendered as a
   small diamond under the word instead of beside it. */
.msub-c{display:inline-block;width:.32em;height:.32em;margin-left:.5em;
  vertical-align:.15em;border-right:1px solid currentColor;
  border-bottom:1px solid currentColor;transform:rotate(45deg);opacity:.55}

/* ── testimonials ──────────────────────────────────────────────────
   Two columns of real reviews. Set as quotations rather than cards:
   a border and a shadow around somebody's words makes them look like
   marketing, and the whole point of a testimonial is that it is not. */
.tqs{columns:2;column-gap:52px;margin-top:1.6rem}
.tqs:first-child{margin-top:0}  /* no lede above it since 8 Oct */
.tq{break-inside:avoid;margin:0 0 2.1rem;padding:0}
.tq blockquote{margin:0;padding:0;border:0}
.tq blockquote p{margin:0;font-size:.96rem;line-height:1.72;color:#2f2a23}
.tq blockquote p::before{content:"\201C"}
.tq blockquote p::after{content:"\201D"}
.tq figcaption{margin-top:.7rem;display:flex;flex-wrap:wrap;gap:.5rem .9rem;
  align-items:baseline}
.tq-who{font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;
  color:#1c1914}
.tq-ctx{font-size:.78rem;color:#8a8175;font-style:italic}
@media (max-width:820px){ .tqs{columns:1} }

/* .menu is a flex row: its children stretch to the row's height, so the
   plain links fill 20px while the submenu's button only fills its own 14px
   and sits 5px lower than everything beside it. Centre the trigger inside
   its wrapper rather than letting it sit on the text baseline. */
.menu .msub{display:flex;align-items:stretch}
/* The trigger must occupy the same box as the links beside it, not just be
   centred in a shorter one - so it takes their line-height rather than
   collapsing to the height of its own text. */
.menu .msub-t{display:inline-flex;align-items:center;line-height:normal;
  padding:0;height:100%}

/* The unverified-address notice. Quiet: nothing is withheld from an
   unverified account, so this is information rather than a barrier. */
.vnote{margin:0 0 1.6rem;padding:1rem 1.2rem;border-radius:2px;
  background:rgba(184,147,90,.08);border-left:2px solid var(--gold,#b8935a)}
.vnote p{margin:0 0 .7rem;font-size:.9rem;line-height:1.6;color:#3a352c}
.vnote-btn{font:inherit;font-size:.74rem;letter-spacing:.12em;
  text-transform:uppercase;background:none;border:0;padding:0 0 3px;
  border-bottom:1px solid #d8cfbe;color:#1c1914;cursor:pointer}
.vnote-btn:hover:not(:disabled){color:#b8935a;border-bottom-color:#b8935a}
.vnote-btn:disabled{opacity:.5;cursor:default}
.vnote-said{font-size:.8rem;color:#8a8175;margin-left:.7rem}

/* ── HERO FILM ─────────────────────────────────────────────────────────
   Lives here rather than inline in one page because six pages now use it.
   Clips are stacked and only ever faded IN, never out - see advance() in
   hero-film.js. Fading one out while fading the next in looks right but is
   not: two layers at half opacity leave (1-.5)squared, a quarter of whatever
   sits behind them, showing through - which here is the photograph, so every
   dissolve flashed a ghost of it. */
.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 58%;z-index:0;opacity:0;
  transition:opacity var(--hero-fade,1s) linear}
/* The first clip arrives over the photograph, which is a different kind of
   change from one clip dissolving into the next - slower, and eased, so the
   hero settles rather than snaps. */
.hero.video-on .hero-video.first-in{transition:opacity 1.6s ease}
/* Footage that already moves does not want a Ken Burns under it. */
.hero.video-on .hero-bg{animation:none}

/* And neither does the poster in the seconds before the footage arrives.
   Higher specificity than the .hero-bg rule that sets the animation, so it
   wins wherever that rule lives - some of it is inline in the page. */
.hero.film-pending .hero-bg,
.sub-hero.film-pending .sub-hero-media,
.sub-hero.film-pending .sub-hero-media img,
.chero.film-pending img{animation:none !important;transform:none !important}
/* The poster written into the page itself: shown at once, at the film's own
   scale, so the first paint is already the finished band and the footage
   lands on exactly the same frame. */
.sub-hero-media img.still{opacity:1;transition:none;animation:none;transform:none}

/* The same film in the two shorter heroes: the .sub-hero band on For Sale
   and Holiday Rentals, and .chero on the collections pages. Both already
   hold a photograph of a real listing, and that stays - it is the poster,
   it paints immediately, and it is what remains if the clip never loads or
   the visitor asked for reduced motion.

   Framed slightly higher than the home page. These bands are a third of the
   height, so centre 58% crops to sea where the full hero shows horizon. */
.sub-hero .hero-video,
.chero .hero-video{object-position:center 50%;z-index:1}
/* Framed exactly like the photograph beneath it (object-fit: cover, centre),
   so the first frame lands on the same pixels - at 45% the film sat a few
   per cent higher and the band visibly shifted when it started (10 Oct 2026). */
.sub-hero.has-media .hero-video.first-in,
.chero.video-on .hero-video.first-in{transition:opacity 1.6s ease}
/* Above the still, below the scrim and the type - both of which the two
   bands already place at higher indices. */
.sub-hero-media img{z-index:0}


/* ── Monogram in the wordmark ──────────────────────────────────────────
   Seven pages carried the words alone while For Sale, Holiday Rentals and
   the account pages carried the mark beside them, so the header changed
   shape as you moved around the site.

   Masked rather than an <img>: it takes the colour of whatever header it
   sits in — pale gold over a photograph, ink over white — and needs no
   second file at a second size. */
.logo{display:inline-flex;align-items:center;gap:12px;text-decoration:none;
  color:inherit}
.logo-mark{display:block;width:44px;height:34px;flex:0 0 auto;
  background-color:currentColor;
  -webkit-mask:url("assets/oce-monogram.webp") center / contain no-repeat;
  mask:url("assets/oce-monogram.webp") center / contain no-repeat}
/* Over a hero photograph the wordmark is pale gold, so the mark matches it
   rather than the body text colour. */
.hero .logo-mark,.sub-hero .logo-mark{background-color:var(--gold-l,#c9a875)}
@media (max-width:640px){.logo-mark{width:36px;height:28px}}

/* ── Show / hide a password ──────────────────────────────────────────
 *
 * A password field is the one input nobody can proof-read. On "create
 * account" it is worse: the rule is ten characters, so people type a phrase,
 * and a phrase is exactly the sort of thing a typo hides inside. The account
 * is then created with a password its owner does not know.
 *
 * A button, not a checkbox floating beside the field — it belongs to the
 * input and should sit inside it. Padding is added on the right so a long
 * password never slides under the control.
 */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { padding-right: 3.2rem !important; }
.pw-eye {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  background: none; border: 0; padding: .35rem .5rem; cursor: pointer;
  color: var(--muted, #8a8175); line-height: 0;
  transition: color .2s;
}
.pw-eye:hover, .pw-eye:focus-visible { color: var(--ink, #1c1914); }
.pw-eye:focus-visible { outline: 1px solid var(--gold, #c9a875); outline-offset: 2px; }
.pw-eye svg { width: 19px; height: 19px; display: block; }
/* The slash is drawn over the open eye rather than swapping icons, so the
   two states are unmistakably the same control in two positions. */
.pw-eye .pw-slash { display: none; }
.pw-eye[aria-pressed="true"] .pw-slash { display: block; }

/* ── An empty shortlist ──────────────────────────────────────────────
 * Shown to every new member the moment they create an account, which makes
 * it the most valuable empty state on the site: they have just committed
 * something and have nothing to look at. It should send them somewhere.
 */
.fav-none { padding: 2.5rem 0 1rem; max-width: 34rem; }
.fav-none-h {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.5rem; color: var(--ink, #1c1914); margin: 0 0 .5rem;
}
.fav-none-p { color: var(--muted, #6b6459); font-size: .95rem; line-height: 1.6; margin: 0 0 1.6rem; }
.fav-none-go { display: flex; flex-wrap: wrap; gap: .7rem; margin-bottom: 1.8rem; }
.fav-cta {
  display: inline-block; padding: .75rem 1.4rem; text-decoration: none;
  font-size: .72rem; letter-spacing: .15em; text-transform: uppercase;
  background: var(--gold, #c9a875); color: #1a1509; border-radius: 2px;
  transition: filter .3s;
}
.fav-cta:hover { filter: brightness(1.06); }
.fav-cta.ghost {
  background: transparent; color: var(--gold-deep, #9c7c4a);
  border: 1px solid rgba(201,168,117,.55);
}
.fav-cta.ghost:hover { background: rgba(201,168,117,.1); }
.fav-none-note { color: var(--muted, #6b6459); font-size: .85rem; line-height: 1.6; margin: 0; }
.fav-none-note a { color: var(--gold-deep, #9c7c4a); }
@media (max-width: 560px) {
  .fav-none-go { flex-direction: column; }
  .fav-cta { text-align: center; }
}


/* The same three ways back into the collection the empty shortlist offers,
   shown under a shortlist that has something on it. Set apart by a rule
   above it so it reads as a footer to the list, not another saved property. */
.fav-more {
  grid-column: 1 / -1;
  margin-top: 2.4rem; padding-top: 2rem;
  border-top: 1px solid var(--line, #e8e1d5);
}
.fav-more-h {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.5rem; margin-bottom: 1.1rem; color: var(--ink, #191713);
}

/* Forgot / reset password. */
.gate-card .lnk.forgot { display: block; margin: 14px auto 0; font-size: .78rem; }
.gate-card .pane-lede { margin: 0 0 18px; font-size: .9rem; line-height: 1.55; color: var(--muted, #5d6b6c); }
/* Inline links in the sign-in points and in FAQ answers: the text colour,
   with a gold underline, so they read as part of the sentence. */
.gate-points li a, .pg-faq dd a { color: inherit; text-decoration: underline;
  text-decoration-color: var(--gold); text-underline-offset: 3px; }
.gate-points li a:hover, .pg-faq dd a:hover { color: var(--gold-deep, #8b6938); }

/* ── Podcast panel (8 Oct 2026) ─────────────────────────────────────
   Chris's buying-in-Barbados conversation: our own thumbnail, and the
   youtube-nocookie player only once somebody presses play. Used on the
   home page, Advisory, and the buying, ownership and long-stay pages. */
.pod{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:clamp(22px,3.5vw,48px);
  align-items:center;max-width:1180px;margin:clamp(40px,6vw,72px) auto;padding:clamp(22px,3vw,36px);
  background:var(--bone);border:1px solid var(--line);border-radius:var(--r-soft)}
.pod-play{position:relative;display:block;width:100%;padding:0;border:0;background:#000;cursor:pointer;
  aspect-ratio:16/9;overflow:hidden;border-radius:var(--r-soft)}
.pod-play img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s var(--ease),opacity .3s}
.pod-play:hover img{transform:scale(1.025);opacity:.92}
.pod-btn{position:absolute;left:clamp(14px,3%,24px);bottom:clamp(14px,4%,24px);width:64px;height:64px;border-radius:50%;
  background:rgba(20,19,15,.72);border:1px solid rgba(255,255,255,.55);transition:background .3s}
.pod-btn::after{content:"";position:absolute;left:25px;top:19px;border-style:solid;border-width:13px 0 13px 21px;
  border-color:transparent transparent transparent #fff}
.pod-play:hover .pod-btn{background:var(--gold-deep)}
.pod-play:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.pod-frame{width:100%;aspect-ratio:16/9;border:0;display:block;border-radius:var(--r-soft)}
.pod-txt h2{font-family:"Cormorant Garamond",Georgia,serif;font-weight:400;font-size:clamp(1.6rem,2.6vw,2.2rem);
  line-height:1.15;margin:0 0 14px;color:var(--ink)}
.pod-txt p{color:var(--ink-2);line-height:1.65;margin:0 0 20px;font-size:1rem}
.pod-watch{display:inline-block;font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);
  text-decoration:none;border-bottom:1px solid var(--gold);padding-bottom:4px}
.pod-watch:hover{color:var(--gold-deep)}
.pod-line a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}
@media (max-width:820px){.pod{grid-template-columns:1fr;margin-left:16px;margin-right:16px;padding:18px}}

/* Continue on WhatsApp, under the account Messages form (8 Oct 2026). */
.msg-wa{margin-top:1.4rem;padding-top:1.2rem;border-top:1px solid var(--line)}
.msg-wa p{margin:0 0 .7rem;font-size:.86rem;color:var(--muted)}
.msg-wa-btn{display:inline-flex;align-items:center;gap:.55rem;padding:.75rem 1.2rem;border:1px solid var(--ink);
  color:var(--ink);text-decoration:none;font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
  border-radius:var(--r-soft);transition:background .25s,color .25s}
.msg-wa-btn::before{content:"";width:9px;height:9px;border-radius:50%;background:#25d366}
.msg-wa-btn:hover{background:var(--ink);color:#fff}
a.msub-t{text-decoration:none;cursor:pointer}

/* Five menu items since 8 Oct 2026 (For Sale, Holiday Villas, Long-Term
   Rentals, Sell With Us, About). Between the phone menu (900px) and a wide
   screen they wrapped onto two lines at 1024px, so labels never break and
   the spacing tightens on mid-size screens. */
header .nav .nav-item, nav.menu a, nav .msub-t { white-space: nowrap; }
@media (min-width: 901px) and (max-width: 1240px) {
  header .nav { gap: 1.25rem; }
  header .nav .nav-item, header .nav .msub-t.nav-item { letter-spacing: .1em; font-size: .68rem; }
  nav.menu { gap: 16px; }
  nav.menu a, nav.menu .msub-t { letter-spacing: .12em; font-size: .66rem; }
}
.hdr-actions a, .nav-actions a { white-space: nowrap; }
@media (min-width: 901px) and (max-width: 1100px) {
  header .nav { gap: .9rem; }
  header .nav .nav-item, header .nav .msub-t.nav-item { letter-spacing: .06em; font-size: .64rem; }
  nav.menu { gap: 12px; }
  nav.menu a, nav.menu .msub-t { letter-spacing: .08em; font-size: .62rem; }
  .hdr-actions, .nav-actions { gap: 14px; }
  .hdr-actions a, .nav-actions a { letter-spacing: .1em; }
}
@media (min-width: 901px) and (max-width: 980px) {
  header .nav { gap: .7rem; }
  .hdr-actions { margin-left: 18px; gap: 12px; }
  nav.menu { gap: 10px; }
}

/* Guidance under the homes on the long-stays page (8 Oct 2026). */
.lt-guide{padding:2.5rem 0 0}
.lt-guide h2{font-family:"Cormorant Garamond",Georgia,serif;font-weight:400;font-size:1.7rem;margin:1.6rem 0 .7rem;color:var(--ink)}
.lt-guide p{max-width:68ch;line-height:1.75;margin:0 0 1em;color:var(--ink-2)}
.lt-guide a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}

/* Testimonials: a swipeable rail on phones, six-then-more on wide screens
   (8 Oct 2026). */
.tq.tq-x{display:none}
.tqs.tq-rail{columns:auto;display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:4px}
.tqs.tq-rail::-webkit-scrollbar{display:none}
.tqs.tq-rail .tq{flex:0 0 86%;scroll-snap-align:start;margin:0;background:#fbf9f5;
  border:1px solid var(--line);border-radius:2px;padding:20px 18px}
.tq-ctl{display:flex;align-items:center;justify-content:center;gap:18px;margin-top:16px}
.tq-ctl[hidden]{display:none}
.tq-ctl button{width:40px;height:40px;border:1px solid var(--line);background:#fff;color:var(--ink);
  font-size:1.3rem;line-height:1;border-radius:50%;cursor:pointer}
.tq-pos{font-size:.78rem;letter-spacing:.1em;color:var(--muted);min-width:4em;text-align:center}
.tq-more{display:block;margin:1.4rem 0 0;background:none;border:1px solid var(--ink);color:var(--ink);
  font:inherit;font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;padding:13px 26px;cursor:pointer}
.tq-more:hover{background:var(--ink);color:#fff}
.tq-more[hidden]{display:none}
#testimonials > div{min-width:0}
.tqs.tq-rail{max-width:100%}
.tqs.tq-rail .tq blockquote p{white-space:normal}
.tqs.tq-rail{align-items:flex-start}
.tq-ctl{justify-content:flex-start;margin:0 0 14px}
/* Key features: a small gold dot rather than a dash (8 Oct 2026). */
.hl li::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--gold);top:.62em}
/* Sell With Us: the form follows a paragraph, so it needs the gap a heading
   would otherwise give it. */
#enquire > .enq-page { margin-top: 2.2rem; }
/* Under Send on every enquiry form (review OCE-11). Quiet: it answers a
   question, it does not ask for attention. */
.enq-privacy { margin: 0.2rem 0 0; font-size: 0.72rem; }
.enq-privacy a { color: var(--muted-2, #8a8175); text-decoration: underline;
                 text-underline-offset: 3px; }
/* Key features on a sale page: one fine gold line, white inside. */
.hl-frame { border: 1px solid var(--gold, #b8935a); border-radius: 2px;
            padding: 18px 20px; margin: 2rem 0 0; background: #fff; }
.hl-frame h3 { font-family: "Cormorant Garamond", Georgia, serif; font-weight: 400;
               font-size: 1.3rem; margin: 0 0 10px; color: var(--ink); }
.hl-frame .hl { margin: 0; }
/* Locations hub groups and Signature addresses (9 Oct 2026). */
.lgroup { margin-top: 2.6rem; }
.lgroup-h { font-size: 0.62rem; letter-spacing: 0.22em; text-transform: uppercase;
            color: var(--gold-deep, #9a7742); margin: 0 0 0.6rem;
            border-bottom: 1px solid var(--line); padding-bottom: 0.6rem; }
.lsig { margin-top: 2rem; }
.lsig-row { display: flex; flex-wrap: wrap; gap: 0.6rem 2rem; }
.lsig-row a { font-family: "Cormorant Garamond", Georgia, serif; font-size: 1.6rem;
              color: var(--ink); text-decoration: none; }
.lsig-row a:hover { color: var(--gold-deep, #9a7742); }
/* Collections hub: one photo tile per theme (Monika, 9 Oct 2026). The
   caption and named houses are real text, so the page still reads in full
   to a search engine; the houses sit quietly beneath each tile. */
.ctiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 34px 18px; }
.ctile { margin: 0; }
.ctile-ph { display: block; }
.ctile { position: relative; }
.ctile-ph img { display: block; width: 100%; height: 250px; object-fit: cover; border-radius: 2px; }
.ctile-ov { position: absolute; left: 0; right: 0; top: 0; height: 250px; border-radius: 2px;
            display: flex; flex-direction: column; justify-content: flex-end; padding: 20px 22px;
            background: linear-gradient(to top, rgba(20,19,16,.80), rgba(20,19,16,.08) 62%);
            pointer-events: none; }
.ctile-ov a { pointer-events: auto; }
.ctile-ov h2 { margin: 0 0 4px; font-family: "Cormorant Garamond", Georgia, serif; font-weight: 400;
               font-size: 1.65rem; line-height: 1.1; }
.ctile-ov h2 a { color: #fff; text-decoration: none; border: 0; }
.ctile-cap { margin: 0 0 10px; color: rgba(255,255,255,.86); font-size: .8rem; line-height: 1.45; }
.ctile-links { margin: 0; display: flex; gap: 18px; }
.ctile-links a { color: #fff; text-decoration: none; font-size: .6rem; letter-spacing: .18em;
                 text-transform: uppercase; border-bottom: 1px solid #c9a875; padding-bottom: 3px; }
.ctile-houses { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-wrap: wrap;
                gap: 2px 14px; font-size: .74rem; }
.ctile-houses li { color: var(--muted, #8a8175); }
.ctile-houses a { color: var(--muted, #8a8175); text-decoration: none; border: 0; }
.ctile-houses a:hover { color: var(--ink); }
.ctile-houses .cuo { margin-left: 4px; font-size: .64rem; color: var(--gold-deep, #9a7742); }
@media (max-width: 900px) { .ctiles { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .ctiles { grid-template-columns: 1fr; }
  .ctile-ph img, .ctile-ov { height: 220px; } }
.ctile-houses { gap: 0; }
.ctile-houses li + li::before { content: "·"; margin: 0 8px; color: var(--line-2, #c9bfae); }

/* ── Every property, by area (10 Oct 2026) ─────────────────────────────
   The listing cards are drawn in the browser; this is the same inventory as
   plain links, so a crawler can reach every property from For Sale, Holiday
   Villas and Long Stays. Closed by default: a quiet A-Z under the results. */
.hix{padding:3rem 0 0}
.hix details{border-top:1px solid var(--line,#e6e1d8);padding-top:1.5rem}
.hix summary{cursor:pointer;list-style:none;font-size:.62rem;letter-spacing:.2em;
  text-transform:uppercase;color:#b8935a;display:inline-flex;align-items:center;gap:.6rem}
.hix summary::-webkit-details-marker{display:none}
.hix summary::after{content:"+";font-size:.9rem;letter-spacing:0;line-height:1}
.hix details[open] summary::after{content:"\2212"}
.hix-cols{columns:4 220px;column-gap:2.4rem;margin-top:1.8rem}
.hix-g{break-inside:avoid;margin:0 0 1.6rem}
.hix-g h3{font-family:"Cormorant Garamond",serif;font-weight:400;font-size:1.15rem;margin:0 0 .45rem;color:var(--ink,#14130f)}
.hix-g ul{list-style:none;margin:0;padding:0}
.hix-g li{font-size:.84rem;line-height:1.75}
.hix-g a{color:rgba(20,19,15,.78);text-decoration:none;border-bottom:1px solid transparent;transition:color .3s,border-color .3s}
.hix-g a:hover{color:#14130f;border-bottom-color:#b8935a}

/* Holiday villa enquiries: arrival, departure and guests in one row
   (Monika, 10 Oct 2026). */
.enq-stay{display:grid;grid-template-columns:1fr 1fr 110px;gap:0 14px}
.enq-stay[hidden]{display:none}
@media (max-width:520px){.enq-stay{grid-template-columns:1fr 1fr}.enq-stay label:last-child{grid-column:1/-1}}

/* Price under the title on phones; the panel carries it on wider screens. */
.hprice{display:none}
@media (max-width:959px){
  .hprice{display:block;margin:.35rem 0 0;font-family:"Cormorant Garamond",serif;font-size:1.45rem;color:var(--ink)}
}

/* Readable small text (review, 10 Oct 2026). The light gold (#c9a875) on
   white measures 2.25:1 and the deep gold 3.34:1, against the 4.5:1 that
   small text needs; the grey was 4.11:1. Slightly darker shades that keep
   the same warmth: deep gold 5.28:1, grey 5.25:1 (4.75 on the bone panels).
   The light gold stays for large headings and for type on photographs and
   the dark footer, where it reads well. */
:root { --gold-deep: #86663a; --muted: #736b5f; }
.lgrid .lcard .p, .csib a, .cask a { color: #86663a; }
.hix summary { color: #86663a; }

/* Page not found (10 Oct 2026). */
.nf-search{display:flex;gap:10px;margin:22px 0 26px;max-width:520px}
.nf-search input{flex:1;font:inherit;padding:12px 14px;border:1px solid var(--line);border-radius:2px;background:#fff}
.nf-search button{font:inherit;font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;padding:0 20px;border:0;background:var(--ink);color:#fff;border-radius:2px;cursor:pointer}
.nf-links{list-style:none;padding:0;margin:0 0 24px;display:flex;flex-wrap:wrap;gap:10px 26px}
.nf-links a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}

/* Comfortable tap targets on phones (review, 10 Oct 2026): every link in the
   "every property, by area" lists and the breadcrumb trail is at least
   44px tall to a finger, without making the lists look spaced out. */
@media (max-width: 820px), (pointer: coarse) {
  .hix-g li { line-height: 1.3; }
  .hix-g a { display: inline-block; padding: 11px 0; }
  .crumbs a, nav.loc a { display: inline-block; padding: 10px 0; }
  .p-nav, .ph-nav { min-width: 44px; min-height: 44px; }
}

/* Skip to content: invisible until a keyboard user tabs onto it. */
.skip-link { position: absolute; left: 12px; top: -60px; z-index: 2000; background: var(--ink, #14130f);
  color: #fff; padding: 10px 16px; font: 500 .8rem Inter, system-ui, sans-serif; text-decoration: none;
  border-radius: 2px; transition: top .15s; }
.skip-link:focus { top: 12px; outline: 2px solid #c9a875; outline-offset: 2px; }

/* Floor plans on a listing (10 Oct 2026). */
.fplans{display:flex;flex-wrap:wrap;gap:12px;margin:6px 0 10px}
.fplans .fplan-img{display:block;max-width:100%}
.fplans .fplan-img img{max-width:100%;height:auto;border:1px solid var(--line);border-radius:2px;display:block}
.fplans .fplan-pdf{display:inline-block;padding:12px 20px;border:1px solid var(--ink);color:var(--ink);text-decoration:none;
  font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;border-radius:2px}
.fplans .fplan-pdf:hover{background:var(--ink);color:#fff}
